/usr/share/acl2-7.2dfsg/doc.lisp is in acl2-source 7.2dfsg-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398 7399 7400 7401 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 7520 7521 7522 7523 7524 7525 7526 7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 9864 9865 9866 9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 9972 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 10054 10055 10056 10057 10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072 10073 10074 10075 10076 10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097 10098 10099 10100 10101 10102 10103 10104 10105 10106 10107 10108 10109 10110 10111 10112 10113 10114 10115 10116 10117 10118 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132 10133 10134 10135 10136 10137 10138 10139 10140 10141 10142 10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173 10174 10175 10176 10177 10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 10213 10214 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 10245 10246 10247 10248 10249 10250 10251 10252 10253 10254 10255 10256 10257 10258 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 10270 10271 10272 10273 10274 10275 10276 10277 10278 10279 10280 10281 10282 10283 10284 10285 10286 10287 10288 10289 10290 10291 10292 10293 10294 10295 10296 10297 10298 10299 10300 10301 10302 10303 10304 10305 10306 10307 10308 10309 10310 10311 10312 10313 10314 10315 10316 10317 10318 10319 10320 10321 10322 10323 10324 10325 10326 10327 10328 10329 10330 10331 10332 10333 10334 10335 10336 10337 10338 10339 10340 10341 10342 10343 10344 10345 10346 10347 10348 10349 10350 10351 10352 10353 10354 10355 10356 10357 10358 10359 10360 10361 10362 10363 10364 10365 10366 10367 10368 10369 10370 10371 10372 10373 10374 10375 10376 10377 10378 10379 10380 10381 10382 10383 10384 10385 10386 10387 10388 10389 10390 10391 10392 10393 10394 10395 10396 10397 10398 10399 10400 10401 10402 10403 10404 10405 10406 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 10420 10421 10422 10423 10424 10425 10426 10427 10428 10429 10430 10431 10432 10433 10434 10435 10436 10437 10438 10439 10440 10441 10442 10443 10444 10445 10446 10447 10448 10449 10450 10451 10452 10453 10454 10455 10456 10457 10458 10459 10460 10461 10462 10463 10464 10465 10466 10467 10468 10469 10470 10471 10472 10473 10474 10475 10476 10477 10478 10479 10480 10481 10482 10483 10484 10485 10486 10487 10488 10489 10490 10491 10492 10493 10494 10495 10496 10497 10498 10499 10500 10501 10502 10503 10504 10505 10506 10507 10508 10509 10510 10511 10512 10513 10514 10515 10516 10517 10518 10519 10520 10521 10522 10523 10524 10525 10526 10527 10528 10529 10530 10531 10532 10533 10534 10535 10536 10537 10538 10539 10540 10541 10542 10543 10544 10545 10546 10547 10548 10549 10550 10551 10552 10553 10554 10555 10556 10557 10558 10559 10560 10561 10562 10563 10564 10565 10566 10567 10568 10569 10570 10571 10572 10573 10574 10575 10576 10577 10578 10579 10580 10581 10582 10583 10584 10585 10586 10587 10588 10589 10590 10591 10592 10593 10594 10595 10596 10597 10598 10599 10600 10601 10602 10603 10604 10605 10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 10618 10619 10620 10621 10622 10623 10624 10625 10626 10627 10628 10629 10630 10631 10632 10633 10634 10635 10636 10637 10638 10639 10640 10641 10642 10643 10644 10645 10646 10647 10648 10649 10650 10651 10652 10653 10654 10655 10656 10657 10658 10659 10660 10661 10662 10663 10664 10665 10666 10667 10668 10669 10670 10671 10672 10673 10674 10675 10676 10677 10678 10679 10680 10681 10682 10683 10684 10685 10686 10687 10688 10689 10690 10691 10692 10693 10694 10695 10696 10697 10698 10699 10700 10701 10702 10703 10704 10705 10706 10707 10708 10709 10710 10711 10712 10713 10714 10715 10716 10717 10718 10719 10720 10721 10722 10723 10724 10725 10726 10727 10728 10729 10730 10731 10732 10733 10734 10735 10736 10737 10738 10739 10740 10741 10742 10743 10744 10745 10746 10747 10748 10749 10750 10751 10752 10753 10754 10755 10756 10757 10758 10759 10760 10761 10762 10763 10764 10765 10766 10767 10768 10769 10770 10771 10772 10773 10774 10775 10776 10777 10778 10779 10780 10781 10782 10783 10784 10785 10786 10787 10788 10789 10790 10791 10792 10793 10794 10795 10796 10797 10798 10799 10800 10801 10802 10803 10804 10805 10806 10807 10808 10809 10810 10811 10812 10813 10814 10815 10816 10817 10818 10819 10820 10821 10822 10823 10824 10825 10826 10827 10828 10829 10830 10831 10832 10833 10834 10835 10836 10837 10838 10839 10840 10841 10842 10843 10844 10845 10846 10847 10848 10849 10850 10851 10852 10853 10854 10855 10856 10857 10858 10859 10860 10861 10862 10863 10864 10865 10866 10867 10868 10869 10870 10871 10872 10873 10874 10875 10876 10877 10878 10879 10880 10881 10882 10883 10884 10885 10886 10887 10888 10889 10890 10891 10892 10893 10894 10895 10896 10897 10898 10899 10900 10901 10902 10903 10904 10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916 10917 10918 10919 10920 10921 10922 10923 10924 10925 10926 10927 10928 10929 10930 10931 10932 10933 10934 10935 10936 10937 10938 10939 10940 10941 10942 10943 10944 10945 10946 10947 10948 10949 10950 10951 10952 10953 10954 10955 10956 10957 10958 10959 10960 10961 10962 10963 10964 10965 10966 10967 10968 10969 10970 10971 10972 10973 10974 10975 10976 10977 10978 10979 10980 10981 10982 10983 10984 10985 10986 10987 10988 10989 10990 10991 10992 10993 10994 10995 10996 10997 10998 10999 11000 11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 11011 11012 11013 11014 11015 11016 11017 11018 11019 11020 11021 11022 11023 11024 11025 11026 11027 11028 11029 11030 11031 11032 11033 11034 11035 11036 11037 11038 11039 11040 11041 11042 11043 11044 11045 11046 11047 11048 11049 11050 11051 11052 11053 11054 11055 11056 11057 11058 11059 11060 11061 11062 11063 11064 11065 11066 11067 11068 11069 11070 11071 11072 11073 11074 11075 11076 11077 11078 11079 11080 11081 11082 11083 11084 11085 11086 11087 11088 11089 11090 11091 11092 11093 11094 11095 11096 11097 11098 11099 11100 11101 11102 11103 11104 11105 11106 11107 11108 11109 11110 11111 11112 11113 11114 11115 11116 11117 11118 11119 11120 11121 11122 11123 11124 11125 11126 11127 11128 11129 11130 11131 11132 11133 11134 11135 11136 11137 11138 11139 11140 11141 11142 11143 11144 11145 11146 11147 11148 11149 11150 11151 11152 11153 11154 11155 11156 11157 11158 11159 11160 11161 11162 11163 11164 11165 11166 11167 11168 11169 11170 11171 11172 11173 11174 11175 11176 11177 11178 11179 11180 11181 11182 11183 11184 11185 11186 11187 11188 11189 11190 11191 11192 11193 11194 11195 11196 11197 11198 11199 11200 11201 11202 11203 11204 11205 11206 11207 11208 11209 11210 11211 11212 11213 11214 11215 11216 11217 11218 11219 11220 11221 11222 11223 11224 11225 11226 11227 11228 11229 11230 11231 11232 11233 11234 11235 11236 11237 11238 11239 11240 11241 11242 11243 11244 11245 11246 11247 11248 11249 11250 11251 11252 11253 11254 11255 11256 11257 11258 11259 11260 11261 11262 11263 11264 11265 11266 11267 11268 11269 11270 11271 11272 11273 11274 11275 11276 11277 11278 11279 11280 11281 11282 11283 11284 11285 11286 11287 11288 11289 11290 11291 11292 11293 11294 11295 11296 11297 11298 11299 11300 11301 11302 11303 11304 11305 11306 11307 11308 11309 11310 11311 11312 11313 11314 11315 11316 11317 11318 11319 11320 11321 11322 11323 11324 11325 11326 11327 11328 11329 11330 11331 11332 11333 11334 11335 11336 11337 11338 11339 11340 11341 11342 11343 11344 11345 11346 11347 11348 11349 11350 11351 11352 11353 11354 11355 11356 11357 11358 11359 11360 11361 11362 11363 11364 11365 11366 11367 11368 11369 11370 11371 11372 11373 11374 11375 11376 11377 11378 11379 11380 11381 11382 11383 11384 11385 11386 11387 11388 11389 11390 11391 11392 11393 11394 11395 11396 11397 11398 11399 11400 11401 11402 11403 11404 11405 11406 11407 11408 11409 11410 11411 11412 11413 11414 11415 11416 11417 11418 11419 11420 11421 11422 11423 11424 11425 11426 11427 11428 11429 11430 11431 11432 11433 11434 11435 11436 11437 11438 11439 11440 11441 11442 11443 11444 11445 11446 11447 11448 11449 11450 11451 11452 11453 11454 11455 11456 11457 11458 11459 11460 11461 11462 11463 11464 11465 11466 11467 11468 11469 11470 11471 11472 11473 11474 11475 11476 11477 11478 11479 11480 11481 11482 11483 11484 11485 11486 11487 11488 11489 11490 11491 11492 11493 11494 11495 11496 11497 11498 11499 11500 11501 11502 11503 11504 11505 11506 11507 11508 11509 11510 11511 11512 11513 11514 11515 11516 11517 11518 11519 11520 11521 11522 11523 11524 11525 11526 11527 11528 11529 11530 11531 11532 11533 11534 11535 11536 11537 11538 11539 11540 11541 11542 11543 11544 11545 11546 11547 11548 11549 11550 11551 11552 11553 11554 11555 11556 11557 11558 11559 11560 11561 11562 11563 11564 11565 11566 11567 11568 11569 11570 11571 11572 11573 11574 11575 11576 11577 11578 11579 11580 11581 11582 11583 11584 11585 11586 11587 11588 11589 11590 11591 11592 11593 11594 11595 11596 11597 11598 11599 11600 11601 11602 11603 11604 11605 11606 11607 11608 11609 11610 11611 11612 11613 11614 11615 11616 11617 11618 11619 11620 11621 11622 11623 11624 11625 11626 11627 11628 11629 11630 11631 11632 11633 11634 11635 11636 11637 11638 11639 11640 11641 11642 11643 11644 11645 11646 11647 11648 11649 11650 11651 11652 11653 11654 11655 11656 11657 11658 11659 11660 11661 11662 11663 11664 11665 11666 11667 11668 11669 11670 11671 11672 11673 11674 11675 11676 11677 11678 11679 11680 11681 11682 11683 11684 11685 11686 11687 11688 11689 11690 11691 11692 11693 11694 11695 11696 11697 11698 11699 11700 11701 11702 11703 11704 11705 11706 11707 11708 11709 11710 11711 11712 11713 11714 11715 11716 11717 11718 11719 11720 11721 11722 11723 11724 11725 11726 11727 11728 11729 11730 11731 11732 11733 11734 11735 11736 11737 11738 11739 11740 11741 11742 11743 11744 11745 11746 11747 11748 11749 11750 11751 11752 11753 11754 11755 11756 11757 11758 11759 11760 11761 11762 11763 11764 11765 11766 11767 11768 11769 11770 11771 11772 11773 11774 11775 11776 11777 11778 11779 11780 11781 11782 11783 11784 11785 11786 11787 11788 11789 11790 11791 11792 11793 11794 11795 11796 11797 11798 11799 11800 11801 11802 11803 11804 11805 11806 11807 11808 11809 11810 11811 11812 11813 11814 11815 11816 11817 11818 11819 11820 11821 11822 11823 11824 11825 11826 11827 11828 11829 11830 11831 11832 11833 11834 11835 11836 11837 11838 11839 11840 11841 11842 11843 11844 11845 11846 11847 11848 11849 11850 11851 11852 11853 11854 11855 11856 11857 11858 11859 11860 11861 11862 11863 11864 11865 11866 11867 11868 11869 11870 11871 11872 11873 11874 11875 11876 11877 11878 11879 11880 11881 11882 11883 11884 11885 11886 11887 11888 11889 11890 11891 11892 11893 11894 11895 11896 11897 11898 11899 11900 11901 11902 11903 11904 11905 11906 11907 11908 11909 11910 11911 11912 11913 11914 11915 11916 11917 11918 11919 11920 11921 11922 11923 11924 11925 11926 11927 11928 11929 11930 11931 11932 11933 11934 11935 11936 11937 11938 11939 11940 11941 11942 11943 11944 11945 11946 11947 11948 11949 11950 11951 11952 11953 11954 11955 11956 11957 11958 11959 11960 11961 11962 11963 11964 11965 11966 11967 11968 11969 11970 11971 11972 11973 11974 11975 11976 11977 11978 11979 11980 11981 11982 11983 11984 11985 11986 11987 11988 11989 11990 11991 11992 11993 11994 11995 11996 11997 11998 11999 12000 12001 12002 12003 12004 12005 12006 12007 12008 12009 12010 12011 12012 12013 12014 12015 12016 12017 12018 12019 12020 12021 12022 12023 12024 12025 12026 12027 12028 12029 12030 12031 12032 12033 12034 12035 12036 12037 12038 12039 12040 12041 12042 12043 12044 12045 12046 12047 12048 12049 12050 12051 12052 12053 12054 12055 12056 12057 12058 12059 12060 12061 12062 12063 12064 12065 12066 12067 12068 12069 12070 12071 12072 12073 12074 12075 12076 12077 12078 12079 12080 12081 12082 12083 12084 12085 12086 12087 12088 12089 12090 12091 12092 12093 12094 12095 12096 12097 12098 12099 12100 12101 12102 12103 12104 12105 12106 12107 12108 12109 12110 12111 12112 12113 12114 12115 12116 12117 12118 12119 12120 12121 12122 12123 12124 12125 12126 12127 12128 12129 12130 12131 12132 12133 12134 12135 12136 12137 12138 12139 12140 12141 12142 12143 12144 12145 12146 12147 12148 12149 12150 12151 12152 12153 12154 12155 12156 12157 12158 12159 12160 12161 12162 12163 12164 12165 12166 12167 12168 12169 12170 12171 12172 12173 12174 12175 12176 12177 12178 12179 12180 12181 12182 12183 12184 12185 12186 12187 12188 12189 12190 12191 12192 12193 12194 12195 12196 12197 12198 12199 12200 12201 12202 12203 12204 12205 12206 12207 12208 12209 12210 12211 12212 12213 12214 12215 12216 12217 12218 12219 12220 12221 12222 12223 12224 12225 12226 12227 12228 12229 12230 12231 12232 12233 12234 12235 12236 12237 12238 12239 12240 12241 12242 12243 12244 12245 12246 12247 12248 12249 12250 12251 12252 12253 12254 12255 12256 12257 12258 12259 12260 12261 12262 12263 12264 12265 12266 12267 12268 12269 12270 12271 12272 12273 12274 12275 12276 12277 12278 12279 12280 12281 12282 12283 12284 12285 12286 12287 12288 12289 12290 12291 12292 12293 12294 12295 12296 12297 12298 12299 12300 12301 12302 12303 12304 12305 12306 12307 12308 12309 12310 12311 12312 12313 12314 12315 12316 12317 12318 12319 12320 12321 12322 12323 12324 12325 12326 12327 12328 12329 12330 12331 12332 12333 12334 12335 12336 12337 12338 12339 12340 12341 12342 12343 12344 12345 12346 12347 12348 12349 12350 12351 12352 12353 12354 12355 12356 12357 12358 12359 12360 12361 12362 12363 12364 12365 12366 12367 12368 12369 12370 12371 12372 12373 12374 12375 12376 12377 12378 12379 12380 12381 12382 12383 12384 12385 12386 12387 12388 12389 12390 12391 12392 12393 12394 12395 12396 12397 12398 12399 12400 12401 12402 12403 12404 12405 12406 12407 12408 12409 12410 12411 12412 12413 12414 12415 12416 12417 12418 12419 12420 12421 12422 12423 12424 12425 12426 12427 12428 12429 12430 12431 12432 12433 12434 12435 12436 12437 12438 12439 12440 12441 12442 12443 12444 12445 12446 12447 12448 12449 12450 12451 12452 12453 12454 12455 12456 12457 12458 12459 12460 12461 12462 12463 12464 12465 12466 12467 12468 12469 12470 12471 12472 12473 12474 12475 12476 12477 12478 12479 12480 12481 12482 12483 12484 12485 12486 12487 12488 12489 12490 12491 12492 12493 12494 12495 12496 12497 12498 12499 12500 12501 12502 12503 12504 12505 12506 12507 12508 12509 12510 12511 12512 12513 12514 12515 12516 12517 12518 12519 12520 12521 12522 12523 12524 12525 12526 12527 12528 12529 12530 12531 12532 12533 12534 12535 12536 12537 12538 12539 12540 12541 12542 12543 12544 12545 12546 12547 12548 12549 12550 12551 12552 12553 12554 12555 12556 12557 12558 12559 12560 12561 12562 12563 12564 12565 12566 12567 12568 12569 12570 12571 12572 12573 12574 12575 12576 12577 12578 12579 12580 12581 12582 12583 12584 12585 12586 12587 12588 12589 12590 12591 12592 12593 12594 12595 12596 12597 12598 12599 12600 12601 12602 12603 12604 12605 12606 12607 12608 12609 12610 12611 12612 12613 12614 12615 12616 12617 12618 12619 12620 12621 12622 12623 12624 12625 12626 12627 12628 12629 12630 12631 12632 12633 12634 12635 12636 12637 12638 12639 12640 12641 12642 12643 12644 12645 12646 12647 12648 12649 12650 12651 12652 12653 12654 12655 12656 12657 12658 12659 12660 12661 12662 12663 12664 12665 12666 12667 12668 12669 12670 12671 12672 12673 12674 12675 12676 12677 12678 12679 12680 12681 12682 12683 12684 12685 12686 12687 12688 12689 12690 12691 12692 12693 12694 12695 12696 12697 12698 12699 12700 12701 12702 12703 12704 12705 12706 12707 12708 12709 12710 12711 12712 12713 12714 12715 12716 12717 12718 12719 12720 12721 12722 12723 12724 12725 12726 12727 12728 12729 12730 12731 12732 12733 12734 12735 12736 12737 12738 12739 12740 12741 12742 12743 12744 12745 12746 12747 12748 12749 12750 12751 12752 12753 12754 12755 12756 12757 12758 12759 12760 12761 12762 12763 12764 12765 12766 12767 12768 12769 12770 12771 12772 12773 12774 12775 12776 12777 12778 12779 12780 12781 12782 12783 12784 12785 12786 12787 12788 12789 12790 12791 12792 12793 12794 12795 12796 12797 12798 12799 12800 12801 12802 12803 12804 12805 12806 12807 12808 12809 12810 12811 12812 12813 12814 12815 12816 12817 12818 12819 12820 12821 12822 12823 12824 12825 12826 12827 12828 12829 12830 12831 12832 12833 12834 12835 12836 12837 12838 12839 12840 12841 12842 12843 12844 12845 12846 12847 12848 12849 12850 12851 12852 12853 12854 12855 12856 12857 12858 12859 12860 12861 12862 12863 12864 12865 12866 12867 12868 12869 12870 12871 12872 12873 12874 12875 12876 12877 12878 12879 12880 12881 12882 12883 12884 12885 12886 12887 12888 12889 12890 12891 12892 12893 12894 12895 12896 12897 12898 12899 12900 12901 12902 12903 12904 12905 12906 12907 12908 12909 12910 12911 12912 12913 12914 12915 12916 12917 12918 12919 12920 12921 12922 12923 12924 12925 12926 12927 12928 12929 12930 12931 12932 12933 12934 12935 12936 12937 12938 12939 12940 12941 12942 12943 12944 12945 12946 12947 12948 12949 12950 12951 12952 12953 12954 12955 12956 12957 12958 12959 12960 12961 12962 12963 12964 12965 12966 12967 12968 12969 12970 12971 12972 12973 12974 12975 12976 12977 12978 12979 12980 12981 12982 12983 12984 12985 12986 12987 12988 12989 12990 12991 12992 12993 12994 12995 12996 12997 12998 12999 13000 13001 13002 13003 13004 13005 13006 13007 13008 13009 13010 13011 13012 13013 13014 13015 13016 13017 13018 13019 13020 13021 13022 13023 13024 13025 13026 13027 13028 13029 13030 13031 13032 13033 13034 13035 13036 13037 13038 13039 13040 13041 13042 13043 13044 13045 13046 13047 13048 13049 13050 13051 13052 13053 13054 13055 13056 13057 13058 13059 13060 13061 13062 13063 13064 13065 13066 13067 13068 13069 13070 13071 13072 13073 13074 13075 13076 13077 13078 13079 13080 13081 13082 13083 13084 13085 13086 13087 13088 13089 13090 13091 13092 13093 13094 13095 13096 13097 13098 13099 13100 13101 13102 13103 13104 13105 13106 13107 13108 13109 13110 13111 13112 13113 13114 13115 13116 13117 13118 13119 13120 13121 13122 13123 13124 13125 13126 13127 13128 13129 13130 13131 13132 13133 13134 13135 13136 13137 13138 13139 13140 13141 13142 13143 13144 13145 13146 13147 13148 13149 13150 13151 13152 13153 13154 13155 13156 13157 13158 13159 13160 13161 13162 13163 13164 13165 13166 13167 13168 13169 13170 13171 13172 13173 13174 13175 13176 13177 13178 13179 13180 13181 13182 13183 13184 13185 13186 13187 13188 13189 13190 13191 13192 13193 13194 13195 13196 13197 13198 13199 13200 13201 13202 13203 13204 13205 13206 13207 13208 13209 13210 13211 13212 13213 13214 13215 13216 13217 13218 13219 13220 13221 13222 13223 13224 13225 13226 13227 13228 13229 13230 13231 13232 13233 13234 13235 13236 13237 13238 13239 13240 13241 13242 13243 13244 13245 13246 13247 13248 13249 13250 13251 13252 13253 13254 13255 13256 13257 13258 13259 13260 13261 13262 13263 13264 13265 13266 13267 13268 13269 13270 13271 13272 13273 13274 13275 13276 13277 13278 13279 13280 13281 13282 13283 13284 13285 13286 13287 13288 13289 13290 13291 13292 13293 13294 13295 13296 13297 13298 13299 13300 13301 13302 13303 13304 13305 13306 13307 13308 13309 13310 13311 13312 13313 13314 13315 13316 13317 13318 13319 13320 13321 13322 13323 13324 13325 13326 13327 13328 13329 13330 13331 13332 13333 13334 13335 13336 13337 13338 13339 13340 13341 13342 13343 13344 13345 13346 13347 13348 13349 13350 13351 13352 13353 13354 13355 13356 13357 13358 13359 13360 13361 13362 13363 13364 13365 13366 13367 13368 13369 13370 13371 13372 13373 13374 13375 13376 13377 13378 13379 13380 13381 13382 13383 13384 13385 13386 13387 13388 13389 13390 13391 13392 13393 13394 13395 13396 13397 13398 13399 13400 13401 13402 13403 13404 13405 13406 13407 13408 13409 13410 13411 13412 13413 13414 13415 13416 13417 13418 13419 13420 13421 13422 13423 13424 13425 13426 13427 13428 13429 13430 13431 13432 13433 13434 13435 13436 13437 13438 13439 13440 13441 13442 13443 13444 13445 13446 13447 13448 13449 13450 13451 13452 13453 13454 13455 13456 13457 13458 13459 13460 13461 13462 13463 13464 13465 13466 13467 13468 13469 13470 13471 13472 13473 13474 13475 13476 13477 13478 13479 13480 13481 13482 13483 13484 13485 13486 13487 13488 13489 13490 13491 13492 13493 13494 13495 13496 13497 13498 13499 13500 13501 13502 13503 13504 13505 13506 13507 13508 13509 13510 13511 13512 13513 13514 13515 13516 13517 13518 13519 13520 13521 13522 13523 13524 13525 13526 13527 13528 13529 13530 13531 13532 13533 13534 13535 13536 13537 13538 13539 13540 13541 13542 13543 13544 13545 13546 13547 13548 13549 13550 13551 13552 13553 13554 13555 13556 13557 13558 13559 13560 13561 13562 13563 13564 13565 13566 13567 13568 13569 13570 13571 13572 13573 13574 13575 13576 13577 13578 13579 13580 13581 13582 13583 13584 13585 13586 13587 13588 13589 13590 13591 13592 13593 13594 13595 13596 13597 13598 13599 13600 13601 13602 13603 13604 13605 13606 13607 13608 13609 13610 13611 13612 13613 13614 13615 13616 13617 13618 13619 13620 13621 13622 13623 13624 13625 13626 13627 13628 13629 13630 13631 13632 13633 13634 13635 13636 13637 13638 13639 13640 13641 13642 13643 13644 13645 13646 13647 13648 13649 13650 13651 13652 13653 13654 13655 13656 13657 13658 13659 13660 13661 13662 13663 13664 13665 13666 13667 13668 13669 13670 13671 13672 13673 13674 13675 13676 13677 13678 13679 13680 13681 13682 13683 13684 13685 13686 13687 13688 13689 13690 13691 13692 13693 13694 13695 13696 13697 13698 13699 13700 13701 13702 13703 13704 13705 13706 13707 13708 13709 13710 13711 13712 13713 13714 13715 13716 13717 13718 13719 13720 13721 13722 13723 13724 13725 13726 13727 13728 13729 13730 13731 13732 13733 13734 13735 13736 13737 13738 13739 13740 13741 13742 13743 13744 13745 13746 13747 13748 13749 13750 13751 13752 13753 13754 13755 13756 13757 13758 13759 13760 13761 13762 13763 13764 13765 13766 13767 13768 13769 13770 13771 13772 13773 13774 13775 13776 13777 13778 13779 13780 13781 13782 13783 13784 13785 13786 13787 13788 13789 13790 13791 13792 13793 13794 13795 13796 13797 13798 13799 13800 13801 13802 13803 13804 13805 13806 13807 13808 13809 13810 13811 13812 13813 13814 13815 13816 13817 13818 13819 13820 13821 13822 13823 13824 13825 13826 13827 13828 13829 13830 13831 13832 13833 13834 13835 13836 13837 13838 13839 13840 13841 13842 13843 13844 13845 13846 13847 13848 13849 13850 13851 13852 13853 13854 13855 13856 13857 13858 13859 13860 13861 13862 13863 13864 13865 13866 13867 13868 13869 13870 13871 13872 13873 13874 13875 13876 13877 13878 13879 13880 13881 13882 13883 13884 13885 13886 13887 13888 13889 13890 13891 13892 13893 13894 13895 13896 13897 13898 13899 13900 13901 13902 13903 13904 13905 13906 13907 13908 13909 13910 13911 13912 13913 13914 13915 13916 13917 13918 13919 13920 13921 13922 13923 13924 13925 13926 13927 13928 13929 13930 13931 13932 13933 13934 13935 13936 13937 13938 13939 13940 13941 13942 13943 13944 13945 13946 13947 13948 13949 13950 13951 13952 13953 13954 13955 13956 13957 13958 13959 13960 13961 13962 13963 13964 13965 13966 13967 13968 13969 13970 13971 13972 13973 13974 13975 13976 13977 13978 13979 13980 13981 13982 13983 13984 13985 13986 13987 13988 13989 13990 13991 13992 13993 13994 13995 13996 13997 13998 13999 14000 14001 14002 14003 14004 14005 14006 14007 14008 14009 14010 14011 14012 14013 14014 14015 14016 14017 14018 14019 14020 14021 14022 14023 14024 14025 14026 14027 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 14041 14042 14043 14044 14045 14046 14047 14048 14049 14050 14051 14052 14053 14054 14055 14056 14057 14058 14059 14060 14061 14062 14063 14064 14065 14066 14067 14068 14069 14070 14071 14072 14073 14074 14075 14076 14077 14078 14079 14080 14081 14082 14083 14084 14085 14086 14087 14088 14089 14090 14091 14092 14093 14094 14095 14096 14097 14098 14099 14100 14101 14102 14103 14104 14105 14106 14107 14108 14109 14110 14111 14112 14113 14114 14115 14116 14117 14118 14119 14120 14121 14122 14123 14124 14125 14126 14127 14128 14129 14130 14131 14132 14133 14134 14135 14136 14137 14138 14139 14140 14141 14142 14143 14144 14145 14146 14147 14148 14149 14150 14151 14152 14153 14154 14155 14156 14157 14158 14159 14160 14161 14162 14163 14164 14165 14166 14167 14168 14169 14170 14171 14172 14173 14174 14175 14176 14177 14178 14179 14180 14181 14182 14183 14184 14185 14186 14187 14188 14189 14190 14191 14192 14193 14194 14195 14196 14197 14198 14199 14200 14201 14202 14203 14204 14205 14206 14207 14208 14209 14210 14211 14212 14213 14214 14215 14216 14217 14218 14219 14220 14221 14222 14223 14224 14225 14226 14227 14228 14229 14230 14231 14232 14233 14234 14235 14236 14237 14238 14239 14240 14241 14242 14243 14244 14245 14246 14247 14248 14249 14250 14251 14252 14253 14254 14255 14256 14257 14258 14259 14260 14261 14262 14263 14264 14265 14266 14267 14268 14269 14270 14271 14272 14273 14274 14275 14276 14277 14278 14279 14280 14281 14282 14283 14284 14285 14286 14287 14288 14289 14290 14291 14292 14293 14294 14295 14296 14297 14298 14299 14300 14301 14302 14303 14304 14305 14306 14307 14308 14309 14310 14311 14312 14313 14314 14315 14316 14317 14318 14319 14320 14321 14322 14323 14324 14325 14326 14327 14328 14329 14330 14331 14332 14333 14334 14335 14336 14337 14338 14339 14340 14341 14342 14343 14344 14345 14346 14347 14348 14349 14350 14351 14352 14353 14354 14355 14356 14357 14358 14359 14360 14361 14362 14363 14364 14365 14366 14367 14368 14369 14370 14371 14372 14373 14374 14375 14376 14377 14378 14379 14380 14381 14382 14383 14384 14385 14386 14387 14388 14389 14390 14391 14392 14393 14394 14395 14396 14397 14398 14399 14400 14401 14402 14403 14404 14405 14406 14407 14408 14409 14410 14411 14412 14413 14414 14415 14416 14417 14418 14419 14420 14421 14422 14423 14424 14425 14426 14427 14428 14429 14430 14431 14432 14433 14434 14435 14436 14437 14438 14439 14440 14441 14442 14443 14444 14445 14446 14447 14448 14449 14450 14451 14452 14453 14454 14455 14456 14457 14458 14459 14460 14461 14462 14463 14464 14465 14466 14467 14468 14469 14470 14471 14472 14473 14474 14475 14476 14477 14478 14479 14480 14481 14482 14483 14484 14485 14486 14487 14488 14489 14490 14491 14492 14493 14494 14495 14496 14497 14498 14499 14500 14501 14502 14503 14504 14505 14506 14507 14508 14509 14510 14511 14512 14513 14514 14515 14516 14517 14518 14519 14520 14521 14522 14523 14524 14525 14526 14527 14528 14529 14530 14531 14532 14533 14534 14535 14536 14537 14538 14539 14540 14541 14542 14543 14544 14545 14546 14547 14548 14549 14550 14551 14552 14553 14554 14555 14556 14557 14558 14559 14560 14561 14562 14563 14564 14565 14566 14567 14568 14569 14570 14571 14572 14573 14574 14575 14576 14577 14578 14579 14580 14581 14582 14583 14584 14585 14586 14587 14588 14589 14590 14591 14592 14593 14594 14595 14596 14597 14598 14599 14600 14601 14602 14603 14604 14605 14606 14607 14608 14609 14610 14611 14612 14613 14614 14615 14616 14617 14618 14619 14620 14621 14622 14623 14624 14625 14626 14627 14628 14629 14630 14631 14632 14633 14634 14635 14636 14637 14638 14639 14640 14641 14642 14643 14644 14645 14646 14647 14648 14649 14650 14651 14652 14653 14654 14655 14656 14657 14658 14659 14660 14661 14662 14663 14664 14665 14666 14667 14668 14669 14670 14671 14672 14673 14674 14675 14676 14677 14678 14679 14680 14681 14682 14683 14684 14685 14686 14687 14688 14689 14690 14691 14692 14693 14694 14695 14696 14697 14698 14699 14700 14701 14702 14703 14704 14705 14706 14707 14708 14709 14710 14711 14712 14713 14714 14715 14716 14717 14718 14719 14720 14721 14722 14723 14724 14725 14726 14727 14728 14729 14730 14731 14732 14733 14734 14735 14736 14737 14738 14739 14740 14741 14742 14743 14744 14745 14746 14747 14748 14749 14750 14751 14752 14753 14754 14755 14756 14757 14758 14759 14760 14761 14762 14763 14764 14765 14766 14767 14768 14769 14770 14771 14772 14773 14774 14775 14776 14777 14778 14779 14780 14781 14782 14783 14784 14785 14786 14787 14788 14789 14790 14791 14792 14793 14794 14795 14796 14797 14798 14799 14800 14801 14802 14803 14804 14805 14806 14807 14808 14809 14810 14811 14812 14813 14814 14815 14816 14817 14818 14819 14820 14821 14822 14823 14824 14825 14826 14827 14828 14829 14830 14831 14832 14833 14834 14835 14836 14837 14838 14839 14840 14841 14842 14843 14844 14845 14846 14847 14848 14849 14850 14851 14852 14853 14854 14855 14856 14857 14858 14859 14860 14861 14862 14863 14864 14865 14866 14867 14868 14869 14870 14871 14872 14873 14874 14875 14876 14877 14878 14879 14880 14881 14882 14883 14884 14885 14886 14887 14888 14889 14890 14891 14892 14893 14894 14895 14896 14897 14898 14899 14900 14901 14902 14903 14904 14905 14906 14907 14908 14909 14910 14911 14912 14913 14914 14915 14916 14917 14918 14919 14920 14921 14922 14923 14924 14925 14926 14927 14928 14929 14930 14931 14932 14933 14934 14935 14936 14937 14938 14939 14940 14941 14942 14943 14944 14945 14946 14947 14948 14949 14950 14951 14952 14953 14954 14955 14956 14957 14958 14959 14960 14961 14962 14963 14964 14965 14966 14967 14968 14969 14970 14971 14972 14973 14974 14975 14976 14977 14978 14979 14980 14981 14982 14983 14984 14985 14986 14987 14988 14989 14990 14991 14992 14993 14994 14995 14996 14997 14998 14999 15000 15001 15002 15003 15004 15005 15006 15007 15008 15009 15010 15011 15012 15013 15014 15015 15016 15017 15018 15019 15020 15021 15022 15023 15024 15025 15026 15027 15028 15029 15030 15031 15032 15033 15034 15035 15036 15037 15038 15039 15040 15041 15042 15043 15044 15045 15046 15047 15048 15049 15050 15051 15052 15053 15054 15055 15056 15057 15058 15059 15060 15061 15062 15063 15064 15065 15066 15067 15068 15069 15070 15071 15072 15073 15074 15075 15076 15077 15078 15079 15080 15081 15082 15083 15084 15085 15086 15087 15088 15089 15090 15091 15092 15093 15094 15095 15096 15097 15098 15099 15100 15101 15102 15103 15104 15105 15106 15107 15108 15109 15110 15111 15112 15113 15114 15115 15116 15117 15118 15119 15120 15121 15122 15123 15124 15125 15126 15127 15128 15129 15130 15131 15132 15133 15134 15135 15136 15137 15138 15139 15140 15141 15142 15143 15144 15145 15146 15147 15148 15149 15150 15151 15152 15153 15154 15155 15156 15157 15158 15159 15160 15161 15162 15163 15164 15165 15166 15167 15168 15169 15170 15171 15172 15173 15174 15175 15176 15177 15178 15179 15180 15181 15182 15183 15184 15185 15186 15187 15188 15189 15190 15191 15192 15193 15194 15195 15196 15197 15198 15199 15200 15201 15202 15203 15204 15205 15206 15207 15208 15209 15210 15211 15212 15213 15214 15215 15216 15217 15218 15219 15220 15221 15222 15223 15224 15225 15226 15227 15228 15229 15230 15231 15232 15233 15234 15235 15236 15237 15238 15239 15240 15241 15242 15243 15244 15245 15246 15247 15248 15249 15250 15251 15252 15253 15254 15255 15256 15257 15258 15259 15260 15261 15262 15263 15264 15265 15266 15267 15268 15269 15270 15271 15272 15273 15274 15275 15276 15277 15278 15279 15280 15281 15282 15283 15284 15285 15286 15287 15288 15289 15290 15291 15292 15293 15294 15295 15296 15297 15298 15299 15300 15301 15302 15303 15304 15305 15306 15307 15308 15309 15310 15311 15312 15313 15314 15315 15316 15317 15318 15319 15320 15321 15322 15323 15324 15325 15326 15327 15328 15329 15330 15331 15332 15333 15334 15335 15336 15337 15338 15339 15340 15341 15342 15343 15344 15345 15346 15347 15348 15349 15350 15351 15352 15353 15354 15355 15356 15357 15358 15359 15360 15361 15362 15363 15364 15365 15366 15367 15368 15369 15370 15371 15372 15373 15374 15375 15376 15377 15378 15379 15380 15381 15382 15383 15384 15385 15386 15387 15388 15389 15390 15391 15392 15393 15394 15395 15396 15397 15398 15399 15400 15401 15402 15403 15404 15405 15406 15407 15408 15409 15410 15411 15412 15413 15414 15415 15416 15417 15418 15419 15420 15421 15422 15423 15424 15425 15426 15427 15428 15429 15430 15431 15432 15433 15434 15435 15436 15437 15438 15439 15440 15441 15442 15443 15444 15445 15446 15447 15448 15449 15450 15451 15452 15453 15454 15455 15456 15457 15458 15459 15460 15461 15462 15463 15464 15465 15466 15467 15468 15469 15470 15471 15472 15473 15474 15475 15476 15477 15478 15479 15480 15481 15482 15483 15484 15485 15486 15487 15488 15489 15490 15491 15492 15493 15494 15495 15496 15497 15498 15499 15500 15501 15502 15503 15504 15505 15506 15507 15508 15509 15510 15511 15512 15513 15514 15515 15516 15517 15518 15519 15520 15521 15522 15523 15524 15525 15526 15527 15528 15529 15530 15531 15532 15533 15534 15535 15536 15537 15538 15539 15540 15541 15542 15543 15544 15545 15546 15547 15548 15549 15550 15551 15552 15553 15554 15555 15556 15557 15558 15559 15560 15561 15562 15563 15564 15565 15566 15567 15568 15569 15570 15571 15572 15573 15574 15575 15576 15577 15578 15579 15580 15581 15582 15583 15584 15585 15586 15587 15588 15589 15590 15591 15592 15593 15594 15595 15596 15597 15598 15599 15600 15601 15602 15603 15604 15605 15606 15607 15608 15609 15610 15611 15612 15613 15614 15615 15616 15617 15618 15619 15620 15621 15622 15623 15624 15625 15626 15627 15628 15629 15630 15631 15632 15633 15634 15635 15636 15637 15638 15639 15640 15641 15642 15643 15644 15645 15646 15647 15648 15649 15650 15651 15652 15653 15654 15655 15656 15657 15658 15659 15660 15661 15662 15663 15664 15665 15666 15667 15668 15669 15670 15671 15672 15673 15674 15675 15676 15677 15678 15679 15680 15681 15682 15683 15684 15685 15686 15687 15688 15689 15690 15691 15692 15693 15694 15695 15696 15697 15698 15699 15700 15701 15702 15703 15704 15705 15706 15707 15708 15709 15710 15711 15712 15713 15714 15715 15716 15717 15718 15719 15720 15721 15722 15723 15724 15725 15726 15727 15728 15729 15730 15731 15732 15733 15734 15735 15736 15737 15738 15739 15740 15741 15742 15743 15744 15745 15746 15747 15748 15749 15750 15751 15752 15753 15754 15755 15756 15757 15758 15759 15760 15761 15762 15763 15764 15765 15766 15767 15768 15769 15770 15771 15772 15773 15774 15775 15776 15777 15778 15779 15780 15781 15782 15783 15784 15785 15786 15787 15788 15789 15790 15791 15792 15793 15794 15795 15796 15797 15798 15799 15800 15801 15802 15803 15804 15805 15806 15807 15808 15809 15810 15811 15812 15813 15814 15815 15816 15817 15818 15819 15820 15821 15822 15823 15824 15825 15826 15827 15828 15829 15830 15831 15832 15833 15834 15835 15836 15837 15838 15839 15840 15841 15842 15843 15844 15845 15846 15847 15848 15849 15850 15851 15852 15853 15854 15855 15856 15857 15858 15859 15860 15861 15862 15863 15864 15865 15866 15867 15868 15869 15870 15871 15872 15873 15874 15875 15876 15877 15878 15879 15880 15881 15882 15883 15884 15885 15886 15887 15888 15889 15890 15891 15892 15893 15894 15895 15896 15897 15898 15899 15900 15901 15902 15903 15904 15905 15906 15907 15908 15909 15910 15911 15912 15913 15914 15915 15916 15917 15918 15919 15920 15921 15922 15923 15924 15925 15926 15927 15928 15929 15930 15931 15932 15933 15934 15935 15936 15937 15938 15939 15940 15941 15942 15943 15944 15945 15946 15947 15948 15949 15950 15951 15952 15953 15954 15955 15956 15957 15958 15959 15960 15961 15962 15963 15964 15965 15966 15967 15968 15969 15970 15971 15972 15973 15974 15975 15976 15977 15978 15979 15980 15981 15982 15983 15984 15985 15986 15987 15988 15989 15990 15991 15992 15993 15994 15995 15996 15997 15998 15999 16000 16001 16002 16003 16004 16005 16006 16007 16008 16009 16010 16011 16012 16013 16014 16015 16016 16017 16018 16019 16020 16021 16022 16023 16024 16025 16026 16027 16028 16029 16030 16031 16032 16033 16034 16035 16036 16037 16038 16039 16040 16041 16042 16043 16044 16045 16046 16047 16048 16049 16050 16051 16052 16053 16054 16055 16056 16057 16058 16059 16060 16061 16062 16063 16064 16065 16066 16067 16068 16069 16070 16071 16072 16073 16074 16075 16076 16077 16078 16079 16080 16081 16082 16083 16084 16085 16086 16087 16088 16089 16090 16091 16092 16093 16094 16095 16096 16097 16098 16099 16100 16101 16102 16103 16104 16105 16106 16107 16108 16109 16110 16111 16112 16113 16114 16115 16116 16117 16118 16119 16120 16121 16122 16123 16124 16125 16126 16127 16128 16129 16130 16131 16132 16133 16134 16135 16136 16137 16138 16139 16140 16141 16142 16143 16144 16145 16146 16147 16148 16149 16150 16151 16152 16153 16154 16155 16156 16157 16158 16159 16160 16161 16162 16163 16164 16165 16166 16167 16168 16169 16170 16171 16172 16173 16174 16175 16176 16177 16178 16179 16180 16181 16182 16183 16184 16185 16186 16187 16188 16189 16190 16191 16192 16193 16194 16195 16196 16197 16198 16199 16200 16201 16202 16203 16204 16205 16206 16207 16208 16209 16210 16211 16212 16213 16214 16215 16216 16217 16218 16219 16220 16221 16222 16223 16224 16225 16226 16227 16228 16229 16230 16231 16232 16233 16234 16235 16236 16237 16238 16239 16240 16241 16242 16243 16244 16245 16246 16247 16248 16249 16250 16251 16252 16253 16254 16255 16256 16257 16258 16259 16260 16261 16262 16263 16264 16265 16266 16267 16268 16269 16270 16271 16272 16273 16274 16275 16276 16277 16278 16279 16280 16281 16282 16283 16284 16285 16286 16287 16288 16289 16290 16291 16292 16293 16294 16295 16296 16297 16298 16299 16300 16301 16302 16303 16304 16305 16306 16307 16308 16309 16310 16311 16312 16313 16314 16315 16316 16317 16318 16319 16320 16321 16322 16323 16324 16325 16326 16327 16328 16329 16330 16331 16332 16333 16334 16335 16336 16337 16338 16339 16340 16341 16342 16343 16344 16345 16346 16347 16348 16349 16350 16351 16352 16353 16354 16355 16356 16357 16358 16359 16360 16361 16362 16363 16364 16365 16366 16367 16368 16369 16370 16371 16372 16373 16374 16375 16376 16377 16378 16379 16380 16381 16382 16383 16384 16385 16386 16387 16388 16389 16390 16391 16392 16393 16394 16395 16396 16397 16398 16399 16400 16401 16402 16403 16404 16405 16406 16407 16408 16409 16410 16411 16412 16413 16414 16415 16416 16417 16418 16419 16420 16421 16422 16423 16424 16425 16426 16427 16428 16429 16430 16431 16432 16433 16434 16435 16436 16437 16438 16439 16440 16441 16442 16443 16444 16445 16446 16447 16448 16449 16450 16451 16452 16453 16454 16455 16456 16457 16458 16459 16460 16461 16462 16463 16464 16465 16466 16467 16468 16469 16470 16471 16472 16473 16474 16475 16476 16477 16478 16479 16480 16481 16482 16483 16484 16485 16486 16487 16488 16489 16490 16491 16492 16493 16494 16495 16496 16497 16498 16499 16500 16501 16502 16503 16504 16505 16506 16507 16508 16509 16510 16511 16512 16513 16514 16515 16516 16517 16518 16519 16520 16521 16522 16523 16524 16525 16526 16527 16528 16529 16530 16531 16532 16533 16534 16535 16536 16537 16538 16539 16540 16541 16542 16543 16544 16545 16546 16547 16548 16549 16550 16551 16552 16553 16554 16555 16556 16557 16558 16559 16560 16561 16562 16563 16564 16565 16566 16567 16568 16569 16570 16571 16572 16573 16574 16575 16576 16577 16578 16579 16580 16581 16582 16583 16584 16585 16586 16587 16588 16589 16590 16591 16592 16593 16594 16595 16596 16597 16598 16599 16600 16601 16602 16603 16604 16605 16606 16607 16608 16609 16610 16611 16612 16613 16614 16615 16616 16617 16618 16619 16620 16621 16622 16623 16624 16625 16626 16627 16628 16629 16630 16631 16632 16633 16634 16635 16636 16637 16638 16639 16640 16641 16642 16643 16644 16645 16646 16647 16648 16649 16650 16651 16652 16653 16654 16655 16656 16657 16658 16659 16660 16661 16662 16663 16664 16665 16666 16667 16668 16669 16670 16671 16672 16673 16674 16675 16676 16677 16678 16679 16680 16681 16682 16683 16684 16685 16686 16687 16688 16689 16690 16691 16692 16693 16694 16695 16696 16697 16698 16699 16700 16701 16702 16703 16704 16705 16706 16707 16708 16709 16710 16711 16712 16713 16714 16715 16716 16717 16718 16719 16720 16721 16722 16723 16724 16725 16726 16727 16728 16729 16730 16731 16732 16733 16734 16735 16736 16737 16738 16739 16740 16741 16742 16743 16744 16745 16746 16747 16748 16749 16750 16751 16752 16753 16754 16755 16756 16757 16758 16759 16760 16761 16762 16763 16764 16765 16766 16767 16768 16769 16770 16771 16772 16773 16774 16775 16776 16777 16778 16779 16780 16781 16782 16783 16784 16785 16786 16787 16788 16789 16790 16791 16792 16793 16794 16795 16796 16797 16798 16799 16800 16801 16802 16803 16804 16805 16806 16807 16808 16809 16810 16811 16812 16813 16814 16815 16816 16817 16818 16819 16820 16821 16822 16823 16824 16825 16826 16827 16828 16829 16830 16831 16832 16833 16834 16835 16836 16837 16838 16839 16840 16841 16842 16843 16844 16845 16846 16847 16848 16849 16850 16851 16852 16853 16854 16855 16856 16857 16858 16859 16860 16861 16862 16863 16864 16865 16866 16867 16868 16869 16870 16871 16872 16873 16874 16875 16876 16877 16878 16879 16880 16881 16882 16883 16884 16885 16886 16887 16888 16889 16890 16891 16892 16893 16894 16895 16896 16897 16898 16899 16900 16901 16902 16903 16904 16905 16906 16907 16908 16909 16910 16911 16912 16913 16914 16915 16916 16917 16918 16919 16920 16921 16922 16923 16924 16925 16926 16927 16928 16929 16930 16931 16932 16933 16934 16935 16936 16937 16938 16939 16940 16941 16942 16943 16944 16945 16946 16947 16948 16949 16950 16951 16952 16953 16954 16955 16956 16957 16958 16959 16960 16961 16962 16963 16964 16965 16966 16967 16968 16969 16970 16971 16972 16973 16974 16975 16976 16977 16978 16979 16980 16981 16982 16983 16984 16985 16986 16987 16988 16989 16990 16991 16992 16993 16994 16995 16996 16997 16998 16999 17000 17001 17002 17003 17004 17005 17006 17007 17008 17009 17010 17011 17012 17013 17014 17015 17016 17017 17018 17019 17020 17021 17022 17023 17024 17025 17026 17027 17028 17029 17030 17031 17032 17033 17034 17035 17036 17037 17038 17039 17040 17041 17042 17043 17044 17045 17046 17047 17048 17049 17050 17051 17052 17053 17054 17055 17056 17057 17058 17059 17060 17061 17062 17063 17064 17065 17066 17067 17068 17069 17070 17071 17072 17073 17074 17075 17076 17077 17078 17079 17080 17081 17082 17083 17084 17085 17086 17087 17088 17089 17090 17091 17092 17093 17094 17095 17096 17097 17098 17099 17100 17101 17102 17103 17104 17105 17106 17107 17108 17109 17110 17111 17112 17113 17114 17115 17116 17117 17118 17119 17120 17121 17122 17123 17124 17125 17126 17127 17128 17129 17130 17131 17132 17133 17134 17135 17136 17137 17138 17139 17140 17141 17142 17143 17144 17145 17146 17147 17148 17149 17150 17151 17152 17153 17154 17155 17156 17157 17158 17159 17160 17161 17162 17163 17164 17165 17166 17167 17168 17169 17170 17171 17172 17173 17174 17175 17176 17177 17178 17179 17180 17181 17182 17183 17184 17185 17186 17187 17188 17189 17190 17191 17192 17193 17194 17195 17196 17197 17198 17199 17200 17201 17202 17203 17204 17205 17206 17207 17208 17209 17210 17211 17212 17213 17214 17215 17216 17217 17218 17219 17220 17221 17222 17223 17224 17225 17226 17227 17228 17229 17230 17231 17232 17233 17234 17235 17236 17237 17238 17239 17240 17241 17242 17243 17244 17245 17246 17247 17248 17249 17250 17251 17252 17253 17254 17255 17256 17257 17258 17259 17260 17261 17262 17263 17264 17265 17266 17267 17268 17269 17270 17271 17272 17273 17274 17275 17276 17277 17278 17279 17280 17281 17282 17283 17284 17285 17286 17287 17288 17289 17290 17291 17292 17293 17294 17295 17296 17297 17298 17299 17300 17301 17302 17303 17304 17305 17306 17307 17308 17309 17310 17311 17312 17313 17314 17315 17316 17317 17318 17319 17320 17321 17322 17323 17324 17325 17326 17327 17328 17329 17330 17331 17332 17333 17334 17335 17336 17337 17338 17339 17340 17341 17342 17343 17344 17345 17346 17347 17348 17349 17350 17351 17352 17353 17354 17355 17356 17357 17358 17359 17360 17361 17362 17363 17364 17365 17366 17367 17368 17369 17370 17371 17372 17373 17374 17375 17376 17377 17378 17379 17380 17381 17382 17383 17384 17385 17386 17387 17388 17389 17390 17391 17392 17393 17394 17395 17396 17397 17398 17399 17400 17401 17402 17403 17404 17405 17406 17407 17408 17409 17410 17411 17412 17413 17414 17415 17416 17417 17418 17419 17420 17421 17422 17423 17424 17425 17426 17427 17428 17429 17430 17431 17432 17433 17434 17435 17436 17437 17438 17439 17440 17441 17442 17443 17444 17445 17446 17447 17448 17449 17450 17451 17452 17453 17454 17455 17456 17457 17458 17459 17460 17461 17462 17463 17464 17465 17466 17467 17468 17469 17470 17471 17472 17473 17474 17475 17476 17477 17478 17479 17480 17481 17482 17483 17484 17485 17486 17487 17488 17489 17490 17491 17492 17493 17494 17495 17496 17497 17498 17499 17500 17501 17502 17503 17504 17505 17506 17507 17508 17509 17510 17511 17512 17513 17514 17515 17516 17517 17518 17519 17520 17521 17522 17523 17524 17525 17526 17527 17528 17529 17530 17531 17532 17533 17534 17535 17536 17537 17538 17539 17540 17541 17542 17543 17544 17545 17546 17547 17548 17549 17550 17551 17552 17553 17554 17555 17556 17557 17558 17559 17560 17561 17562 17563 17564 17565 17566 17567 17568 17569 17570 17571 17572 17573 17574 17575 17576 17577 17578 17579 17580 17581 17582 17583 17584 17585 17586 17587 17588 17589 17590 17591 17592 17593 17594 17595 17596 17597 17598 17599 17600 17601 17602 17603 17604 17605 17606 17607 17608 17609 17610 17611 17612 17613 17614 17615 17616 17617 17618 17619 17620 17621 17622 17623 17624 17625 17626 17627 17628 17629 17630 17631 17632 17633 17634 17635 17636 17637 17638 17639 17640 17641 17642 17643 17644 17645 17646 17647 17648 17649 17650 17651 17652 17653 17654 17655 17656 17657 17658 17659 17660 17661 17662 17663 17664 17665 17666 17667 17668 17669 17670 17671 17672 17673 17674 17675 17676 17677 17678 17679 17680 17681 17682 17683 17684 17685 17686 17687 17688 17689 17690 17691 17692 17693 17694 17695 17696 17697 17698 17699 17700 17701 17702 17703 17704 17705 17706 17707 17708 17709 17710 17711 17712 17713 17714 17715 17716 17717 17718 17719 17720 17721 17722 17723 17724 17725 17726 17727 17728 17729 17730 17731 17732 17733 17734 17735 17736 17737 17738 17739 17740 17741 17742 17743 17744 17745 17746 17747 17748 17749 17750 17751 17752 17753 17754 17755 17756 17757 17758 17759 17760 17761 17762 17763 17764 17765 17766 17767 17768 17769 17770 17771 17772 17773 17774 17775 17776 17777 17778 17779 17780 17781 17782 17783 17784 17785 17786 17787 17788 17789 17790 17791 17792 17793 17794 17795 17796 17797 17798 17799 17800 17801 17802 17803 17804 17805 17806 17807 17808 17809 17810 17811 17812 17813 17814 17815 17816 17817 17818 17819 17820 17821 17822 17823 17824 17825 17826 17827 17828 17829 17830 17831 17832 17833 17834 17835 17836 17837 17838 17839 17840 17841 17842 17843 17844 17845 17846 17847 17848 17849 17850 17851 17852 17853 17854 17855 17856 17857 17858 17859 17860 17861 17862 17863 17864 17865 17866 17867 17868 17869 17870 17871 17872 17873 17874 17875 17876 17877 17878 17879 17880 17881 17882 17883 17884 17885 17886 17887 17888 17889 17890 17891 17892 17893 17894 17895 17896 17897 17898 17899 17900 17901 17902 17903 17904 17905 17906 17907 17908 17909 17910 17911 17912 17913 17914 17915 17916 17917 17918 17919 17920 17921 17922 17923 17924 17925 17926 17927 17928 17929 17930 17931 17932 17933 17934 17935 17936 17937 17938 17939 17940 17941 17942 17943 17944 17945 17946 17947 17948 17949 17950 17951 17952 17953 17954 17955 17956 17957 17958 17959 17960 17961 17962 17963 17964 17965 17966 17967 17968 17969 17970 17971 17972 17973 17974 17975 17976 17977 17978 17979 17980 17981 17982 17983 17984 17985 17986 17987 17988 17989 17990 17991 17992 17993 17994 17995 17996 17997 17998 17999 18000 18001 18002 18003 18004 18005 18006 18007 18008 18009 18010 18011 18012 18013 18014 18015 18016 18017 18018 18019 18020 18021 18022 18023 18024 18025 18026 18027 18028 18029 18030 18031 18032 18033 18034 18035 18036 18037 18038 18039 18040 18041 18042 18043 18044 18045 18046 18047 18048 18049 18050 18051 18052 18053 18054 18055 18056 18057 18058 18059 18060 18061 18062 18063 18064 18065 18066 18067 18068 18069 18070 18071 18072 18073 18074 18075 18076 18077 18078 18079 18080 18081 18082 18083 18084 18085 18086 18087 18088 18089 18090 18091 18092 18093 18094 18095 18096 18097 18098 18099 18100 18101 18102 18103 18104 18105 18106 18107 18108 18109 18110 18111 18112 18113 18114 18115 18116 18117 18118 18119 18120 18121 18122 18123 18124 18125 18126 18127 18128 18129 18130 18131 18132 18133 18134 18135 18136 18137 18138 18139 18140 18141 18142 18143 18144 18145 18146 18147 18148 18149 18150 18151 18152 18153 18154 18155 18156 18157 18158 18159 18160 18161 18162 18163 18164 18165 18166 18167 18168 18169 18170 18171 18172 18173 18174 18175 18176 18177 18178 18179 18180 18181 18182 18183 18184 18185 18186 18187 18188 18189 18190 18191 18192 18193 18194 18195 18196 18197 18198 18199 18200 18201 18202 18203 18204 18205 18206 18207 18208 18209 18210 18211 18212 18213 18214 18215 18216 18217 18218 18219 18220 18221 18222 18223 18224 18225 18226 18227 18228 18229 18230 18231 18232 18233 18234 18235 18236 18237 18238 18239 18240 18241 18242 18243 18244 18245 18246 18247 18248 18249 18250 18251 18252 18253 18254 18255 18256 18257 18258 18259 18260 18261 18262 18263 18264 18265 18266 18267 18268 18269 18270 18271 18272 18273 18274 18275 18276 18277 18278 18279 18280 18281 18282 18283 18284 18285 18286 18287 18288 18289 18290 18291 18292 18293 18294 18295 18296 18297 18298 18299 18300 18301 18302 18303 18304 18305 18306 18307 18308 18309 18310 18311 18312 18313 18314 18315 18316 18317 18318 18319 18320 18321 18322 18323 18324 18325 18326 18327 18328 18329 18330 18331 18332 18333 18334 18335 18336 18337 18338 18339 18340 18341 18342 18343 18344 18345 18346 18347 18348 18349 18350 18351 18352 18353 18354 18355 18356 18357 18358 18359 18360 18361 18362 18363 18364 18365 18366 18367 18368 18369 18370 18371 18372 18373 18374 18375 18376 18377 18378 18379 18380 18381 18382 18383 18384 18385 18386 18387 18388 18389 18390 18391 18392 18393 18394 18395 18396 18397 18398 18399 18400 18401 18402 18403 18404 18405 18406 18407 18408 18409 18410 18411 18412 18413 18414 18415 18416 18417 18418 18419 18420 18421 18422 18423 18424 18425 18426 18427 18428 18429 18430 18431 18432 18433 18434 18435 18436 18437 18438 18439 18440 18441 18442 18443 18444 18445 18446 18447 18448 18449 18450 18451 18452 18453 18454 18455 18456 18457 18458 18459 18460 18461 18462 18463 18464 18465 18466 18467 18468 18469 18470 18471 18472 18473 18474 18475 18476 18477 18478 18479 18480 18481 18482 18483 18484 18485 18486 18487 18488 18489 18490 18491 18492 18493 18494 18495 18496 18497 18498 18499 18500 18501 18502 18503 18504 18505 18506 18507 18508 18509 18510 18511 18512 18513 18514 18515 18516 18517 18518 18519 18520 18521 18522 18523 18524 18525 18526 18527 18528 18529 18530 18531 18532 18533 18534 18535 18536 18537 18538 18539 18540 18541 18542 18543 18544 18545 18546 18547 18548 18549 18550 18551 18552 18553 18554 18555 18556 18557 18558 18559 18560 18561 18562 18563 18564 18565 18566 18567 18568 18569 18570 18571 18572 18573 18574 18575 18576 18577 18578 18579 18580 18581 18582 18583 18584 18585 18586 18587 18588 18589 18590 18591 18592 18593 18594 18595 18596 18597 18598 18599 18600 18601 18602 18603 18604 18605 18606 18607 18608 18609 18610 18611 18612 18613 18614 18615 18616 18617 18618 18619 18620 18621 18622 18623 18624 18625 18626 18627 18628 18629 18630 18631 18632 18633 18634 18635 18636 18637 18638 18639 18640 18641 18642 18643 18644 18645 18646 18647 18648 18649 18650 18651 18652 18653 18654 18655 18656 18657 18658 18659 18660 18661 18662 18663 18664 18665 18666 18667 18668 18669 18670 18671 18672 18673 18674 18675 18676 18677 18678 18679 18680 18681 18682 18683 18684 18685 18686 18687 18688 18689 18690 18691 18692 18693 18694 18695 18696 18697 18698 18699 18700 18701 18702 18703 18704 18705 18706 18707 18708 18709 18710 18711 18712 18713 18714 18715 18716 18717 18718 18719 18720 18721 18722 18723 18724 18725 18726 18727 18728 18729 18730 18731 18732 18733 18734 18735 18736 18737 18738 18739 18740 18741 18742 18743 18744 18745 18746 18747 18748 18749 18750 18751 18752 18753 18754 18755 18756 18757 18758 18759 18760 18761 18762 18763 18764 18765 18766 18767 18768 18769 18770 18771 18772 18773 18774 18775 18776 18777 18778 18779 18780 18781 18782 18783 18784 18785 18786 18787 18788 18789 18790 18791 18792 18793 18794 18795 18796 18797 18798 18799 18800 18801 18802 18803 18804 18805 18806 18807 18808 18809 18810 18811 18812 18813 18814 18815 18816 18817 18818 18819 18820 18821 18822 18823 18824 18825 18826 18827 18828 18829 18830 18831 18832 18833 18834 18835 18836 18837 18838 18839 18840 18841 18842 18843 18844 18845 18846 18847 18848 18849 18850 18851 18852 18853 18854 18855 18856 18857 18858 18859 18860 18861 18862 18863 18864 18865 18866 18867 18868 18869 18870 18871 18872 18873 18874 18875 18876 18877 18878 18879 18880 18881 18882 18883 18884 18885 18886 18887 18888 18889 18890 18891 18892 18893 18894 18895 18896 18897 18898 18899 18900 18901 18902 18903 18904 18905 18906 18907 18908 18909 18910 18911 18912 18913 18914 18915 18916 18917 18918 18919 18920 18921 18922 18923 18924 18925 18926 18927 18928 18929 18930 18931 18932 18933 18934 18935 18936 18937 18938 18939 18940 18941 18942 18943 18944 18945 18946 18947 18948 18949 18950 18951 18952 18953 18954 18955 18956 18957 18958 18959 18960 18961 18962 18963 18964 18965 18966 18967 18968 18969 18970 18971 18972 18973 18974 18975 18976 18977 18978 18979 18980 18981 18982 18983 18984 18985 18986 18987 18988 18989 18990 18991 18992 18993 18994 18995 18996 18997 18998 18999 19000 19001 19002 19003 19004 19005 19006 19007 19008 19009 19010 19011 19012 19013 19014 19015 19016 19017 19018 19019 19020 19021 19022 19023 19024 19025 19026 19027 19028 19029 19030 19031 19032 19033 19034 19035 19036 19037 19038 19039 19040 19041 19042 19043 19044 19045 19046 19047 19048 19049 19050 19051 19052 19053 19054 19055 19056 19057 19058 19059 19060 19061 19062 19063 19064 19065 19066 19067 19068 19069 19070 19071 19072 19073 19074 19075 19076 19077 19078 19079 19080 19081 19082 19083 19084 19085 19086 19087 19088 19089 19090 19091 19092 19093 19094 19095 19096 19097 19098 19099 19100 19101 19102 19103 19104 19105 19106 19107 19108 19109 19110 19111 19112 19113 19114 19115 19116 19117 19118 19119 19120 19121 19122 19123 19124 19125 19126 19127 19128 19129 19130 19131 19132 19133 19134 19135 19136 19137 19138 19139 19140 19141 19142 19143 19144 19145 19146 19147 19148 19149 19150 19151 19152 19153 19154 19155 19156 19157 19158 19159 19160 19161 19162 19163 19164 19165 19166 19167 19168 19169 19170 19171 19172 19173 19174 19175 19176 19177 19178 19179 19180 19181 19182 19183 19184 19185 19186 19187 19188 19189 19190 19191 19192 19193 19194 19195 19196 19197 19198 19199 19200 19201 19202 19203 19204 19205 19206 19207 19208 19209 19210 19211 19212 19213 19214 19215 19216 19217 19218 19219 19220 19221 19222 19223 19224 19225 19226 19227 19228 19229 19230 19231 19232 19233 19234 19235 19236 19237 19238 19239 19240 19241 19242 19243 19244 19245 19246 19247 19248 19249 19250 19251 19252 19253 19254 19255 19256 19257 19258 19259 19260 19261 19262 19263 19264 19265 19266 19267 19268 19269 19270 19271 19272 19273 19274 19275 19276 19277 19278 19279 19280 19281 19282 19283 19284 19285 19286 19287 19288 19289 19290 19291 19292 19293 19294 19295 19296 19297 19298 19299 19300 19301 19302 19303 19304 19305 19306 19307 19308 19309 19310 19311 19312 19313 19314 19315 19316 19317 19318 19319 19320 19321 19322 19323 19324 19325 19326 19327 19328 19329 19330 19331 19332 19333 19334 19335 19336 19337 19338 19339 19340 19341 19342 19343 19344 19345 19346 19347 19348 19349 19350 19351 19352 19353 19354 19355 19356 19357 19358 19359 19360 19361 19362 19363 19364 19365 19366 19367 19368 19369 19370 19371 19372 19373 19374 19375 19376 19377 19378 19379 19380 19381 19382 19383 19384 19385 19386 19387 19388 19389 19390 19391 19392 19393 19394 19395 19396 19397 19398 19399 19400 19401 19402 19403 19404 19405 19406 19407 19408 19409 19410 19411 19412 19413 19414 19415 19416 19417 19418 19419 19420 19421 19422 19423 19424 19425 19426 19427 19428 19429 19430 19431 19432 19433 19434 19435 19436 19437 19438 19439 19440 19441 19442 19443 19444 19445 19446 19447 19448 19449 19450 19451 19452 19453 19454 19455 19456 19457 19458 19459 19460 19461 19462 19463 19464 19465 19466 19467 19468 19469 19470 19471 19472 19473 19474 19475 19476 19477 19478 19479 19480 19481 19482 19483 19484 19485 19486 19487 19488 19489 19490 19491 19492 19493 19494 19495 19496 19497 19498 19499 19500 19501 19502 19503 19504 19505 19506 19507 19508 19509 19510 19511 19512 19513 19514 19515 19516 19517 19518 19519 19520 19521 19522 19523 19524 19525 19526 19527 19528 19529 19530 19531 19532 19533 19534 19535 19536 19537 19538 19539 19540 19541 19542 19543 19544 19545 19546 19547 19548 19549 19550 19551 19552 19553 19554 19555 19556 19557 19558 19559 19560 19561 19562 19563 19564 19565 19566 19567 19568 19569 19570 19571 19572 19573 19574 19575 19576 19577 19578 19579 19580 19581 19582 19583 19584 19585 19586 19587 19588 19589 19590 19591 19592 19593 19594 19595 19596 19597 19598 19599 19600 19601 19602 19603 19604 19605 19606 19607 19608 19609 19610 19611 19612 19613 19614 19615 19616 19617 19618 19619 19620 19621 19622 19623 19624 19625 19626 19627 19628 19629 19630 19631 19632 19633 19634 19635 19636 19637 19638 19639 19640 19641 19642 19643 19644 19645 19646 19647 19648 19649 19650 19651 19652 19653 19654 19655 19656 19657 19658 19659 19660 19661 19662 19663 19664 19665 19666 19667 19668 19669 19670 19671 19672 19673 19674 19675 19676 19677 19678 19679 19680 19681 19682 19683 19684 19685 19686 19687 19688 19689 19690 19691 19692 19693 19694 19695 19696 19697 19698 19699 19700 19701 19702 19703 19704 19705 19706 19707 19708 19709 19710 19711 19712 19713 19714 19715 19716 19717 19718 19719 19720 19721 19722 19723 19724 19725 19726 19727 19728 19729 19730 19731 19732 19733 19734 19735 19736 19737 19738 19739 19740 19741 19742 19743 19744 19745 19746 19747 19748 19749 19750 19751 19752 19753 19754 19755 19756 19757 19758 19759 19760 19761 19762 19763 19764 19765 19766 19767 19768 19769 19770 19771 19772 19773 19774 19775 19776 19777 19778 19779 19780 19781 19782 19783 19784 19785 19786 19787 19788 19789 19790 19791 19792 19793 19794 19795 19796 19797 19798 19799 19800 19801 19802 19803 19804 19805 19806 19807 19808 19809 19810 19811 19812 19813 19814 19815 19816 19817 19818 19819 19820 19821 19822 19823 19824 19825 19826 19827 19828 19829 19830 19831 19832 19833 19834 19835 19836 19837 19838 19839 19840 19841 19842 19843 19844 19845 19846 19847 19848 19849 19850 19851 19852 19853 19854 19855 19856 19857 19858 19859 19860 19861 19862 19863 19864 19865 19866 19867 19868 19869 19870 19871 19872 19873 19874 19875 19876 19877 19878 19879 19880 19881 19882 19883 19884 19885 19886 19887 19888 19889 19890 19891 19892 19893 19894 19895 19896 19897 19898 19899 19900 19901 19902 19903 19904 19905 19906 19907 19908 19909 19910 19911 19912 19913 19914 19915 19916 19917 19918 19919 19920 19921 19922 19923 19924 19925 19926 19927 19928 19929 19930 19931 19932 19933 19934 19935 19936 19937 19938 19939 19940 19941 19942 19943 19944 19945 19946 19947 19948 19949 19950 19951 19952 19953 19954 19955 19956 19957 19958 19959 19960 19961 19962 19963 19964 19965 19966 19967 19968 19969 19970 19971 19972 19973 19974 19975 19976 19977 19978 19979 19980 19981 19982 19983 19984 19985 19986 19987 19988 19989 19990 19991 19992 19993 19994 19995 19996 19997 19998 19999 20000 20001 20002 20003 20004 20005 20006 20007 20008 20009 20010 20011 20012 20013 20014 20015 20016 20017 20018 20019 20020 20021 20022 20023 20024 20025 20026 20027 20028 20029 20030 20031 20032 20033 20034 20035 20036 20037 20038 20039 20040 20041 20042 20043 20044 20045 20046 20047 20048 20049 20050 20051 20052 20053 20054 20055 20056 20057 20058 20059 20060 20061 20062 20063 20064 20065 20066 20067 20068 20069 20070 20071 20072 20073 20074 20075 20076 20077 20078 20079 20080 20081 20082 20083 20084 20085 20086 20087 20088 20089 20090 20091 20092 20093 20094 20095 20096 20097 20098 20099 20100 20101 20102 20103 20104 20105 20106 20107 20108 20109 20110 20111 20112 20113 20114 20115 20116 20117 20118 20119 20120 20121 20122 20123 20124 20125 20126 20127 20128 20129 20130 20131 20132 20133 20134 20135 20136 20137 20138 20139 20140 20141 20142 20143 20144 20145 20146 20147 20148 20149 20150 20151 20152 20153 20154 20155 20156 20157 20158 20159 20160 20161 20162 20163 20164 20165 20166 20167 20168 20169 20170 20171 20172 20173 20174 20175 20176 20177 20178 20179 20180 20181 20182 20183 20184 20185 20186 20187 20188 20189 20190 20191 20192 20193 20194 20195 20196 20197 20198 20199 20200 20201 20202 20203 20204 20205 20206 20207 20208 20209 20210 20211 20212 20213 20214 20215 20216 20217 20218 20219 20220 20221 20222 20223 20224 20225 20226 20227 20228 20229 20230 20231 20232 20233 20234 20235 20236 20237 20238 20239 20240 20241 20242 20243 20244 20245 20246 20247 20248 20249 20250 20251 20252 20253 20254 20255 20256 20257 20258 20259 20260 20261 20262 20263 20264 20265 20266 20267 20268 20269 20270 20271 20272 20273 20274 20275 20276 20277 20278 20279 20280 20281 20282 20283 20284 20285 20286 20287 20288 20289 20290 20291 20292 20293 20294 20295 20296 20297 20298 20299 20300 20301 20302 20303 20304 20305 20306 20307 20308 20309 20310 20311 20312 20313 20314 20315 20316 20317 20318 20319 20320 20321 20322 20323 20324 20325 20326 20327 20328 20329 20330 20331 20332 20333 20334 20335 20336 20337 20338 20339 20340 20341 20342 20343 20344 20345 20346 20347 20348 20349 20350 20351 20352 20353 20354 20355 20356 20357 20358 20359 20360 20361 20362 20363 20364 20365 20366 20367 20368 20369 20370 20371 20372 20373 20374 20375 20376 20377 20378 20379 20380 20381 20382 20383 20384 20385 20386 20387 20388 20389 20390 20391 20392 20393 20394 20395 20396 20397 20398 20399 20400 20401 20402 20403 20404 20405 20406 20407 20408 20409 20410 20411 20412 20413 20414 20415 20416 20417 20418 20419 20420 20421 20422 20423 20424 20425 20426 20427 20428 20429 20430 20431 20432 20433 20434 20435 20436 20437 20438 20439 20440 20441 20442 20443 20444 20445 20446 20447 20448 20449 20450 20451 20452 20453 20454 20455 20456 20457 20458 20459 20460 20461 20462 20463 20464 20465 20466 20467 20468 20469 20470 20471 20472 20473 20474 20475 20476 20477 20478 20479 20480 20481 20482 20483 20484 20485 20486 20487 20488 20489 20490 20491 20492 20493 20494 20495 20496 20497 20498 20499 20500 20501 20502 20503 20504 20505 20506 20507 20508 20509 20510 20511 20512 20513 20514 20515 20516 20517 20518 20519 20520 20521 20522 20523 20524 20525 20526 20527 20528 20529 20530 20531 20532 20533 20534 20535 20536 20537 20538 20539 20540 20541 20542 20543 20544 20545 20546 20547 20548 20549 20550 20551 20552 20553 20554 20555 20556 20557 20558 20559 20560 20561 20562 20563 20564 20565 20566 20567 20568 20569 20570 20571 20572 20573 20574 20575 20576 20577 20578 20579 20580 20581 20582 20583 20584 20585 20586 20587 20588 20589 20590 20591 20592 20593 20594 20595 20596 20597 20598 20599 20600 20601 20602 20603 20604 20605 20606 20607 20608 20609 20610 20611 20612 20613 20614 20615 20616 20617 20618 20619 20620 20621 20622 20623 20624 20625 20626 20627 20628 20629 20630 20631 20632 20633 20634 20635 20636 20637 20638 20639 20640 20641 20642 20643 20644 20645 20646 20647 20648 20649 20650 20651 20652 20653 20654 20655 20656 20657 20658 20659 20660 20661 20662 20663 20664 20665 20666 20667 20668 20669 20670 20671 20672 20673 20674 20675 20676 20677 20678 20679 20680 20681 20682 20683 20684 20685 20686 20687 20688 20689 20690 20691 20692 20693 20694 20695 20696 20697 20698 20699 20700 20701 20702 20703 20704 20705 20706 20707 20708 20709 20710 20711 20712 20713 20714 20715 20716 20717 20718 20719 20720 20721 20722 20723 20724 20725 20726 20727 20728 20729 20730 20731 20732 20733 20734 20735 20736 20737 20738 20739 20740 20741 20742 20743 20744 20745 20746 20747 20748 20749 20750 20751 20752 20753 20754 20755 20756 20757 20758 20759 20760 20761 20762 20763 20764 20765 20766 20767 20768 20769 20770 20771 20772 20773 20774 20775 20776 20777 20778 20779 20780 20781 20782 20783 20784 20785 20786 20787 20788 20789 20790 20791 20792 20793 20794 20795 20796 20797 20798 20799 20800 20801 20802 20803 20804 20805 20806 20807 20808 20809 20810 20811 20812 20813 20814 20815 20816 20817 20818 20819 20820 20821 20822 20823 20824 20825 20826 20827 20828 20829 20830 20831 20832 20833 20834 20835 20836 20837 20838 20839 20840 20841 20842 20843 20844 20845 20846 20847 20848 20849 20850 20851 20852 20853 20854 20855 20856 20857 20858 20859 20860 20861 20862 20863 20864 20865 20866 20867 20868 20869 20870 20871 20872 20873 20874 20875 20876 20877 20878 20879 20880 20881 20882 20883 20884 20885 20886 20887 20888 20889 20890 20891 20892 20893 20894 20895 20896 20897 20898 20899 20900 20901 20902 20903 20904 20905 20906 20907 20908 20909 20910 20911 20912 20913 20914 20915 20916 20917 20918 20919 20920 20921 20922 20923 20924 20925 20926 20927 20928 20929 20930 20931 20932 20933 20934 20935 20936 20937 20938 20939 20940 20941 20942 20943 20944 20945 20946 20947 20948 20949 20950 20951 20952 20953 20954 20955 20956 20957 20958 20959 20960 20961 20962 20963 20964 20965 20966 20967 20968 20969 20970 20971 20972 20973 20974 20975 20976 20977 20978 20979 20980 20981 20982 20983 20984 20985 20986 20987 20988 20989 20990 20991 20992 20993 20994 20995 20996 20997 20998 20999 21000 21001 21002 21003 21004 21005 21006 21007 21008 21009 21010 21011 21012 21013 21014 21015 21016 21017 21018 21019 21020 21021 21022 21023 21024 21025 21026 21027 21028 21029 21030 21031 21032 21033 21034 21035 21036 21037 21038 21039 21040 21041 21042 21043 21044 21045 21046 21047 21048 21049 21050 21051 21052 21053 21054 21055 21056 21057 21058 21059 21060 21061 21062 21063 21064 21065 21066 21067 21068 21069 21070 21071 21072 21073 21074 21075 21076 21077 21078 21079 21080 21081 21082 21083 21084 21085 21086 21087 21088 21089 21090 21091 21092 21093 21094 21095 21096 21097 21098 21099 21100 21101 21102 21103 21104 21105 21106 21107 21108 21109 21110 21111 21112 21113 21114 21115 21116 21117 21118 21119 21120 21121 21122 21123 21124 21125 21126 21127 21128 21129 21130 21131 21132 21133 21134 21135 21136 21137 21138 21139 21140 21141 21142 21143 21144 21145 21146 21147 21148 21149 21150 21151 21152 21153 21154 21155 21156 21157 21158 21159 21160 21161 21162 21163 21164 21165 21166 21167 21168 21169 21170 21171 21172 21173 21174 21175 21176 21177 21178 21179 21180 21181 21182 21183 21184 21185 21186 21187 21188 21189 21190 21191 21192 21193 21194 21195 21196 21197 21198 21199 21200 21201 21202 21203 21204 21205 21206 21207 21208 21209 21210 21211 21212 21213 21214 21215 21216 21217 21218 21219 21220 21221 21222 21223 21224 21225 21226 21227 21228 21229 21230 21231 21232 21233 21234 21235 21236 21237 21238 21239 21240 21241 21242 21243 21244 21245 21246 21247 21248 21249 21250 21251 21252 21253 21254 21255 21256 21257 21258 21259 21260 21261 21262 21263 21264 21265 21266 21267 21268 21269 21270 21271 21272 21273 21274 21275 21276 21277 21278 21279 21280 21281 21282 21283 21284 21285 21286 21287 21288 21289 21290 21291 21292 21293 21294 21295 21296 21297 21298 21299 21300 21301 21302 21303 21304 21305 21306 21307 21308 21309 21310 21311 21312 21313 21314 21315 21316 21317 21318 21319 21320 21321 21322 21323 21324 21325 21326 21327 21328 21329 21330 21331 21332 21333 21334 21335 21336 21337 21338 21339 21340 21341 21342 21343 21344 21345 21346 21347 21348 21349 21350 21351 21352 21353 21354 21355 21356 21357 21358 21359 21360 21361 21362 21363 21364 21365 21366 21367 21368 21369 21370 21371 21372 21373 21374 21375 21376 21377 21378 21379 21380 21381 21382 21383 21384 21385 21386 21387 21388 21389 21390 21391 21392 21393 21394 21395 21396 21397 21398 21399 21400 21401 21402 21403 21404 21405 21406 21407 21408 21409 21410 21411 21412 21413 21414 21415 21416 21417 21418 21419 21420 21421 21422 21423 21424 21425 21426 21427 21428 21429 21430 21431 21432 21433 21434 21435 21436 21437 21438 21439 21440 21441 21442 21443 21444 21445 21446 21447 21448 21449 21450 21451 21452 21453 21454 21455 21456 21457 21458 21459 21460 21461 21462 21463 21464 21465 21466 21467 21468 21469 21470 21471 21472 21473 21474 21475 21476 21477 21478 21479 21480 21481 21482 21483 21484 21485 21486 21487 21488 21489 21490 21491 21492 21493 21494 21495 21496 21497 21498 21499 21500 21501 21502 21503 21504 21505 21506 21507 21508 21509 21510 21511 21512 21513 21514 21515 21516 21517 21518 21519 21520 21521 21522 21523 21524 21525 21526 21527 21528 21529 21530 21531 21532 21533 21534 21535 21536 21537 21538 21539 21540 21541 21542 21543 21544 21545 21546 21547 21548 21549 21550 21551 21552 21553 21554 21555 21556 21557 21558 21559 21560 21561 21562 21563 21564 21565 21566 21567 21568 21569 21570 21571 21572 21573 21574 21575 21576 21577 21578 21579 21580 21581 21582 21583 21584 21585 21586 21587 21588 21589 21590 21591 21592 21593 21594 21595 21596 21597 21598 21599 21600 21601 21602 21603 21604 21605 21606 21607 21608 21609 21610 21611 21612 21613 21614 21615 21616 21617 21618 21619 21620 21621 21622 21623 21624 21625 21626 21627 21628 21629 21630 21631 21632 21633 21634 21635 21636 21637 21638 21639 21640 21641 21642 21643 21644 21645 21646 21647 21648 21649 21650 21651 21652 21653 21654 21655 21656 21657 21658 21659 21660 21661 21662 21663 21664 21665 21666 21667 21668 21669 21670 21671 21672 21673 21674 21675 21676 21677 21678 21679 21680 21681 21682 21683 21684 21685 21686 21687 21688 21689 21690 21691 21692 21693 21694 21695 21696 21697 21698 21699 21700 21701 21702 21703 21704 21705 21706 21707 21708 21709 21710 21711 21712 21713 21714 21715 21716 21717 21718 21719 21720 21721 21722 21723 21724 21725 21726 21727 21728 21729 21730 21731 21732 21733 21734 21735 21736 21737 21738 21739 21740 21741 21742 21743 21744 21745 21746 21747 21748 21749 21750 21751 21752 21753 21754 21755 21756 21757 21758 21759 21760 21761 21762 21763 21764 21765 21766 21767 21768 21769 21770 21771 21772 21773 21774 21775 21776 21777 21778 21779 21780 21781 21782 21783 21784 21785 21786 21787 21788 21789 21790 21791 21792 21793 21794 21795 21796 21797 21798 21799 21800 21801 21802 21803 21804 21805 21806 21807 21808 21809 21810 21811 21812 21813 21814 21815 21816 21817 21818 21819 21820 21821 21822 21823 21824 21825 21826 21827 21828 21829 21830 21831 21832 21833 21834 21835 21836 21837 21838 21839 21840 21841 21842 21843 21844 21845 21846 21847 21848 21849 21850 21851 21852 21853 21854 21855 21856 21857 21858 21859 21860 21861 21862 21863 21864 21865 21866 21867 21868 21869 21870 21871 21872 21873 21874 21875 21876 21877 21878 21879 21880 21881 21882 21883 21884 21885 21886 21887 21888 21889 21890 21891 21892 21893 21894 21895 21896 21897 21898 21899 21900 21901 21902 21903 21904 21905 21906 21907 21908 21909 21910 21911 21912 21913 21914 21915 21916 21917 21918 21919 21920 21921 21922 21923 21924 21925 21926 21927 21928 21929 21930 21931 21932 21933 21934 21935 21936 21937 21938 21939 21940 21941 21942 21943 21944 21945 21946 21947 21948 21949 21950 21951 21952 21953 21954 21955 21956 21957 21958 21959 21960 21961 21962 21963 21964 21965 21966 21967 21968 21969 21970 21971 21972 21973 21974 21975 21976 21977 21978 21979 21980 21981 21982 21983 21984 21985 21986 21987 21988 21989 21990 21991 21992 21993 21994 21995 21996 21997 21998 21999 22000 22001 22002 22003 22004 22005 22006 22007 22008 22009 22010 22011 22012 22013 22014 22015 22016 22017 22018 22019 22020 22021 22022 22023 22024 22025 22026 22027 22028 22029 22030 22031 22032 22033 22034 22035 22036 22037 22038 22039 22040 22041 22042 22043 22044 22045 22046 22047 22048 22049 22050 22051 22052 22053 22054 22055 22056 22057 22058 22059 22060 22061 22062 22063 22064 22065 22066 22067 22068 22069 22070 22071 22072 22073 22074 22075 22076 22077 22078 22079 22080 22081 22082 22083 22084 22085 22086 22087 22088 22089 22090 22091 22092 22093 22094 22095 22096 22097 22098 22099 22100 22101 22102 22103 22104 22105 22106 22107 22108 22109 22110 22111 22112 22113 22114 22115 22116 22117 22118 22119 22120 22121 22122 22123 22124 22125 22126 22127 22128 22129 22130 22131 22132 22133 22134 22135 22136 22137 22138 22139 22140 22141 22142 22143 22144 22145 22146 22147 22148 22149 22150 22151 22152 22153 22154 22155 22156 22157 22158 22159 22160 22161 22162 22163 22164 22165 22166 22167 22168 22169 22170 22171 22172 22173 22174 22175 22176 22177 22178 22179 22180 22181 22182 22183 22184 22185 22186 22187 22188 22189 22190 22191 22192 22193 22194 22195 22196 22197 22198 22199 22200 22201 22202 22203 22204 22205 22206 22207 22208 22209 22210 22211 22212 22213 22214 22215 22216 22217 22218 22219 22220 22221 22222 22223 22224 22225 22226 22227 22228 22229 22230 22231 22232 22233 22234 22235 22236 22237 22238 22239 22240 22241 22242 22243 22244 22245 22246 22247 22248 22249 22250 22251 22252 22253 22254 22255 22256 22257 22258 22259 22260 22261 22262 22263 22264 22265 22266 22267 22268 22269 22270 22271 22272 22273 22274 22275 22276 22277 22278 22279 22280 22281 22282 22283 22284 22285 22286 22287 22288 22289 22290 22291 22292 22293 22294 22295 22296 22297 22298 22299 22300 22301 22302 22303 22304 22305 22306 22307 22308 22309 22310 22311 22312 22313 22314 22315 22316 22317 22318 22319 22320 22321 22322 22323 22324 22325 22326 22327 22328 22329 22330 22331 22332 22333 22334 22335 22336 22337 22338 22339 22340 22341 22342 22343 22344 22345 22346 22347 22348 22349 22350 22351 22352 22353 22354 22355 22356 22357 22358 22359 22360 22361 22362 22363 22364 22365 22366 22367 22368 22369 22370 22371 22372 22373 22374 22375 22376 22377 22378 22379 22380 22381 22382 22383 22384 22385 22386 22387 22388 22389 22390 22391 22392 22393 22394 22395 22396 22397 22398 22399 22400 22401 22402 22403 22404 22405 22406 22407 22408 22409 22410 22411 22412 22413 22414 22415 22416 22417 22418 22419 22420 22421 22422 22423 22424 22425 22426 22427 22428 22429 22430 22431 22432 22433 22434 22435 22436 22437 22438 22439 22440 22441 22442 22443 22444 22445 22446 22447 22448 22449 22450 22451 22452 22453 22454 22455 22456 22457 22458 22459 22460 22461 22462 22463 22464 22465 22466 22467 22468 22469 22470 22471 22472 22473 22474 22475 22476 22477 22478 22479 22480 22481 22482 22483 22484 22485 22486 22487 22488 22489 22490 22491 22492 22493 22494 22495 22496 22497 22498 22499 22500 22501 22502 22503 22504 22505 22506 22507 22508 22509 22510 22511 22512 22513 22514 22515 22516 22517 22518 22519 22520 22521 22522 22523 22524 22525 22526 22527 22528 22529 22530 22531 22532 22533 22534 22535 22536 22537 22538 22539 22540 22541 22542 22543 22544 22545 22546 22547 22548 22549 22550 22551 22552 22553 22554 22555 22556 22557 22558 22559 22560 22561 22562 22563 22564 22565 22566 22567 22568 22569 22570 22571 22572 22573 22574 22575 22576 22577 22578 22579 22580 22581 22582 22583 22584 22585 22586 22587 22588 22589 22590 22591 22592 22593 22594 22595 22596 22597 22598 22599 22600 22601 22602 22603 22604 22605 22606 22607 22608 22609 22610 22611 22612 22613 22614 22615 22616 22617 22618 22619 22620 22621 22622 22623 22624 22625 22626 22627 22628 22629 22630 22631 22632 22633 22634 22635 22636 22637 22638 22639 22640 22641 22642 22643 22644 22645 22646 22647 22648 22649 22650 22651 22652 22653 22654 22655 22656 22657 22658 22659 22660 22661 22662 22663 22664 22665 22666 22667 22668 22669 22670 22671 22672 22673 22674 22675 22676 22677 22678 22679 22680 22681 22682 22683 22684 22685 22686 22687 22688 22689 22690 22691 22692 22693 22694 22695 22696 22697 22698 22699 22700 22701 22702 22703 22704 22705 22706 22707 22708 22709 22710 22711 22712 22713 22714 22715 22716 22717 22718 22719 22720 22721 22722 22723 22724 22725 22726 22727 22728 22729 22730 22731 22732 22733 22734 22735 22736 22737 22738 22739 22740 22741 22742 22743 22744 22745 22746 22747 22748 22749 22750 22751 22752 22753 22754 22755 22756 22757 22758 22759 22760 22761 22762 22763 22764 22765 22766 22767 22768 22769 22770 22771 22772 22773 22774 22775 22776 22777 22778 22779 22780 22781 22782 22783 22784 22785 22786 22787 22788 22789 22790 22791 22792 22793 22794 22795 22796 22797 22798 22799 22800 22801 22802 22803 22804 22805 22806 22807 22808 22809 22810 22811 22812 22813 22814 22815 22816 22817 22818 22819 22820 22821 22822 22823 22824 22825 22826 22827 22828 22829 22830 22831 22832 22833 22834 22835 22836 22837 22838 22839 22840 22841 22842 22843 22844 22845 22846 22847 22848 22849 22850 22851 22852 22853 22854 22855 22856 22857 22858 22859 22860 22861 22862 22863 22864 22865 22866 22867 22868 22869 22870 22871 22872 22873 22874 22875 22876 22877 22878 22879 22880 22881 22882 22883 22884 22885 22886 22887 22888 22889 22890 22891 22892 22893 22894 22895 22896 22897 22898 22899 22900 22901 22902 22903 22904 22905 22906 22907 22908 22909 22910 22911 22912 22913 22914 22915 22916 22917 22918 22919 22920 22921 22922 22923 22924 22925 22926 22927 22928 22929 22930 22931 22932 22933 22934 22935 22936 22937 22938 22939 22940 22941 22942 22943 22944 22945 22946 22947 22948 22949 22950 22951 22952 22953 22954 22955 22956 22957 22958 22959 22960 22961 22962 22963 22964 22965 22966 22967 22968 22969 22970 22971 22972 22973 22974 22975 22976 22977 22978 22979 22980 22981 22982 22983 22984 22985 22986 22987 22988 22989 22990 22991 22992 22993 22994 22995 22996 22997 22998 22999 23000 23001 23002 23003 23004 23005 23006 23007 23008 23009 23010 23011 23012 23013 23014 23015 23016 23017 23018 23019 23020 23021 23022 23023 23024 23025 23026 23027 23028 23029 23030 23031 23032 23033 23034 23035 23036 23037 23038 23039 23040 23041 23042 23043 23044 23045 23046 23047 23048 23049 23050 23051 23052 23053 23054 23055 23056 23057 23058 23059 23060 23061 23062 23063 23064 23065 23066 23067 23068 23069 23070 23071 23072 23073 23074 23075 23076 23077 23078 23079 23080 23081 23082 23083 23084 23085 23086 23087 23088 23089 23090 23091 23092 23093 23094 23095 23096 23097 23098 23099 23100 23101 23102 23103 23104 23105 23106 23107 23108 23109 23110 23111 23112 23113 23114 23115 23116 23117 23118 23119 23120 23121 23122 23123 23124 23125 23126 23127 23128 23129 23130 23131 23132 23133 23134 23135 23136 23137 23138 23139 23140 23141 23142 23143 23144 23145 23146 23147 23148 23149 23150 23151 23152 23153 23154 23155 23156 23157 23158 23159 23160 23161 23162 23163 23164 23165 23166 23167 23168 23169 23170 23171 23172 23173 23174 23175 23176 23177 23178 23179 23180 23181 23182 23183 23184 23185 23186 23187 23188 23189 23190 23191 23192 23193 23194 23195 23196 23197 23198 23199 23200 23201 23202 23203 23204 23205 23206 23207 23208 23209 23210 23211 23212 23213 23214 23215 23216 23217 23218 23219 23220 23221 23222 23223 23224 23225 23226 23227 23228 23229 23230 23231 23232 23233 23234 23235 23236 23237 23238 23239 23240 23241 23242 23243 23244 23245 23246 23247 23248 23249 23250 23251 23252 23253 23254 23255 23256 23257 23258 23259 23260 23261 23262 23263 23264 23265 23266 23267 23268 23269 23270 23271 23272 23273 23274 23275 23276 23277 23278 23279 23280 23281 23282 23283 23284 23285 23286 23287 23288 23289 23290 23291 23292 23293 23294 23295 23296 23297 23298 23299 23300 23301 23302 23303 23304 23305 23306 23307 23308 23309 23310 23311 23312 23313 23314 23315 23316 23317 23318 23319 23320 23321 23322 23323 23324 23325 23326 23327 23328 23329 23330 23331 23332 23333 23334 23335 23336 23337 23338 23339 23340 23341 23342 23343 23344 23345 23346 23347 23348 23349 23350 23351 23352 23353 23354 23355 23356 23357 23358 23359 23360 23361 23362 23363 23364 23365 23366 23367 23368 23369 23370 23371 23372 23373 23374 23375 23376 23377 23378 23379 23380 23381 23382 23383 23384 23385 23386 23387 23388 23389 23390 23391 23392 23393 23394 23395 23396 23397 23398 23399 23400 23401 23402 23403 23404 23405 23406 23407 23408 23409 23410 23411 23412 23413 23414 23415 23416 23417 23418 23419 23420 23421 23422 23423 23424 23425 23426 23427 23428 23429 23430 23431 23432 23433 23434 23435 23436 23437 23438 23439 23440 23441 23442 23443 23444 23445 23446 23447 23448 23449 23450 23451 23452 23453 23454 23455 23456 23457 23458 23459 23460 23461 23462 23463 23464 23465 23466 23467 23468 23469 23470 23471 23472 23473 23474 23475 23476 23477 23478 23479 23480 23481 23482 23483 23484 23485 23486 23487 23488 23489 23490 23491 23492 23493 23494 23495 23496 23497 23498 23499 23500 23501 23502 23503 23504 23505 23506 23507 23508 23509 23510 23511 23512 23513 23514 23515 23516 23517 23518 23519 23520 23521 23522 23523 23524 23525 23526 23527 23528 23529 23530 23531 23532 23533 23534 23535 23536 23537 23538 23539 23540 23541 23542 23543 23544 23545 23546 23547 23548 23549 23550 23551 23552 23553 23554 23555 23556 23557 23558 23559 23560 23561 23562 23563 23564 23565 23566 23567 23568 23569 23570 23571 23572 23573 23574 23575 23576 23577 23578 23579 23580 23581 23582 23583 23584 23585 23586 23587 23588 23589 23590 23591 23592 23593 23594 23595 23596 23597 23598 23599 23600 23601 23602 23603 23604 23605 23606 23607 23608 23609 23610 23611 23612 23613 23614 23615 23616 23617 23618 23619 23620 23621 23622 23623 23624 23625 23626 23627 23628 23629 23630 23631 23632 23633 23634 23635 23636 23637 23638 23639 23640 23641 23642 23643 23644 23645 23646 23647 23648 23649 23650 23651 23652 23653 23654 23655 23656 23657 23658 23659 23660 23661 23662 23663 23664 23665 23666 23667 23668 23669 23670 23671 23672 23673 23674 23675 23676 23677 23678 23679 23680 23681 23682 23683 23684 23685 23686 23687 23688 23689 23690 23691 23692 23693 23694 23695 23696 23697 23698 23699 23700 23701 23702 23703 23704 23705 23706 23707 23708 23709 23710 23711 23712 23713 23714 23715 23716 23717 23718 23719 23720 23721 23722 23723 23724 23725 23726 23727 23728 23729 23730 23731 23732 23733 23734 23735 23736 23737 23738 23739 23740 23741 23742 23743 23744 23745 23746 23747 23748 23749 23750 23751 23752 23753 23754 23755 23756 23757 23758 23759 23760 23761 23762 23763 23764 23765 23766 23767 23768 23769 23770 23771 23772 23773 23774 23775 23776 23777 23778 23779 23780 23781 23782 23783 23784 23785 23786 23787 23788 23789 23790 23791 23792 23793 23794 23795 23796 23797 23798 23799 23800 23801 23802 23803 23804 23805 23806 23807 23808 23809 23810 23811 23812 23813 23814 23815 23816 23817 23818 23819 23820 23821 23822 23823 23824 23825 23826 23827 23828 23829 23830 23831 23832 23833 23834 23835 23836 23837 23838 23839 23840 23841 23842 23843 23844 23845 23846 23847 23848 23849 23850 23851 23852 23853 23854 23855 23856 23857 23858 23859 23860 23861 23862 23863 23864 23865 23866 23867 23868 23869 23870 23871 23872 23873 23874 23875 23876 23877 23878 23879 23880 23881 23882 23883 23884 23885 23886 23887 23888 23889 23890 23891 23892 23893 23894 23895 23896 23897 23898 23899 23900 23901 23902 23903 23904 23905 23906 23907 23908 23909 23910 23911 23912 23913 23914 23915 23916 23917 23918 23919 23920 23921 23922 23923 23924 23925 23926 23927 23928 23929 23930 23931 23932 23933 23934 23935 23936 23937 23938 23939 23940 23941 23942 23943 23944 23945 23946 23947 23948 23949 23950 23951 23952 23953 23954 23955 23956 23957 23958 23959 23960 23961 23962 23963 23964 23965 23966 23967 23968 23969 23970 23971 23972 23973 23974 23975 23976 23977 23978 23979 23980 23981 23982 23983 23984 23985 23986 23987 23988 23989 23990 23991 23992 23993 23994 23995 23996 23997 23998 23999 24000 24001 24002 24003 24004 24005 24006 24007 24008 24009 24010 24011 24012 24013 24014 24015 24016 24017 24018 24019 24020 24021 24022 24023 24024 24025 24026 24027 24028 24029 24030 24031 24032 24033 24034 24035 24036 24037 24038 24039 24040 24041 24042 24043 24044 24045 24046 24047 24048 24049 24050 24051 24052 24053 24054 24055 24056 24057 24058 24059 24060 24061 24062 24063 24064 24065 24066 24067 24068 24069 24070 24071 24072 24073 24074 24075 24076 24077 24078 24079 24080 24081 24082 24083 24084 24085 24086 24087 24088 24089 24090 24091 24092 24093 24094 24095 24096 24097 24098 24099 24100 24101 24102 24103 24104 24105 24106 24107 24108 24109 24110 24111 24112 24113 24114 24115 24116 24117 24118 24119 24120 24121 24122 24123 24124 24125 24126 24127 24128 24129 24130 24131 24132 24133 24134 24135 24136 24137 24138 24139 24140 24141 24142 24143 24144 24145 24146 24147 24148 24149 24150 24151 24152 24153 24154 24155 24156 24157 24158 24159 24160 24161 24162 24163 24164 24165 24166 24167 24168 24169 24170 24171 24172 24173 24174 24175 24176 24177 24178 24179 24180 24181 24182 24183 24184 24185 24186 24187 24188 24189 24190 24191 24192 24193 24194 24195 24196 24197 24198 24199 24200 24201 24202 24203 24204 24205 24206 24207 24208 24209 24210 24211 24212 24213 24214 24215 24216 24217 24218 24219 24220 24221 24222 24223 24224 24225 24226 24227 24228 24229 24230 24231 24232 24233 24234 24235 24236 24237 24238 24239 24240 24241 24242 24243 24244 24245 24246 24247 24248 24249 24250 24251 24252 24253 24254 24255 24256 24257 24258 24259 24260 24261 24262 24263 24264 24265 24266 24267 24268 24269 24270 24271 24272 24273 24274 24275 24276 24277 24278 24279 24280 24281 24282 24283 24284 24285 24286 24287 24288 24289 24290 24291 24292 24293 24294 24295 24296 24297 24298 24299 24300 24301 24302 24303 24304 24305 24306 24307 24308 24309 24310 24311 24312 24313 24314 24315 24316 24317 24318 24319 24320 24321 24322 24323 24324 24325 24326 24327 24328 24329 24330 24331 24332 24333 24334 24335 24336 24337 24338 24339 24340 24341 24342 24343 24344 24345 24346 24347 24348 24349 24350 24351 24352 24353 24354 24355 24356 24357 24358 24359 24360 24361 24362 24363 24364 24365 24366 24367 24368 24369 24370 24371 24372 24373 24374 24375 24376 24377 24378 24379 24380 24381 24382 24383 24384 24385 24386 24387 24388 24389 24390 24391 24392 24393 24394 24395 24396 24397 24398 24399 24400 24401 24402 24403 24404 24405 24406 24407 24408 24409 24410 24411 24412 24413 24414 24415 24416 24417 24418 24419 24420 24421 24422 24423 24424 24425 24426 24427 24428 24429 24430 24431 24432 24433 24434 24435 24436 24437 24438 24439 24440 24441 24442 24443 24444 24445 24446 24447 24448 24449 24450 24451 24452 24453 24454 24455 24456 24457 24458 24459 24460 24461 24462 24463 24464 24465 24466 24467 24468 24469 24470 24471 24472 24473 24474 24475 24476 24477 24478 24479 24480 24481 24482 24483 24484 24485 24486 24487 24488 24489 24490 24491 24492 24493 24494 24495 24496 24497 24498 24499 24500 24501 24502 24503 24504 24505 24506 24507 24508 24509 24510 24511 24512 24513 24514 24515 24516 24517 24518 24519 24520 24521 24522 24523 24524 24525 24526 24527 24528 24529 24530 24531 24532 24533 24534 24535 24536 24537 24538 24539 24540 24541 24542 24543 24544 24545 24546 24547 24548 24549 24550 24551 24552 24553 24554 24555 24556 24557 24558 24559 24560 24561 24562 24563 24564 24565 24566 24567 24568 24569 24570 24571 24572 24573 24574 24575 24576 24577 24578 24579 24580 24581 24582 24583 24584 24585 24586 24587 24588 24589 24590 24591 24592 24593 24594 24595 24596 24597 24598 24599 24600 24601 24602 24603 24604 24605 24606 24607 24608 24609 24610 24611 24612 24613 24614 24615 24616 24617 24618 24619 24620 24621 24622 24623 24624 24625 24626 24627 24628 24629 24630 24631 24632 24633 24634 24635 24636 24637 24638 24639 24640 24641 24642 24643 24644 24645 24646 24647 24648 24649 24650 24651 24652 24653 24654 24655 24656 24657 24658 24659 24660 24661 24662 24663 24664 24665 24666 24667 24668 24669 24670 24671 24672 24673 24674 24675 24676 24677 24678 24679 24680 24681 24682 24683 24684 24685 24686 24687 24688 24689 24690 24691 24692 24693 24694 24695 24696 24697 24698 24699 24700 24701 24702 24703 24704 24705 24706 24707 24708 24709 24710 24711 24712 24713 24714 24715 24716 24717 24718 24719 24720 24721 24722 24723 24724 24725 24726 24727 24728 24729 24730 24731 24732 24733 24734 24735 24736 24737 24738 24739 24740 24741 24742 24743 24744 24745 24746 24747 24748 24749 24750 24751 24752 24753 24754 24755 24756 24757 24758 24759 24760 24761 24762 24763 24764 24765 24766 24767 24768 24769 24770 24771 24772 24773 24774 24775 24776 24777 24778 24779 24780 24781 24782 24783 24784 24785 24786 24787 24788 24789 24790 24791 24792 24793 24794 24795 24796 24797 24798 24799 24800 24801 24802 24803 24804 24805 24806 24807 24808 24809 24810 24811 24812 24813 24814 24815 24816 24817 24818 24819 24820 24821 24822 24823 24824 24825 24826 24827 24828 24829 24830 24831 24832 24833 24834 24835 24836 24837 24838 24839 24840 24841 24842 24843 24844 24845 24846 24847 24848 24849 24850 24851 24852 24853 24854 24855 24856 24857 24858 24859 24860 24861 24862 24863 24864 24865 24866 24867 24868 24869 24870 24871 24872 24873 24874 24875 24876 24877 24878 24879 24880 24881 24882 24883 24884 24885 24886 24887 24888 24889 24890 24891 24892 24893 24894 24895 24896 24897 24898 24899 24900 24901 24902 24903 24904 24905 24906 24907 24908 24909 24910 24911 24912 24913 24914 24915 24916 24917 24918 24919 24920 24921 24922 24923 24924 24925 24926 24927 24928 24929 24930 24931 24932 24933 24934 24935 24936 24937 24938 24939 24940 24941 24942 24943 24944 24945 24946 24947 24948 24949 24950 24951 24952 24953 24954 24955 24956 24957 24958 24959 24960 24961 24962 24963 24964 24965 24966 24967 24968 24969 24970 24971 24972 24973 24974 24975 24976 24977 24978 24979 24980 24981 24982 24983 24984 24985 24986 24987 24988 24989 24990 24991 24992 24993 24994 24995 24996 24997 24998 24999 25000 25001 25002 25003 25004 25005 25006 25007 25008 25009 25010 25011 25012 25013 25014 25015 25016 25017 25018 25019 25020 25021 25022 25023 25024 25025 25026 25027 25028 25029 25030 25031 25032 25033 25034 25035 25036 25037 25038 25039 25040 25041 25042 25043 25044 25045 25046 25047 25048 25049 25050 25051 25052 25053 25054 25055 25056 25057 25058 25059 25060 25061 25062 25063 25064 25065 25066 25067 25068 25069 25070 25071 25072 25073 25074 25075 25076 25077 25078 25079 25080 25081 25082 25083 25084 25085 25086 25087 25088 25089 25090 25091 25092 25093 25094 25095 25096 25097 25098 25099 25100 25101 25102 25103 25104 25105 25106 25107 25108 25109 25110 25111 25112 25113 25114 25115 25116 25117 25118 25119 25120 25121 25122 25123 25124 25125 25126 25127 25128 25129 25130 25131 25132 25133 25134 25135 25136 25137 25138 25139 25140 25141 25142 25143 25144 25145 25146 25147 25148 25149 25150 25151 25152 25153 25154 25155 25156 25157 25158 25159 25160 25161 25162 25163 25164 25165 25166 25167 25168 25169 25170 25171 25172 25173 25174 25175 25176 25177 25178 25179 25180 25181 25182 25183 25184 25185 25186 25187 25188 25189 25190 25191 25192 25193 25194 25195 25196 25197 25198 25199 25200 25201 25202 25203 25204 25205 25206 25207 25208 25209 25210 25211 25212 25213 25214 25215 25216 25217 25218 25219 25220 25221 25222 25223 25224 25225 25226 25227 25228 25229 25230 25231 25232 25233 25234 25235 25236 25237 25238 25239 25240 25241 25242 25243 25244 25245 25246 25247 25248 25249 25250 25251 25252 25253 25254 25255 25256 25257 25258 25259 25260 25261 25262 25263 25264 25265 25266 25267 25268 25269 25270 25271 25272 25273 25274 25275 25276 25277 25278 25279 25280 25281 25282 25283 25284 25285 25286 25287 25288 25289 25290 25291 25292 25293 25294 25295 25296 25297 25298 25299 25300 25301 25302 25303 25304 25305 25306 25307 25308 25309 25310 25311 25312 25313 25314 25315 25316 25317 25318 25319 25320 25321 25322 25323 25324 25325 25326 25327 25328 25329 25330 25331 25332 25333 25334 25335 25336 25337 25338 25339 25340 25341 25342 25343 25344 25345 25346 25347 25348 25349 25350 25351 25352 25353 25354 25355 25356 25357 25358 25359 25360 25361 25362 25363 25364 25365 25366 25367 25368 25369 25370 25371 25372 25373 25374 25375 25376 25377 25378 25379 25380 25381 25382 25383 25384 25385 25386 25387 25388 25389 25390 25391 25392 25393 25394 25395 25396 25397 25398 25399 25400 25401 25402 25403 25404 25405 25406 25407 25408 25409 25410 25411 25412 25413 25414 25415 25416 25417 25418 25419 25420 25421 25422 25423 25424 25425 25426 25427 25428 25429 25430 25431 25432 25433 25434 25435 25436 25437 25438 25439 25440 25441 25442 25443 25444 25445 25446 25447 25448 25449 25450 25451 25452 25453 25454 25455 25456 25457 25458 25459 25460 25461 25462 25463 25464 25465 25466 25467 25468 25469 25470 25471 25472 25473 25474 25475 25476 25477 25478 25479 25480 25481 25482 25483 25484 25485 25486 25487 25488 25489 25490 25491 25492 25493 25494 25495 25496 25497 25498 25499 25500 25501 25502 25503 25504 25505 25506 25507 25508 25509 25510 25511 25512 25513 25514 25515 25516 25517 25518 25519 25520 25521 25522 25523 25524 25525 25526 25527 25528 25529 25530 25531 25532 25533 25534 25535 25536 25537 25538 25539 25540 25541 25542 25543 25544 25545 25546 25547 25548 25549 25550 25551 25552 25553 25554 25555 25556 25557 25558 25559 25560 25561 25562 25563 25564 25565 25566 25567 25568 25569 25570 25571 25572 25573 25574 25575 25576 25577 25578 25579 25580 25581 25582 25583 25584 25585 25586 25587 25588 25589 25590 25591 25592 25593 25594 25595 25596 25597 25598 25599 25600 25601 25602 25603 25604 25605 25606 25607 25608 25609 25610 25611 25612 25613 25614 25615 25616 25617 25618 25619 25620 25621 25622 25623 25624 25625 25626 25627 25628 25629 25630 25631 25632 25633 25634 25635 25636 25637 25638 25639 25640 25641 25642 25643 25644 25645 25646 25647 25648 25649 25650 25651 25652 25653 25654 25655 25656 25657 25658 25659 25660 25661 25662 25663 25664 25665 25666 25667 25668 25669 25670 25671 25672 25673 25674 25675 25676 25677 25678 25679 25680 25681 25682 25683 25684 25685 25686 25687 25688 25689 25690 25691 25692 25693 25694 25695 25696 25697 25698 25699 25700 25701 25702 25703 25704 25705 25706 25707 25708 25709 25710 25711 25712 25713 25714 25715 25716 25717 25718 25719 25720 25721 25722 25723 25724 25725 25726 25727 25728 25729 25730 25731 25732 25733 25734 25735 25736 25737 25738 25739 25740 25741 25742 25743 25744 25745 25746 25747 25748 25749 25750 25751 25752 25753 25754 25755 25756 25757 25758 25759 25760 25761 25762 25763 25764 25765 25766 25767 25768 25769 25770 25771 25772 25773 25774 25775 25776 25777 25778 25779 25780 25781 25782 25783 25784 25785 25786 25787 25788 25789 25790 25791 25792 25793 25794 25795 25796 25797 25798 25799 25800 25801 25802 25803 25804 25805 25806 25807 25808 25809 25810 25811 25812 25813 25814 25815 25816 25817 25818 25819 25820 25821 25822 25823 25824 25825 25826 25827 25828 25829 25830 25831 25832 25833 25834 25835 25836 25837 25838 25839 25840 25841 25842 25843 25844 25845 25846 25847 25848 25849 25850 25851 25852 25853 25854 25855 25856 25857 25858 25859 25860 25861 25862 25863 25864 25865 25866 25867 25868 25869 25870 25871 25872 25873 25874 25875 25876 25877 25878 25879 25880 25881 25882 25883 25884 25885 25886 25887 25888 25889 25890 25891 25892 25893 25894 25895 25896 25897 25898 25899 25900 25901 25902 25903 25904 25905 25906 25907 25908 25909 25910 25911 25912 25913 25914 25915 25916 25917 25918 25919 25920 25921 25922 25923 25924 25925 25926 25927 25928 25929 25930 25931 25932 25933 25934 25935 25936 25937 25938 25939 25940 25941 25942 25943 25944 25945 25946 25947 25948 25949 25950 25951 25952 25953 25954 25955 25956 25957 25958 25959 25960 25961 25962 25963 25964 25965 25966 25967 25968 25969 25970 25971 25972 25973 25974 25975 25976 25977 25978 25979 25980 25981 25982 25983 25984 25985 25986 25987 25988 25989 25990 25991 25992 25993 25994 25995 25996 25997 25998 25999 26000 26001 26002 26003 26004 26005 26006 26007 26008 26009 26010 26011 26012 26013 26014 26015 26016 26017 26018 26019 26020 26021 26022 26023 26024 26025 26026 26027 26028 26029 26030 26031 26032 26033 26034 26035 26036 26037 26038 26039 26040 26041 26042 26043 26044 26045 26046 26047 26048 26049 26050 26051 26052 26053 26054 26055 26056 26057 26058 26059 26060 26061 26062 26063 26064 26065 26066 26067 26068 26069 26070 26071 26072 26073 26074 26075 26076 26077 26078 26079 26080 26081 26082 26083 26084 26085 26086 26087 26088 26089 26090 26091 26092 26093 26094 26095 26096 26097 26098 26099 26100 26101 26102 26103 26104 26105 26106 26107 26108 26109 26110 26111 26112 26113 26114 26115 26116 26117 26118 26119 26120 26121 26122 26123 26124 26125 26126 26127 26128 26129 26130 26131 26132 26133 26134 26135 26136 26137 26138 26139 26140 26141 26142 26143 26144 26145 26146 26147 26148 26149 26150 26151 26152 26153 26154 26155 26156 26157 26158 26159 26160 26161 26162 26163 26164 26165 26166 26167 26168 26169 26170 26171 26172 26173 26174 26175 26176 26177 26178 26179 26180 26181 26182 26183 26184 26185 26186 26187 26188 26189 26190 26191 26192 26193 26194 26195 26196 26197 26198 26199 26200 26201 26202 26203 26204 26205 26206 26207 26208 26209 26210 26211 26212 26213 26214 26215 26216 26217 26218 26219 26220 26221 26222 26223 26224 26225 26226 26227 26228 26229 26230 26231 26232 26233 26234 26235 26236 26237 26238 26239 26240 26241 26242 26243 26244 26245 26246 26247 26248 26249 26250 26251 26252 26253 26254 26255 26256 26257 26258 26259 26260 26261 26262 26263 26264 26265 26266 26267 26268 26269 26270 26271 26272 26273 26274 26275 26276 26277 26278 26279 26280 26281 26282 26283 26284 26285 26286 26287 26288 26289 26290 26291 26292 26293 26294 26295 26296 26297 26298 26299 26300 26301 26302 26303 26304 26305 26306 26307 26308 26309 26310 26311 26312 26313 26314 26315 26316 26317 26318 26319 26320 26321 26322 26323 26324 26325 26326 26327 26328 26329 26330 26331 26332 26333 26334 26335 26336 26337 26338 26339 26340 26341 26342 26343 26344 26345 26346 26347 26348 26349 26350 26351 26352 26353 26354 26355 26356 26357 26358 26359 26360 26361 26362 26363 26364 26365 26366 26367 26368 26369 26370 26371 26372 26373 26374 26375 26376 26377 26378 26379 26380 26381 26382 26383 26384 26385 26386 26387 26388 26389 26390 26391 26392 26393 26394 26395 26396 26397 26398 26399 26400 26401 26402 26403 26404 26405 26406 26407 26408 26409 26410 26411 26412 26413 26414 26415 26416 26417 26418 26419 26420 26421 26422 26423 26424 26425 26426 26427 26428 26429 26430 26431 26432 26433 26434 26435 26436 26437 26438 26439 26440 26441 26442 26443 26444 26445 26446 26447 26448 26449 26450 26451 26452 26453 26454 26455 26456 26457 26458 26459 26460 26461 26462 26463 26464 26465 26466 26467 26468 26469 26470 26471 26472 26473 26474 26475 26476 26477 26478 26479 26480 26481 26482 26483 26484 26485 26486 26487 26488 26489 26490 26491 26492 26493 26494 26495 26496 26497 26498 26499 26500 26501 26502 26503 26504 26505 26506 26507 26508 26509 26510 26511 26512 26513 26514 26515 26516 26517 26518 26519 26520 26521 26522 26523 26524 26525 26526 26527 26528 26529 26530 26531 26532 26533 26534 26535 26536 26537 26538 26539 26540 26541 26542 26543 26544 26545 26546 26547 26548 26549 26550 26551 26552 26553 26554 26555 26556 26557 26558 26559 26560 26561 26562 26563 26564 26565 26566 26567 26568 26569 26570 26571 26572 26573 26574 26575 26576 26577 26578 26579 26580 26581 26582 26583 26584 26585 26586 26587 26588 26589 26590 26591 26592 26593 26594 26595 26596 26597 26598 26599 26600 26601 26602 26603 26604 26605 26606 26607 26608 26609 26610 26611 26612 26613 26614 26615 26616 26617 26618 26619 26620 26621 26622 26623 26624 26625 26626 26627 26628 26629 26630 26631 26632 26633 26634 26635 26636 26637 26638 26639 26640 26641 26642 26643 26644 26645 26646 26647 26648 26649 26650 26651 26652 26653 26654 26655 26656 26657 26658 26659 26660 26661 26662 26663 26664 26665 26666 26667 26668 26669 26670 26671 26672 26673 26674 26675 26676 26677 26678 26679 26680 26681 26682 26683 26684 26685 26686 26687 26688 26689 26690 26691 26692 26693 26694 26695 26696 26697 26698 26699 26700 26701 26702 26703 26704 26705 26706 26707 26708 26709 26710 26711 26712 26713 26714 26715 26716 26717 26718 26719 26720 26721 26722 26723 26724 26725 26726 26727 26728 26729 26730 26731 26732 26733 26734 26735 26736 26737 26738 26739 26740 26741 26742 26743 26744 26745 26746 26747 26748 26749 26750 26751 26752 26753 26754 26755 26756 26757 26758 26759 26760 26761 26762 26763 26764 26765 26766 26767 26768 26769 26770 26771 26772 26773 26774 26775 26776 26777 26778 26779 26780 26781 26782 26783 26784 26785 26786 26787 26788 26789 26790 26791 26792 26793 26794 26795 26796 26797 26798 26799 26800 26801 26802 26803 26804 26805 26806 26807 26808 26809 26810 26811 26812 26813 26814 26815 26816 26817 26818 26819 26820 26821 26822 26823 26824 26825 26826 26827 26828 26829 26830 26831 26832 26833 26834 26835 26836 26837 26838 26839 26840 26841 26842 26843 26844 26845 26846 26847 26848 26849 26850 26851 26852 26853 26854 26855 26856 26857 26858 26859 26860 26861 26862 26863 26864 26865 26866 26867 26868 26869 26870 26871 26872 26873 26874 26875 26876 26877 26878 26879 26880 26881 26882 26883 26884 26885 26886 26887 26888 26889 26890 26891 26892 26893 26894 26895 26896 26897 26898 26899 26900 26901 26902 26903 26904 26905 26906 26907 26908 26909 26910 26911 26912 26913 26914 26915 26916 26917 26918 26919 26920 26921 26922 26923 26924 26925 26926 26927 26928 26929 26930 26931 26932 26933 26934 26935 26936 26937 26938 26939 26940 26941 26942 26943 26944 26945 26946 26947 26948 26949 26950 26951 26952 26953 26954 26955 26956 26957 26958 26959 26960 26961 26962 26963 26964 26965 26966 26967 26968 26969 26970 26971 26972 26973 26974 26975 26976 26977 26978 26979 26980 26981 26982 26983 26984 26985 26986 26987 26988 26989 26990 26991 26992 26993 26994 26995 26996 26997 26998 26999 27000 27001 27002 27003 27004 27005 27006 27007 27008 27009 27010 27011 27012 27013 27014 27015 27016 27017 27018 27019 27020 27021 27022 27023 27024 27025 27026 27027 27028 27029 27030 27031 27032 27033 27034 27035 27036 27037 27038 27039 27040 27041 27042 27043 27044 27045 27046 27047 27048 27049 27050 27051 27052 27053 27054 27055 27056 27057 27058 27059 27060 27061 27062 27063 27064 27065 27066 27067 27068 27069 27070 27071 27072 27073 27074 27075 27076 27077 27078 27079 27080 27081 27082 27083 27084 27085 27086 27087 27088 27089 27090 27091 27092 27093 27094 27095 27096 27097 27098 27099 27100 27101 27102 27103 27104 27105 27106 27107 27108 27109 27110 27111 27112 27113 27114 27115 27116 27117 27118 27119 27120 27121 27122 27123 27124 27125 27126 27127 27128 27129 27130 27131 27132 27133 27134 27135 27136 27137 27138 27139 27140 27141 27142 27143 27144 27145 27146 27147 27148 27149 27150 27151 27152 27153 27154 27155 27156 27157 27158 27159 27160 27161 27162 27163 27164 27165 27166 27167 27168 27169 27170 27171 27172 27173 27174 27175 27176 27177 27178 27179 27180 27181 27182 27183 27184 27185 27186 27187 27188 27189 27190 27191 27192 27193 27194 27195 27196 27197 27198 27199 27200 27201 27202 27203 27204 27205 27206 27207 27208 27209 27210 27211 27212 27213 27214 27215 27216 27217 27218 27219 27220 27221 27222 27223 27224 27225 27226 27227 27228 27229 27230 27231 27232 27233 27234 27235 27236 27237 27238 27239 27240 27241 27242 27243 27244 27245 27246 27247 27248 27249 27250 27251 27252 27253 27254 27255 27256 27257 27258 27259 27260 27261 27262 27263 27264 27265 27266 27267 27268 27269 27270 27271 27272 27273 27274 27275 27276 27277 27278 27279 27280 27281 27282 27283 27284 27285 27286 27287 27288 27289 27290 27291 27292 27293 27294 27295 27296 27297 27298 27299 27300 27301 27302 27303 27304 27305 27306 27307 27308 27309 27310 27311 27312 27313 27314 27315 27316 27317 27318 27319 27320 27321 27322 27323 27324 27325 27326 27327 27328 27329 27330 27331 27332 27333 27334 27335 27336 27337 27338 27339 27340 27341 27342 27343 27344 27345 27346 27347 27348 27349 27350 27351 27352 27353 27354 27355 27356 27357 27358 27359 27360 27361 27362 27363 27364 27365 27366 27367 27368 27369 27370 27371 27372 27373 27374 27375 27376 27377 27378 27379 27380 27381 27382 27383 27384 27385 27386 27387 27388 27389 27390 27391 27392 27393 27394 27395 27396 27397 27398 27399 27400 27401 27402 27403 27404 27405 27406 27407 27408 27409 27410 27411 27412 27413 27414 27415 27416 27417 27418 27419 27420 27421 27422 27423 27424 27425 27426 27427 27428 27429 27430 27431 27432 27433 27434 27435 27436 27437 27438 27439 27440 27441 27442 27443 27444 27445 27446 27447 27448 27449 27450 27451 27452 27453 27454 27455 27456 27457 27458 27459 27460 27461 27462 27463 27464 27465 27466 27467 27468 27469 27470 27471 27472 27473 27474 27475 27476 27477 27478 27479 27480 27481 27482 27483 27484 27485 27486 27487 27488 27489 27490 27491 27492 27493 27494 27495 27496 27497 27498 27499 27500 27501 27502 27503 27504 27505 27506 27507 27508 27509 27510 27511 27512 27513 27514 27515 27516 27517 27518 27519 27520 27521 27522 27523 27524 27525 27526 27527 27528 27529 27530 27531 27532 27533 27534 27535 27536 27537 27538 27539 27540 27541 27542 27543 27544 27545 27546 27547 27548 27549 27550 27551 27552 27553 27554 27555 27556 27557 27558 27559 27560 27561 27562 27563 27564 27565 27566 27567 27568 27569 27570 27571 27572 27573 27574 27575 27576 27577 27578 27579 27580 27581 27582 27583 27584 27585 27586 27587 27588 27589 27590 27591 27592 27593 27594 27595 27596 27597 27598 27599 27600 27601 27602 27603 27604 27605 27606 27607 27608 27609 27610 27611 27612 27613 27614 27615 27616 27617 27618 27619 27620 27621 27622 27623 27624 27625 27626 27627 27628 27629 27630 27631 27632 27633 27634 27635 27636 27637 27638 27639 27640 27641 27642 27643 27644 27645 27646 27647 27648 27649 27650 27651 27652 27653 27654 27655 27656 27657 27658 27659 27660 27661 27662 27663 27664 27665 27666 27667 27668 27669 27670 27671 27672 27673 27674 27675 27676 27677 27678 27679 27680 27681 27682 27683 27684 27685 27686 27687 27688 27689 27690 27691 27692 27693 27694 27695 27696 27697 27698 27699 27700 27701 27702 27703 27704 27705 27706 27707 27708 27709 27710 27711 27712 27713 27714 27715 27716 27717 27718 27719 27720 27721 27722 27723 27724 27725 27726 27727 27728 27729 27730 27731 27732 27733 27734 27735 27736 27737 27738 27739 27740 27741 27742 27743 27744 27745 27746 27747 27748 27749 27750 27751 27752 27753 27754 27755 27756 27757 27758 27759 27760 27761 27762 27763 27764 27765 27766 27767 27768 27769 27770 27771 27772 27773 27774 27775 27776 27777 27778 27779 27780 27781 27782 27783 27784 27785 27786 27787 27788 27789 27790 27791 27792 27793 27794 27795 27796 27797 27798 27799 27800 27801 27802 27803 27804 27805 27806 27807 27808 27809 27810 27811 27812 27813 27814 27815 27816 27817 27818 27819 27820 27821 27822 27823 27824 27825 27826 27827 27828 27829 27830 27831 27832 27833 27834 27835 27836 27837 27838 27839 27840 27841 27842 27843 27844 27845 27846 27847 27848 27849 27850 27851 27852 27853 27854 27855 27856 27857 27858 27859 27860 27861 27862 27863 27864 27865 27866 27867 27868 27869 27870 27871 27872 27873 27874 27875 27876 27877 27878 27879 27880 27881 27882 27883 27884 27885 27886 27887 27888 27889 27890 27891 27892 27893 27894 27895 27896 27897 27898 27899 27900 27901 27902 27903 27904 27905 27906 27907 27908 27909 27910 27911 27912 27913 27914 27915 27916 27917 27918 27919 27920 27921 27922 27923 27924 27925 27926 27927 27928 27929 27930 27931 27932 27933 27934 27935 27936 27937 27938 27939 27940 27941 27942 27943 27944 27945 27946 27947 27948 27949 27950 27951 27952 27953 27954 27955 27956 27957 27958 27959 27960 27961 27962 27963 27964 27965 27966 27967 27968 27969 27970 27971 27972 27973 27974 27975 27976 27977 27978 27979 27980 27981 27982 27983 27984 27985 27986 27987 27988 27989 27990 27991 27992 27993 27994 27995 27996 27997 27998 27999 28000 28001 28002 28003 28004 28005 28006 28007 28008 28009 28010 28011 28012 28013 28014 28015 28016 28017 28018 28019 28020 28021 28022 28023 28024 28025 28026 28027 28028 28029 28030 28031 28032 28033 28034 28035 28036 28037 28038 28039 28040 28041 28042 28043 28044 28045 28046 28047 28048 28049 28050 28051 28052 28053 28054 28055 28056 28057 28058 28059 28060 28061 28062 28063 28064 28065 28066 28067 28068 28069 28070 28071 28072 28073 28074 28075 28076 28077 28078 28079 28080 28081 28082 28083 28084 28085 28086 28087 28088 28089 28090 28091 28092 28093 28094 28095 28096 28097 28098 28099 28100 28101 28102 28103 28104 28105 28106 28107 28108 28109 28110 28111 28112 28113 28114 28115 28116 28117 28118 28119 28120 28121 28122 28123 28124 28125 28126 28127 28128 28129 28130 28131 28132 28133 28134 28135 28136 28137 28138 28139 28140 28141 28142 28143 28144 28145 28146 28147 28148 28149 28150 28151 28152 28153 28154 28155 28156 28157 28158 28159 28160 28161 28162 28163 28164 28165 28166 28167 28168 28169 28170 28171 28172 28173 28174 28175 28176 28177 28178 28179 28180 28181 28182 28183 28184 28185 28186 28187 28188 28189 28190 28191 28192 28193 28194 28195 28196 28197 28198 28199 28200 28201 28202 28203 28204 28205 28206 28207 28208 28209 28210 28211 28212 28213 28214 28215 28216 28217 28218 28219 28220 28221 28222 28223 28224 28225 28226 28227 28228 28229 28230 28231 28232 28233 28234 28235 28236 28237 28238 28239 28240 28241 28242 28243 28244 28245 28246 28247 28248 28249 28250 28251 28252 28253 28254 28255 28256 28257 28258 28259 28260 28261 28262 28263 28264 28265 28266 28267 28268 28269 28270 28271 28272 28273 28274 28275 28276 28277 28278 28279 28280 28281 28282 28283 28284 28285 28286 28287 28288 28289 28290 28291 28292 28293 28294 28295 28296 28297 28298 28299 28300 28301 28302 28303 28304 28305 28306 28307 28308 28309 28310 28311 28312 28313 28314 28315 28316 28317 28318 28319 28320 28321 28322 28323 28324 28325 28326 28327 28328 28329 28330 28331 28332 28333 28334 28335 28336 28337 28338 28339 28340 28341 28342 28343 28344 28345 28346 28347 28348 28349 28350 28351 28352 28353 28354 28355 28356 28357 28358 28359 28360 28361 28362 28363 28364 28365 28366 28367 28368 28369 28370 28371 28372 28373 28374 28375 28376 28377 28378 28379 28380 28381 28382 28383 28384 28385 28386 28387 28388 28389 28390 28391 28392 28393 28394 28395 28396 28397 28398 28399 28400 28401 28402 28403 28404 28405 28406 28407 28408 28409 28410 28411 28412 28413 28414 28415 28416 28417 28418 28419 28420 28421 28422 28423 28424 28425 28426 28427 28428 28429 28430 28431 28432 28433 28434 28435 28436 28437 28438 28439 28440 28441 28442 28443 28444 28445 28446 28447 28448 28449 28450 28451 28452 28453 28454 28455 28456 28457 28458 28459 28460 28461 28462 28463 28464 28465 28466 28467 28468 28469 28470 28471 28472 28473 28474 28475 28476 28477 28478 28479 28480 28481 28482 28483 28484 28485 28486 28487 28488 28489 28490 28491 28492 28493 28494 28495 28496 28497 28498 28499 28500 28501 28502 28503 28504 28505 28506 28507 28508 28509 28510 28511 28512 28513 28514 28515 28516 28517 28518 28519 28520 28521 28522 28523 28524 28525 28526 28527 28528 28529 28530 28531 28532 28533 28534 28535 28536 28537 28538 28539 28540 28541 28542 28543 28544 28545 28546 28547 28548 28549 28550 28551 28552 28553 28554 28555 28556 28557 28558 28559 28560 28561 28562 28563 28564 28565 28566 28567 28568 28569 28570 28571 28572 28573 28574 28575 28576 28577 28578 28579 28580 28581 28582 28583 28584 28585 28586 28587 28588 28589 28590 28591 28592 28593 28594 28595 28596 28597 28598 28599 28600 28601 28602 28603 28604 28605 28606 28607 28608 28609 28610 28611 28612 28613 28614 28615 28616 28617 28618 28619 28620 28621 28622 28623 28624 28625 28626 28627 28628 28629 28630 28631 28632 28633 28634 28635 28636 28637 28638 28639 28640 28641 28642 28643 28644 28645 28646 28647 28648 28649 28650 28651 28652 28653 28654 28655 28656 28657 28658 28659 28660 28661 28662 28663 28664 28665 28666 28667 28668 28669 28670 28671 28672 28673 28674 28675 28676 28677 28678 28679 28680 28681 28682 28683 28684 28685 28686 28687 28688 28689 28690 28691 28692 28693 28694 28695 28696 28697 28698 28699 28700 28701 28702 28703 28704 28705 28706 28707 28708 28709 28710 28711 28712 28713 28714 28715 28716 28717 28718 28719 28720 28721 28722 28723 28724 28725 28726 28727 28728 28729 28730 28731 28732 28733 28734 28735 28736 28737 28738 28739 28740 28741 28742 28743 28744 28745 28746 28747 28748 28749 28750 28751 28752 28753 28754 28755 28756 28757 28758 28759 28760 28761 28762 28763 28764 28765 28766 28767 28768 28769 28770 28771 28772 28773 28774 28775 28776 28777 28778 28779 28780 28781 28782 28783 28784 28785 28786 28787 28788 28789 28790 28791 28792 28793 28794 28795 28796 28797 28798 28799 28800 28801 28802 28803 28804 28805 28806 28807 28808 28809 28810 28811 28812 28813 28814 28815 28816 28817 28818 28819 28820 28821 28822 28823 28824 28825 28826 28827 28828 28829 28830 28831 28832 28833 28834 28835 28836 28837 28838 28839 28840 28841 28842 28843 28844 28845 28846 28847 28848 28849 28850 28851 28852 28853 28854 28855 28856 28857 28858 28859 28860 28861 28862 28863 28864 28865 28866 28867 28868 28869 28870 28871 28872 28873 28874 28875 28876 28877 28878 28879 28880 28881 28882 28883 28884 28885 28886 28887 28888 28889 28890 28891 28892 28893 28894 28895 28896 28897 28898 28899 28900 28901 28902 28903 28904 28905 28906 28907 28908 28909 28910 28911 28912 28913 28914 28915 28916 28917 28918 28919 28920 28921 28922 28923 28924 28925 28926 28927 28928 28929 28930 28931 28932 28933 28934 28935 28936 28937 28938 28939 28940 28941 28942 28943 28944 28945 28946 28947 28948 28949 28950 28951 28952 28953 28954 28955 28956 28957 28958 28959 28960 28961 28962 28963 28964 28965 28966 28967 28968 28969 28970 28971 28972 28973 28974 28975 28976 28977 28978 28979 28980 28981 28982 28983 28984 28985 28986 28987 28988 28989 28990 28991 28992 28993 28994 28995 28996 28997 28998 28999 29000 29001 29002 29003 29004 29005 29006 29007 29008 29009 29010 29011 29012 29013 29014 29015 29016 29017 29018 29019 29020 29021 29022 29023 29024 29025 29026 29027 29028 29029 29030 29031 29032 29033 29034 29035 29036 29037 29038 29039 29040 29041 29042 29043 29044 29045 29046 29047 29048 29049 29050 29051 29052 29053 29054 29055 29056 29057 29058 29059 29060 29061 29062 29063 29064 29065 29066 29067 29068 29069 29070 29071 29072 29073 29074 29075 29076 29077 29078 29079 29080 29081 29082 29083 29084 29085 29086 29087 29088 29089 29090 29091 29092 29093 29094 29095 29096 29097 29098 29099 29100 29101 29102 29103 29104 29105 29106 29107 29108 29109 29110 29111 29112 29113 29114 29115 29116 29117 29118 29119 29120 29121 29122 29123 29124 29125 29126 29127 29128 29129 29130 29131 29132 29133 29134 29135 29136 29137 29138 29139 29140 29141 29142 29143 29144 29145 29146 29147 29148 29149 29150 29151 29152 29153 29154 29155 29156 29157 29158 29159 29160 29161 29162 29163 29164 29165 29166 29167 29168 29169 29170 29171 29172 29173 29174 29175 29176 29177 29178 29179 29180 29181 29182 29183 29184 29185 29186 29187 29188 29189 29190 29191 29192 29193 29194 29195 29196 29197 29198 29199 29200 29201 29202 29203 29204 29205 29206 29207 29208 29209 29210 29211 29212 29213 29214 29215 29216 29217 29218 29219 29220 29221 29222 29223 29224 29225 29226 29227 29228 29229 29230 29231 29232 29233 29234 29235 29236 29237 29238 29239 29240 29241 29242 29243 29244 29245 29246 29247 29248 29249 29250 29251 29252 29253 29254 29255 29256 29257 29258 29259 29260 29261 29262 29263 29264 29265 29266 29267 29268 29269 29270 29271 29272 29273 29274 29275 29276 29277 29278 29279 29280 29281 29282 29283 29284 29285 29286 29287 29288 29289 29290 29291 29292 29293 29294 29295 29296 29297 29298 29299 29300 29301 29302 29303 29304 29305 29306 29307 29308 29309 29310 29311 29312 29313 29314 29315 29316 29317 29318 29319 29320 29321 29322 29323 29324 29325 29326 29327 29328 29329 29330 29331 29332 29333 29334 29335 29336 29337 29338 29339 29340 29341 29342 29343 29344 29345 29346 29347 29348 29349 29350 29351 29352 29353 29354 29355 29356 29357 29358 29359 29360 29361 29362 29363 29364 29365 29366 29367 29368 29369 29370 29371 29372 29373 29374 29375 29376 29377 29378 29379 29380 29381 29382 29383 29384 29385 29386 29387 29388 29389 29390 29391 29392 29393 29394 29395 29396 29397 29398 29399 29400 29401 29402 29403 29404 29405 29406 29407 29408 29409 29410 29411 29412 29413 29414 29415 29416 29417 29418 29419 29420 29421 29422 29423 29424 29425 29426 29427 29428 29429 29430 29431 29432 29433 29434 29435 29436 29437 29438 29439 29440 29441 29442 29443 29444 29445 29446 29447 29448 29449 29450 29451 29452 29453 29454 29455 29456 29457 29458 29459 29460 29461 29462 29463 29464 29465 29466 29467 29468 29469 29470 29471 29472 29473 29474 29475 29476 29477 29478 29479 29480 29481 29482 29483 29484 29485 29486 29487 29488 29489 29490 29491 29492 29493 29494 29495 29496 29497 29498 29499 29500 29501 29502 29503 29504 29505 29506 29507 29508 29509 29510 29511 29512 29513 29514 29515 29516 29517 29518 29519 29520 29521 29522 29523 29524 29525 29526 29527 29528 29529 29530 29531 29532 29533 29534 29535 29536 29537 29538 29539 29540 29541 29542 29543 29544 29545 29546 29547 29548 29549 29550 29551 29552 29553 29554 29555 29556 29557 29558 29559 29560 29561 29562 29563 29564 29565 29566 29567 29568 29569 29570 29571 29572 29573 29574 29575 29576 29577 29578 29579 29580 29581 29582 29583 29584 29585 29586 29587 29588 29589 29590 29591 29592 29593 29594 29595 29596 29597 29598 29599 29600 29601 29602 29603 29604 29605 29606 29607 29608 29609 29610 29611 29612 29613 29614 29615 29616 29617 29618 29619 29620 29621 29622 29623 29624 29625 29626 29627 29628 29629 29630 29631 29632 29633 29634 29635 29636 29637 29638 29639 29640 29641 29642 29643 29644 29645 29646 29647 29648 29649 29650 29651 29652 29653 29654 29655 29656 29657 29658 29659 29660 29661 29662 29663 29664 29665 29666 29667 29668 29669 29670 29671 29672 29673 29674 29675 29676 29677 29678 29679 29680 29681 29682 29683 29684 29685 29686 29687 29688 29689 29690 29691 29692 29693 29694 29695 29696 29697 29698 29699 29700 29701 29702 29703 29704 29705 29706 29707 29708 29709 29710 29711 29712 29713 29714 29715 29716 29717 29718 29719 29720 29721 29722 29723 29724 29725 29726 29727 29728 29729 29730 29731 29732 29733 29734 29735 29736 29737 29738 29739 29740 29741 29742 29743 29744 29745 29746 29747 29748 29749 29750 29751 29752 29753 29754 29755 29756 29757 29758 29759 29760 29761 29762 29763 29764 29765 29766 29767 29768 29769 29770 29771 29772 29773 29774 29775 29776 29777 29778 29779 29780 29781 29782 29783 29784 29785 29786 29787 29788 29789 29790 29791 29792 29793 29794 29795 29796 29797 29798 29799 29800 29801 29802 29803 29804 29805 29806 29807 29808 29809 29810 29811 29812 29813 29814 29815 29816 29817 29818 29819 29820 29821 29822 29823 29824 29825 29826 29827 29828 29829 29830 29831 29832 29833 29834 29835 29836 29837 29838 29839 29840 29841 29842 29843 29844 29845 29846 29847 29848 29849 29850 29851 29852 29853 29854 29855 29856 29857 29858 29859 29860 29861 29862 29863 29864 29865 29866 29867 29868 29869 29870 29871 29872 29873 29874 29875 29876 29877 29878 29879 29880 29881 29882 29883 29884 29885 29886 29887 29888 29889 29890 29891 29892 29893 29894 29895 29896 29897 29898 29899 29900 29901 29902 29903 29904 29905 29906 29907 29908 29909 29910 29911 29912 29913 29914 29915 29916 29917 29918 29919 29920 29921 29922 29923 29924 29925 29926 29927 29928 29929 29930 29931 29932 29933 29934 29935 29936 29937 29938 29939 29940 29941 29942 29943 29944 29945 29946 29947 29948 29949 29950 29951 29952 29953 29954 29955 29956 29957 29958 29959 29960 29961 29962 29963 29964 29965 29966 29967 29968 29969 29970 29971 29972 29973 29974 29975 29976 29977 29978 29979 29980 29981 29982 29983 29984 29985 29986 29987 29988 29989 29990 29991 29992 29993 29994 29995 29996 29997 29998 29999 30000 30001 30002 30003 30004 30005 30006 30007 30008 30009 30010 30011 30012 30013 30014 30015 30016 30017 30018 30019 30020 30021 30022 30023 30024 30025 30026 30027 30028 30029 30030 30031 30032 30033 30034 30035 30036 30037 30038 30039 30040 30041 30042 30043 30044 30045 30046 30047 30048 30049 30050 30051 30052 30053 30054 30055 30056 30057 30058 30059 30060 30061 30062 30063 30064 30065 30066 30067 30068 30069 30070 30071 30072 30073 30074 30075 30076 30077 30078 30079 30080 30081 30082 30083 30084 30085 30086 30087 30088 30089 30090 30091 30092 30093 30094 30095 30096 30097 30098 30099 30100 30101 30102 30103 30104 30105 30106 30107 30108 30109 30110 30111 30112 30113 30114 30115 30116 30117 30118 30119 30120 30121 30122 30123 30124 30125 30126 30127 30128 30129 30130 30131 30132 30133 30134 30135 30136 30137 30138 30139 30140 30141 30142 30143 30144 30145 30146 30147 30148 30149 30150 30151 30152 30153 30154 30155 30156 30157 30158 30159 30160 30161 30162 30163 30164 30165 30166 30167 30168 30169 30170 30171 30172 30173 30174 30175 30176 30177 30178 30179 30180 30181 30182 30183 30184 30185 30186 30187 30188 30189 30190 30191 30192 30193 30194 30195 30196 30197 30198 30199 30200 30201 30202 30203 30204 30205 30206 30207 30208 30209 30210 30211 30212 30213 30214 30215 30216 30217 30218 30219 30220 30221 30222 30223 30224 30225 30226 30227 30228 30229 30230 30231 30232 30233 30234 30235 30236 30237 30238 30239 30240 30241 30242 30243 30244 30245 30246 30247 30248 30249 30250 30251 30252 30253 30254 30255 30256 30257 30258 30259 30260 30261 30262 30263 30264 30265 30266 30267 30268 30269 30270 30271 30272 30273 30274 30275 30276 30277 30278 30279 30280 30281 30282 30283 30284 30285 30286 30287 30288 30289 30290 30291 30292 30293 30294 30295 30296 30297 30298 30299 30300 30301 30302 30303 30304 30305 30306 30307 30308 30309 30310 30311 30312 30313 30314 30315 30316 30317 30318 30319 30320 30321 30322 30323 30324 30325 30326 30327 30328 30329 30330 30331 30332 30333 30334 30335 30336 30337 30338 30339 30340 30341 30342 30343 30344 30345 30346 30347 30348 30349 30350 30351 30352 30353 30354 30355 30356 30357 30358 30359 30360 30361 30362 30363 30364 30365 30366 30367 30368 30369 30370 30371 30372 30373 30374 30375 30376 30377 30378 30379 30380 30381 30382 30383 30384 30385 30386 30387 30388 30389 30390 30391 30392 30393 30394 30395 30396 30397 30398 30399 30400 30401 30402 30403 30404 30405 30406 30407 30408 30409 30410 30411 30412 30413 30414 30415 30416 30417 30418 30419 30420 30421 30422 30423 30424 30425 30426 30427 30428 30429 30430 30431 30432 30433 30434 30435 30436 30437 30438 30439 30440 30441 30442 30443 30444 30445 30446 30447 30448 30449 30450 30451 30452 30453 30454 30455 30456 30457 30458 30459 30460 30461 30462 30463 30464 30465 30466 30467 30468 30469 30470 30471 30472 30473 30474 30475 30476 30477 30478 30479 30480 30481 30482 30483 30484 30485 30486 30487 30488 30489 30490 30491 30492 30493 30494 30495 30496 30497 30498 30499 30500 30501 30502 30503 30504 30505 30506 30507 30508 30509 30510 30511 30512 30513 30514 30515 30516 30517 30518 30519 30520 30521 30522 30523 30524 30525 30526 30527 30528 30529 30530 30531 30532 30533 30534 30535 30536 30537 30538 30539 30540 30541 30542 30543 30544 30545 30546 30547 30548 30549 30550 30551 30552 30553 30554 30555 30556 30557 30558 30559 30560 30561 30562 30563 30564 30565 30566 30567 30568 30569 30570 30571 30572 30573 30574 30575 30576 30577 30578 30579 30580 30581 30582 30583 30584 30585 30586 30587 30588 30589 30590 30591 30592 30593 30594 30595 30596 30597 30598 30599 30600 30601 30602 30603 30604 30605 30606 30607 30608 30609 30610 30611 30612 30613 30614 30615 30616 30617 30618 30619 30620 30621 30622 30623 30624 30625 30626 30627 30628 30629 30630 30631 30632 30633 30634 30635 30636 30637 30638 30639 30640 30641 30642 30643 30644 30645 30646 30647 30648 30649 30650 30651 30652 30653 30654 30655 30656 30657 30658 30659 30660 30661 30662 30663 30664 30665 30666 30667 30668 30669 30670 30671 30672 30673 30674 30675 30676 30677 30678 30679 30680 30681 30682 30683 30684 30685 30686 30687 30688 30689 30690 30691 30692 30693 30694 30695 30696 30697 30698 30699 30700 30701 30702 30703 30704 30705 30706 30707 30708 30709 30710 30711 30712 30713 30714 30715 30716 30717 30718 30719 30720 30721 30722 30723 30724 30725 30726 30727 30728 30729 30730 30731 30732 30733 30734 30735 30736 30737 30738 30739 30740 30741 30742 30743 30744 30745 30746 30747 30748 30749 30750 30751 30752 30753 30754 30755 30756 30757 30758 30759 30760 30761 30762 30763 30764 30765 30766 30767 30768 30769 30770 30771 30772 30773 30774 30775 30776 30777 30778 30779 30780 30781 30782 30783 30784 30785 30786 30787 30788 30789 30790 30791 30792 30793 30794 30795 30796 30797 30798 30799 30800 30801 30802 30803 30804 30805 30806 30807 30808 30809 30810 30811 30812 30813 30814 30815 30816 30817 30818 30819 30820 30821 30822 30823 30824 30825 30826 30827 30828 30829 30830 30831 30832 30833 30834 30835 30836 30837 30838 30839 30840 30841 30842 30843 30844 30845 30846 30847 30848 30849 30850 30851 30852 30853 30854 30855 30856 30857 30858 30859 30860 30861 30862 30863 30864 30865 30866 30867 30868 30869 30870 30871 30872 30873 30874 30875 30876 30877 30878 30879 30880 30881 30882 30883 30884 30885 30886 30887 30888 30889 30890 30891 30892 30893 30894 30895 30896 30897 30898 30899 30900 30901 30902 30903 30904 30905 30906 30907 30908 30909 30910 30911 30912 30913 30914 30915 30916 30917 30918 30919 30920 30921 30922 30923 30924 30925 30926 30927 30928 30929 30930 30931 30932 30933 30934 30935 30936 30937 30938 30939 30940 30941 30942 30943 30944 30945 30946 30947 30948 30949 30950 30951 30952 30953 30954 30955 30956 30957 30958 30959 30960 30961 30962 30963 30964 30965 30966 30967 30968 30969 30970 30971 30972 30973 30974 30975 30976 30977 30978 30979 30980 30981 30982 30983 30984 30985 30986 30987 30988 30989 30990 30991 30992 30993 30994 30995 30996 30997 30998 30999 31000 31001 31002 31003 31004 31005 31006 31007 31008 31009 31010 31011 31012 31013 31014 31015 31016 31017 31018 31019 31020 31021 31022 31023 31024 31025 31026 31027 31028 31029 31030 31031 31032 31033 31034 31035 31036 31037 31038 31039 31040 31041 31042 31043 31044 31045 31046 31047 31048 31049 31050 31051 31052 31053 31054 31055 31056 31057 31058 31059 31060 31061 31062 31063 31064 31065 31066 31067 31068 31069 31070 31071 31072 31073 31074 31075 31076 31077 31078 31079 31080 31081 31082 31083 31084 31085 31086 31087 31088 31089 31090 31091 31092 31093 31094 31095 31096 31097 31098 31099 31100 31101 31102 31103 31104 31105 31106 31107 31108 31109 31110 31111 31112 31113 31114 31115 31116 31117 31118 31119 31120 31121 31122 31123 31124 31125 31126 31127 31128 31129 31130 31131 31132 31133 31134 31135 31136 31137 31138 31139 31140 31141 31142 31143 31144 31145 31146 31147 31148 31149 31150 31151 31152 31153 31154 31155 31156 31157 31158 31159 31160 31161 31162 31163 31164 31165 31166 31167 31168 31169 31170 31171 31172 31173 31174 31175 31176 31177 31178 31179 31180 31181 31182 31183 31184 31185 31186 31187 31188 31189 31190 31191 31192 31193 31194 31195 31196 31197 31198 31199 31200 31201 31202 31203 31204 31205 31206 31207 31208 31209 31210 31211 31212 31213 31214 31215 31216 31217 31218 31219 31220 31221 31222 31223 31224 31225 31226 31227 31228 31229 31230 31231 31232 31233 31234 31235 31236 31237 31238 31239 31240 31241 31242 31243 31244 31245 31246 31247 31248 31249 31250 31251 31252 31253 31254 31255 31256 31257 31258 31259 31260 31261 31262 31263 31264 31265 31266 31267 31268 31269 31270 31271 31272 31273 31274 31275 31276 31277 31278 31279 31280 31281 31282 31283 31284 31285 31286 31287 31288 31289 31290 31291 31292 31293 31294 31295 31296 31297 31298 31299 31300 31301 31302 31303 31304 31305 31306 31307 31308 31309 31310 31311 31312 31313 31314 31315 31316 31317 31318 31319 31320 31321 31322 31323 31324 31325 31326 31327 31328 31329 31330 31331 31332 31333 31334 31335 31336 31337 31338 31339 31340 31341 31342 31343 31344 31345 31346 31347 31348 31349 31350 31351 31352 31353 31354 31355 31356 31357 31358 31359 31360 31361 31362 31363 31364 31365 31366 31367 31368 31369 31370 31371 31372 31373 31374 31375 31376 31377 31378 31379 31380 31381 31382 31383 31384 31385 31386 31387 31388 31389 31390 31391 31392 31393 31394 31395 31396 31397 31398 31399 31400 31401 31402 31403 31404 31405 31406 31407 31408 31409 31410 31411 31412 31413 31414 31415 31416 31417 31418 31419 31420 31421 31422 31423 31424 31425 31426 31427 31428 31429 31430 31431 31432 31433 31434 31435 31436 31437 31438 31439 31440 31441 31442 31443 31444 31445 31446 31447 31448 31449 31450 31451 31452 31453 31454 31455 31456 31457 31458 31459 31460 31461 31462 31463 31464 31465 31466 31467 31468 31469 31470 31471 31472 31473 31474 31475 31476 31477 31478 31479 31480 31481 31482 31483 31484 31485 31486 31487 31488 31489 31490 31491 31492 31493 31494 31495 31496 31497 31498 31499 31500 31501 31502 31503 31504 31505 31506 31507 31508 31509 31510 31511 31512 31513 31514 31515 31516 31517 31518 31519 31520 31521 31522 31523 31524 31525 31526 31527 31528 31529 31530 31531 31532 31533 31534 31535 31536 31537 31538 31539 31540 31541 31542 31543 31544 31545 31546 31547 31548 31549 31550 31551 31552 31553 31554 31555 31556 31557 31558 31559 31560 31561 31562 31563 31564 31565 31566 31567 31568 31569 31570 31571 31572 31573 31574 31575 31576 31577 31578 31579 31580 31581 31582 31583 31584 31585 31586 31587 31588 31589 31590 31591 31592 31593 31594 31595 31596 31597 31598 31599 31600 31601 31602 31603 31604 31605 31606 31607 31608 31609 31610 31611 31612 31613 31614 31615 31616 31617 31618 31619 31620 31621 31622 31623 31624 31625 31626 31627 31628 31629 31630 31631 31632 31633 31634 31635 31636 31637 31638 31639 31640 31641 31642 31643 31644 31645 31646 31647 31648 31649 31650 31651 31652 31653 31654 31655 31656 31657 31658 31659 31660 31661 31662 31663 31664 31665 31666 31667 31668 31669 31670 31671 31672 31673 31674 31675 31676 31677 31678 31679 31680 31681 31682 31683 31684 31685 31686 31687 31688 31689 31690 31691 31692 31693 31694 31695 31696 31697 31698 31699 31700 31701 31702 31703 31704 31705 31706 31707 31708 31709 31710 31711 31712 31713 31714 31715 31716 31717 31718 31719 31720 31721 31722 31723 31724 31725 31726 31727 31728 31729 31730 31731 31732 31733 31734 31735 31736 31737 31738 31739 31740 31741 31742 31743 31744 31745 31746 31747 31748 31749 31750 31751 31752 31753 31754 31755 31756 31757 31758 31759 31760 31761 31762 31763 31764 31765 31766 31767 31768 31769 31770 31771 31772 31773 31774 31775 31776 31777 31778 31779 31780 31781 31782 31783 31784 31785 31786 31787 31788 31789 31790 31791 31792 31793 31794 31795 31796 31797 31798 31799 31800 31801 31802 31803 31804 31805 31806 31807 31808 31809 31810 31811 31812 31813 31814 31815 31816 31817 31818 31819 31820 31821 31822 31823 31824 31825 31826 31827 31828 31829 31830 31831 31832 31833 31834 31835 31836 31837 31838 31839 31840 31841 31842 31843 31844 31845 31846 31847 31848 31849 31850 31851 31852 31853 31854 31855 31856 31857 31858 31859 31860 31861 31862 31863 31864 31865 31866 31867 31868 31869 31870 31871 31872 31873 31874 31875 31876 31877 31878 31879 31880 31881 31882 31883 31884 31885 31886 31887 31888 31889 31890 31891 31892 31893 31894 31895 31896 31897 31898 31899 31900 31901 31902 31903 31904 31905 31906 31907 31908 31909 31910 31911 31912 31913 31914 31915 31916 31917 31918 31919 31920 31921 31922 31923 31924 31925 31926 31927 31928 31929 31930 31931 31932 31933 31934 31935 31936 31937 31938 31939 31940 31941 31942 31943 31944 31945 31946 31947 31948 31949 31950 31951 31952 31953 31954 31955 31956 31957 31958 31959 31960 31961 31962 31963 31964 31965 31966 31967 31968 31969 31970 31971 31972 31973 31974 31975 31976 31977 31978 31979 31980 31981 31982 31983 31984 31985 31986 31987 31988 31989 31990 31991 31992 31993 31994 31995 31996 31997 31998 31999 32000 32001 32002 32003 32004 32005 32006 32007 32008 32009 32010 32011 32012 32013 32014 32015 32016 32017 32018 32019 32020 32021 32022 32023 32024 32025 32026 32027 32028 32029 32030 32031 32032 32033 32034 32035 32036 32037 32038 32039 32040 32041 32042 32043 32044 32045 32046 32047 32048 32049 32050 32051 32052 32053 32054 32055 32056 32057 32058 32059 32060 32061 32062 32063 32064 32065 32066 32067 32068 32069 32070 32071 32072 32073 32074 32075 32076 32077 32078 32079 32080 32081 32082 32083 32084 32085 32086 32087 32088 32089 32090 32091 32092 32093 32094 32095 32096 32097 32098 32099 32100 32101 32102 32103 32104 32105 32106 32107 32108 32109 32110 32111 32112 32113 32114 32115 32116 32117 32118 32119 32120 32121 32122 32123 32124 32125 32126 32127 32128 32129 32130 32131 32132 32133 32134 32135 32136 32137 32138 32139 32140 32141 32142 32143 32144 32145 32146 32147 32148 32149 32150 32151 32152 32153 32154 32155 32156 32157 32158 32159 32160 32161 32162 32163 32164 32165 32166 32167 32168 32169 32170 32171 32172 32173 32174 32175 32176 32177 32178 32179 32180 32181 32182 32183 32184 32185 32186 32187 32188 32189 32190 32191 32192 32193 32194 32195 32196 32197 32198 32199 32200 32201 32202 32203 32204 32205 32206 32207 32208 32209 32210 32211 32212 32213 32214 32215 32216 32217 32218 32219 32220 32221 32222 32223 32224 32225 32226 32227 32228 32229 32230 32231 32232 32233 32234 32235 32236 32237 32238 32239 32240 32241 32242 32243 32244 32245 32246 32247 32248 32249 32250 32251 32252 32253 32254 32255 32256 32257 32258 32259 32260 32261 32262 32263 32264 32265 32266 32267 32268 32269 32270 32271 32272 32273 32274 32275 32276 32277 32278 32279 32280 32281 32282 32283 32284 32285 32286 32287 32288 32289 32290 32291 32292 32293 32294 32295 32296 32297 32298 32299 32300 32301 32302 32303 32304 32305 32306 32307 32308 32309 32310 32311 32312 32313 32314 32315 32316 32317 32318 32319 32320 32321 32322 32323 32324 32325 32326 32327 32328 32329 32330 32331 32332 32333 32334 32335 32336 32337 32338 32339 32340 32341 32342 32343 32344 32345 32346 32347 32348 32349 32350 32351 32352 32353 32354 32355 32356 32357 32358 32359 32360 32361 32362 32363 32364 32365 32366 32367 32368 32369 32370 32371 32372 32373 32374 32375 32376 32377 32378 32379 32380 32381 32382 32383 32384 32385 32386 32387 32388 32389 32390 32391 32392 32393 32394 32395 32396 32397 32398 32399 32400 32401 32402 32403 32404 32405 32406 32407 32408 32409 32410 32411 32412 32413 32414 32415 32416 32417 32418 32419 32420 32421 32422 32423 32424 32425 32426 32427 32428 32429 32430 32431 32432 32433 32434 32435 32436 32437 32438 32439 32440 32441 32442 32443 32444 32445 32446 32447 32448 32449 32450 32451 32452 32453 32454 32455 32456 32457 32458 32459 32460 32461 32462 32463 32464 32465 32466 32467 32468 32469 32470 32471 32472 32473 32474 32475 32476 32477 32478 32479 32480 32481 32482 32483 32484 32485 32486 32487 32488 32489 32490 32491 32492 32493 32494 32495 32496 32497 32498 32499 32500 32501 32502 32503 32504 32505 32506 32507 32508 32509 32510 32511 32512 32513 32514 32515 32516 32517 32518 32519 32520 32521 32522 32523 32524 32525 32526 32527 32528 32529 32530 32531 32532 32533 32534 32535 32536 32537 32538 32539 32540 32541 32542 32543 32544 32545 32546 32547 32548 32549 32550 32551 32552 32553 32554 32555 32556 32557 32558 32559 32560 32561 32562 32563 32564 32565 32566 32567 32568 32569 32570 32571 32572 32573 32574 32575 32576 32577 32578 32579 32580 32581 32582 32583 32584 32585 32586 32587 32588 32589 32590 32591 32592 32593 32594 32595 32596 32597 32598 32599 32600 32601 32602 32603 32604 32605 32606 32607 32608 32609 32610 32611 32612 32613 32614 32615 32616 32617 32618 32619 32620 32621 32622 32623 32624 32625 32626 32627 32628 32629 32630 32631 32632 32633 32634 32635 32636 32637 32638 32639 32640 32641 32642 32643 32644 32645 32646 32647 32648 32649 32650 32651 32652 32653 32654 32655 32656 32657 32658 32659 32660 32661 32662 32663 32664 32665 32666 32667 32668 32669 32670 32671 32672 32673 32674 32675 32676 32677 32678 32679 32680 32681 32682 32683 32684 32685 32686 32687 32688 32689 32690 32691 32692 32693 32694 32695 32696 32697 32698 32699 32700 32701 32702 32703 32704 32705 32706 32707 32708 32709 32710 32711 32712 32713 32714 32715 32716 32717 32718 32719 32720 32721 32722 32723 32724 32725 32726 32727 32728 32729 32730 32731 32732 32733 32734 32735 32736 32737 32738 32739 32740 32741 32742 32743 32744 32745 32746 32747 32748 32749 32750 32751 32752 32753 32754 32755 32756 32757 32758 32759 32760 32761 32762 32763 32764 32765 32766 32767 32768 32769 32770 32771 32772 32773 32774 32775 32776 32777 32778 32779 32780 32781 32782 32783 32784 32785 32786 32787 32788 32789 32790 32791 32792 32793 32794 32795 32796 32797 32798 32799 32800 32801 32802 32803 32804 32805 32806 32807 32808 32809 32810 32811 32812 32813 32814 32815 32816 32817 32818 32819 32820 32821 32822 32823 32824 32825 32826 32827 32828 32829 32830 32831 32832 32833 32834 32835 32836 32837 32838 32839 32840 32841 32842 32843 32844 32845 32846 32847 32848 32849 32850 32851 32852 32853 32854 32855 32856 32857 32858 32859 32860 32861 32862 32863 32864 32865 32866 32867 32868 32869 32870 32871 32872 32873 32874 32875 32876 32877 32878 32879 32880 32881 32882 32883 32884 32885 32886 32887 32888 32889 32890 32891 32892 32893 32894 32895 32896 32897 32898 32899 32900 32901 32902 32903 32904 32905 32906 32907 32908 32909 32910 32911 32912 32913 32914 32915 32916 32917 32918 32919 32920 32921 32922 32923 32924 32925 32926 32927 32928 32929 32930 32931 32932 32933 32934 32935 32936 32937 32938 32939 32940 32941 32942 32943 32944 32945 32946 32947 32948 32949 32950 32951 32952 32953 32954 32955 32956 32957 32958 32959 32960 32961 32962 32963 32964 32965 32966 32967 32968 32969 32970 32971 32972 32973 32974 32975 32976 32977 32978 32979 32980 32981 32982 32983 32984 32985 32986 32987 32988 32989 32990 32991 32992 32993 32994 32995 32996 32997 32998 32999 33000 33001 33002 33003 33004 33005 33006 33007 33008 33009 33010 33011 33012 33013 33014 33015 33016 33017 33018 33019 33020 33021 33022 33023 33024 33025 33026 33027 33028 33029 33030 33031 33032 33033 33034 33035 33036 33037 33038 33039 33040 33041 33042 33043 33044 33045 33046 33047 33048 33049 33050 33051 33052 33053 33054 33055 33056 33057 33058 33059 33060 33061 33062 33063 33064 33065 33066 33067 33068 33069 33070 33071 33072 33073 33074 33075 33076 33077 33078 33079 33080 33081 33082 33083 33084 33085 33086 33087 33088 33089 33090 33091 33092 33093 33094 33095 33096 33097 33098 33099 33100 33101 33102 33103 33104 33105 33106 33107 33108 33109 33110 33111 33112 33113 33114 33115 33116 33117 33118 33119 33120 33121 33122 33123 33124 33125 33126 33127 33128 33129 33130 33131 33132 33133 33134 33135 33136 33137 33138 33139 33140 33141 33142 33143 33144 33145 33146 33147 33148 33149 33150 33151 33152 33153 33154 33155 33156 33157 33158 33159 33160 33161 33162 33163 33164 33165 33166 33167 33168 33169 33170 33171 33172 33173 33174 33175 33176 33177 33178 33179 33180 33181 33182 33183 33184 33185 33186 33187 33188 33189 33190 33191 33192 33193 33194 33195 33196 33197 33198 33199 33200 33201 33202 33203 33204 33205 33206 33207 33208 33209 33210 33211 33212 33213 33214 33215 33216 33217 33218 33219 33220 33221 33222 33223 33224 33225 33226 33227 33228 33229 33230 33231 33232 33233 33234 33235 33236 33237 33238 33239 33240 33241 33242 33243 33244 33245 33246 33247 33248 33249 33250 33251 33252 33253 33254 33255 33256 33257 33258 33259 33260 33261 33262 33263 33264 33265 33266 33267 33268 33269 33270 33271 33272 33273 33274 33275 33276 33277 33278 33279 33280 33281 33282 33283 33284 33285 33286 33287 33288 33289 33290 33291 33292 33293 33294 33295 33296 33297 33298 33299 33300 33301 33302 33303 33304 33305 33306 33307 33308 33309 33310 33311 33312 33313 33314 33315 33316 33317 33318 33319 33320 33321 33322 33323 33324 33325 33326 33327 33328 33329 33330 33331 33332 33333 33334 33335 33336 33337 33338 33339 33340 33341 33342 33343 33344 33345 33346 33347 33348 33349 33350 33351 33352 33353 33354 33355 33356 33357 33358 33359 33360 33361 33362 33363 33364 33365 33366 33367 33368 33369 33370 33371 33372 33373 33374 33375 33376 33377 33378 33379 33380 33381 33382 33383 33384 33385 33386 33387 33388 33389 33390 33391 33392 33393 33394 33395 33396 33397 33398 33399 33400 33401 33402 33403 33404 33405 33406 33407 33408 33409 33410 33411 33412 33413 33414 33415 33416 33417 33418 33419 33420 33421 33422 33423 33424 33425 33426 33427 33428 33429 33430 33431 33432 33433 33434 33435 33436 33437 33438 33439 33440 33441 33442 33443 33444 33445 33446 33447 33448 33449 33450 33451 33452 33453 33454 33455 33456 33457 33458 33459 33460 33461 33462 33463 33464 33465 33466 33467 33468 33469 33470 33471 33472 33473 33474 33475 33476 33477 33478 33479 33480 33481 33482 33483 33484 33485 33486 33487 33488 33489 33490 33491 33492 33493 33494 33495 33496 33497 33498 33499 33500 33501 33502 33503 33504 33505 33506 33507 33508 33509 33510 33511 33512 33513 33514 33515 33516 33517 33518 33519 33520 33521 33522 33523 33524 33525 33526 33527 33528 33529 33530 33531 33532 33533 33534 33535 33536 33537 33538 33539 33540 33541 33542 33543 33544 33545 33546 33547 33548 33549 33550 33551 33552 33553 33554 33555 33556 33557 33558 33559 33560 33561 33562 33563 33564 33565 33566 33567 33568 33569 33570 33571 33572 33573 33574 33575 33576 33577 33578 33579 33580 33581 33582 33583 33584 33585 33586 33587 33588 33589 33590 33591 33592 33593 33594 33595 33596 33597 33598 33599 33600 33601 33602 33603 33604 33605 33606 33607 33608 33609 33610 33611 33612 33613 33614 33615 33616 33617 33618 33619 33620 33621 33622 33623 33624 33625 33626 33627 33628 33629 33630 33631 33632 33633 33634 33635 33636 33637 33638 33639 33640 33641 33642 33643 33644 33645 33646 33647 33648 33649 33650 33651 33652 33653 33654 33655 33656 33657 33658 33659 33660 33661 33662 33663 33664 33665 33666 33667 33668 33669 33670 33671 33672 33673 33674 33675 33676 33677 33678 33679 33680 33681 33682 33683 33684 33685 33686 33687 33688 33689 33690 33691 33692 33693 33694 33695 33696 33697 33698 33699 33700 33701 33702 33703 33704 33705 33706 33707 33708 33709 33710 33711 33712 33713 33714 33715 33716 33717 33718 33719 33720 33721 33722 33723 33724 33725 33726 33727 33728 33729 33730 33731 33732 33733 33734 33735 33736 33737 33738 33739 33740 33741 33742 33743 33744 33745 33746 33747 33748 33749 33750 33751 33752 33753 33754 33755 33756 33757 33758 33759 33760 33761 33762 33763 33764 33765 33766 33767 33768 33769 33770 33771 33772 33773 33774 33775 33776 33777 33778 33779 33780 33781 33782 33783 33784 33785 33786 33787 33788 33789 33790 33791 33792 33793 33794 33795 33796 33797 33798 33799 33800 33801 33802 33803 33804 33805 33806 33807 33808 33809 33810 33811 33812 33813 33814 33815 33816 33817 33818 33819 33820 33821 33822 33823 33824 33825 33826 33827 33828 33829 33830 33831 33832 33833 33834 33835 33836 33837 33838 33839 33840 33841 33842 33843 33844 33845 33846 33847 33848 33849 33850 33851 33852 33853 33854 33855 33856 33857 33858 33859 33860 33861 33862 33863 33864 33865 33866 33867 33868 33869 33870 33871 33872 33873 33874 33875 33876 33877 33878 33879 33880 33881 33882 33883 33884 33885 33886 33887 33888 33889 33890 33891 33892 33893 33894 33895 33896 33897 33898 33899 33900 33901 33902 33903 33904 33905 33906 33907 33908 33909 33910 33911 33912 33913 33914 33915 33916 33917 33918 33919 33920 33921 33922 33923 33924 33925 33926 33927 33928 33929 33930 33931 33932 33933 33934 33935 33936 33937 33938 33939 33940 33941 33942 33943 33944 33945 33946 33947 33948 33949 33950 33951 33952 33953 33954 33955 33956 33957 33958 33959 33960 33961 33962 33963 33964 33965 33966 33967 33968 33969 33970 33971 33972 33973 33974 33975 33976 33977 33978 33979 33980 33981 33982 33983 33984 33985 33986 33987 33988 33989 33990 33991 33992 33993 33994 33995 33996 33997 33998 33999 34000 34001 34002 34003 34004 34005 34006 34007 34008 34009 34010 34011 34012 34013 34014 34015 34016 34017 34018 34019 34020 34021 34022 34023 34024 34025 34026 34027 34028 34029 34030 34031 34032 34033 34034 34035 34036 34037 34038 34039 34040 34041 34042 34043 34044 34045 34046 34047 34048 34049 34050 34051 34052 34053 34054 34055 34056 34057 34058 34059 34060 34061 34062 34063 34064 34065 34066 34067 34068 34069 34070 34071 34072 34073 34074 34075 34076 34077 34078 34079 34080 34081 34082 34083 34084 34085 34086 34087 34088 34089 34090 34091 34092 34093 34094 34095 34096 34097 34098 34099 34100 34101 34102 34103 34104 34105 34106 34107 34108 34109 34110 34111 34112 34113 34114 34115 34116 34117 34118 34119 34120 34121 34122 34123 34124 34125 34126 34127 34128 34129 34130 34131 34132 34133 34134 34135 34136 34137 34138 34139 34140 34141 34142 34143 34144 34145 34146 34147 34148 34149 34150 34151 34152 34153 34154 34155 34156 34157 34158 34159 34160 34161 34162 34163 34164 34165 34166 34167 34168 34169 34170 34171 34172 34173 34174 34175 34176 34177 34178 34179 34180 34181 34182 34183 34184 34185 34186 34187 34188 34189 34190 34191 34192 34193 34194 34195 34196 34197 34198 34199 34200 34201 34202 34203 34204 34205 34206 34207 34208 34209 34210 34211 34212 34213 34214 34215 34216 34217 34218 34219 34220 34221 34222 34223 34224 34225 34226 34227 34228 34229 34230 34231 34232 34233 34234 34235 34236 34237 34238 34239 34240 34241 34242 34243 34244 34245 34246 34247 34248 34249 34250 34251 34252 34253 34254 34255 34256 34257 34258 34259 34260 34261 34262 34263 34264 34265 34266 34267 34268 34269 34270 34271 34272 34273 34274 34275 34276 34277 34278 34279 34280 34281 34282 34283 34284 34285 34286 34287 34288 34289 34290 34291 34292 34293 34294 34295 34296 34297 34298 34299 34300 34301 34302 34303 34304 34305 34306 34307 34308 34309 34310 34311 34312 34313 34314 34315 34316 34317 34318 34319 34320 34321 34322 34323 34324 34325 34326 34327 34328 34329 34330 34331 34332 34333 34334 34335 34336 34337 34338 34339 34340 34341 34342 34343 34344 34345 34346 34347 34348 34349 34350 34351 34352 34353 34354 34355 34356 34357 34358 34359 34360 34361 34362 34363 34364 34365 34366 34367 34368 34369 34370 34371 34372 34373 34374 34375 34376 34377 34378 34379 34380 34381 34382 34383 34384 34385 34386 34387 34388 34389 34390 34391 34392 34393 34394 34395 34396 34397 34398 34399 34400 34401 34402 34403 34404 34405 34406 34407 34408 34409 34410 34411 34412 34413 34414 34415 34416 34417 34418 34419 34420 34421 34422 34423 34424 34425 34426 34427 34428 34429 34430 34431 34432 34433 34434 34435 34436 34437 34438 34439 34440 34441 34442 34443 34444 34445 34446 34447 34448 34449 34450 34451 34452 34453 34454 34455 34456 34457 34458 34459 34460 34461 34462 34463 34464 34465 34466 34467 34468 34469 34470 34471 34472 34473 34474 34475 34476 34477 34478 34479 34480 34481 34482 34483 34484 34485 34486 34487 34488 34489 34490 34491 34492 34493 34494 34495 34496 34497 34498 34499 34500 34501 34502 34503 34504 34505 34506 34507 34508 34509 34510 34511 34512 34513 34514 34515 34516 34517 34518 34519 34520 34521 34522 34523 34524 34525 34526 34527 34528 34529 34530 34531 34532 34533 34534 34535 34536 34537 34538 34539 34540 34541 34542 34543 34544 34545 34546 34547 34548 34549 34550 34551 34552 34553 34554 34555 34556 34557 34558 34559 34560 34561 34562 34563 34564 34565 34566 34567 34568 34569 34570 34571 34572 34573 34574 34575 34576 34577 34578 34579 34580 34581 34582 34583 34584 34585 34586 34587 34588 34589 34590 34591 34592 34593 34594 34595 34596 34597 34598 34599 34600 34601 34602 34603 34604 34605 34606 34607 34608 34609 34610 34611 34612 34613 34614 34615 34616 34617 34618 34619 34620 34621 34622 34623 34624 34625 34626 34627 34628 34629 34630 34631 34632 34633 34634 34635 34636 34637 34638 34639 34640 34641 34642 34643 34644 34645 34646 34647 34648 34649 34650 34651 34652 34653 34654 34655 34656 34657 34658 34659 34660 34661 34662 34663 34664 34665 34666 34667 34668 34669 34670 34671 34672 34673 34674 34675 34676 34677 34678 34679 34680 34681 34682 34683 34684 34685 34686 34687 34688 34689 34690 34691 34692 34693 34694 34695 34696 34697 34698 34699 34700 34701 34702 34703 34704 34705 34706 34707 34708 34709 34710 34711 34712 34713 34714 34715 34716 34717 34718 34719 34720 34721 34722 34723 34724 34725 34726 34727 34728 34729 34730 34731 34732 34733 34734 34735 34736 34737 34738 34739 34740 34741 34742 34743 34744 34745 34746 34747 34748 34749 34750 34751 34752 34753 34754 34755 34756 34757 34758 34759 34760 34761 34762 34763 34764 34765 34766 34767 34768 34769 34770 34771 34772 34773 34774 34775 34776 34777 34778 34779 34780 34781 34782 34783 34784 34785 34786 34787 34788 34789 34790 34791 34792 34793 34794 34795 34796 34797 34798 34799 34800 34801 34802 34803 34804 34805 34806 34807 34808 34809 34810 34811 34812 34813 34814 34815 34816 34817 34818 34819 34820 34821 34822 34823 34824 34825 34826 34827 34828 34829 34830 34831 34832 34833 34834 34835 34836 34837 34838 34839 34840 34841 34842 34843 34844 34845 34846 34847 34848 34849 34850 34851 34852 34853 34854 34855 34856 34857 34858 34859 34860 34861 34862 34863 34864 34865 34866 34867 34868 34869 34870 34871 34872 34873 34874 34875 34876 34877 34878 34879 34880 34881 34882 34883 34884 34885 34886 34887 34888 34889 34890 34891 34892 34893 34894 34895 34896 34897 34898 34899 34900 34901 34902 34903 34904 34905 34906 34907 34908 34909 34910 34911 34912 34913 34914 34915 34916 34917 34918 34919 34920 34921 34922 34923 34924 34925 34926 34927 34928 34929 34930 34931 34932 34933 34934 34935 34936 34937 34938 34939 34940 34941 34942 34943 34944 34945 34946 34947 34948 34949 34950 34951 34952 34953 34954 34955 34956 34957 34958 34959 34960 34961 34962 34963 34964 34965 34966 34967 34968 34969 34970 34971 34972 34973 34974 34975 34976 34977 34978 34979 34980 34981 34982 34983 34984 34985 34986 34987 34988 34989 34990 34991 34992 34993 34994 34995 34996 34997 34998 34999 35000 35001 35002 35003 35004 35005 35006 35007 35008 35009 35010 35011 35012 35013 35014 35015 35016 35017 35018 35019 35020 35021 35022 35023 35024 35025 35026 35027 35028 35029 35030 35031 35032 35033 35034 35035 35036 35037 35038 35039 35040 35041 35042 35043 35044 35045 35046 35047 35048 35049 35050 35051 35052 35053 35054 35055 35056 35057 35058 35059 35060 35061 35062 35063 35064 35065 35066 35067 35068 35069 35070 35071 35072 35073 35074 35075 35076 35077 35078 35079 35080 35081 35082 35083 35084 35085 35086 35087 35088 35089 35090 35091 35092 35093 35094 35095 35096 35097 35098 35099 35100 35101 35102 35103 35104 35105 35106 35107 35108 35109 35110 35111 35112 35113 35114 35115 35116 35117 35118 35119 35120 35121 35122 35123 35124 35125 35126 35127 35128 35129 35130 35131 35132 35133 35134 35135 35136 35137 35138 35139 35140 35141 35142 35143 35144 35145 35146 35147 35148 35149 35150 35151 35152 35153 35154 35155 35156 35157 35158 35159 35160 35161 35162 35163 35164 35165 35166 35167 35168 35169 35170 35171 35172 35173 35174 35175 35176 35177 35178 35179 35180 35181 35182 35183 35184 35185 35186 35187 35188 35189 35190 35191 35192 35193 35194 35195 35196 35197 35198 35199 35200 35201 35202 35203 35204 35205 35206 35207 35208 35209 35210 35211 35212 35213 35214 35215 35216 35217 35218 35219 35220 35221 35222 35223 35224 35225 35226 35227 35228 35229 35230 35231 35232 35233 35234 35235 35236 35237 35238 35239 35240 35241 35242 35243 35244 35245 35246 35247 35248 35249 35250 35251 35252 35253 35254 35255 35256 35257 35258 35259 35260 35261 35262 35263 35264 35265 35266 35267 35268 35269 35270 35271 35272 35273 35274 35275 35276 35277 35278 35279 35280 35281 35282 35283 35284 35285 35286 35287 35288 35289 35290 35291 35292 35293 35294 35295 35296 35297 35298 35299 35300 35301 35302 35303 35304 35305 35306 35307 35308 35309 35310 35311 35312 35313 35314 35315 35316 35317 35318 35319 35320 35321 35322 35323 35324 35325 35326 35327 35328 35329 35330 35331 35332 35333 35334 35335 35336 35337 35338 35339 35340 35341 35342 35343 35344 35345 35346 35347 35348 35349 35350 35351 35352 35353 35354 35355 35356 35357 35358 35359 35360 35361 35362 35363 35364 35365 35366 35367 35368 35369 35370 35371 35372 35373 35374 35375 35376 35377 35378 35379 35380 35381 35382 35383 35384 35385 35386 35387 35388 35389 35390 35391 35392 35393 35394 35395 35396 35397 35398 35399 35400 35401 35402 35403 35404 35405 35406 35407 35408 35409 35410 35411 35412 35413 35414 35415 35416 35417 35418 35419 35420 35421 35422 35423 35424 35425 35426 35427 35428 35429 35430 35431 35432 35433 35434 35435 35436 35437 35438 35439 35440 35441 35442 35443 35444 35445 35446 35447 35448 35449 35450 35451 35452 35453 35454 35455 35456 35457 35458 35459 35460 35461 35462 35463 35464 35465 35466 35467 35468 35469 35470 35471 35472 35473 35474 35475 35476 35477 35478 35479 35480 35481 35482 35483 35484 35485 35486 35487 35488 35489 35490 35491 35492 35493 35494 35495 35496 35497 35498 35499 35500 35501 35502 35503 35504 35505 35506 35507 35508 35509 35510 35511 35512 35513 35514 35515 35516 35517 35518 35519 35520 35521 35522 35523 35524 35525 35526 35527 35528 35529 35530 35531 35532 35533 35534 35535 35536 35537 35538 35539 35540 35541 35542 35543 35544 35545 35546 35547 35548 35549 35550 35551 35552 35553 35554 35555 35556 35557 35558 35559 35560 35561 35562 35563 35564 35565 35566 35567 35568 35569 35570 35571 35572 35573 35574 35575 35576 35577 35578 35579 35580 35581 35582 35583 35584 35585 35586 35587 35588 35589 35590 35591 35592 35593 35594 35595 35596 35597 35598 35599 35600 35601 35602 35603 35604 35605 35606 35607 35608 35609 35610 35611 35612 35613 35614 35615 35616 35617 35618 35619 35620 35621 35622 35623 35624 35625 35626 35627 35628 35629 35630 35631 35632 35633 35634 35635 35636 35637 35638 35639 35640 35641 35642 35643 35644 35645 35646 35647 35648 35649 35650 35651 35652 35653 35654 35655 35656 35657 35658 35659 35660 35661 35662 35663 35664 35665 35666 35667 35668 35669 35670 35671 35672 35673 35674 35675 35676 35677 35678 35679 35680 35681 35682 35683 35684 35685 35686 35687 35688 35689 35690 35691 35692 35693 35694 35695 35696 35697 35698 35699 35700 35701 35702 35703 35704 35705 35706 35707 35708 35709 35710 35711 35712 35713 35714 35715 35716 35717 35718 35719 35720 35721 35722 35723 35724 35725 35726 35727 35728 35729 35730 35731 35732 35733 35734 35735 35736 35737 35738 35739 35740 35741 35742 35743 35744 35745 35746 35747 35748 35749 35750 35751 35752 35753 35754 35755 35756 35757 35758 35759 35760 35761 35762 35763 35764 35765 35766 35767 35768 35769 35770 35771 35772 35773 35774 35775 35776 35777 35778 35779 35780 35781 35782 35783 35784 35785 35786 35787 35788 35789 35790 35791 35792 35793 35794 35795 35796 35797 35798 35799 35800 35801 35802 35803 35804 35805 35806 35807 35808 35809 35810 35811 35812 35813 35814 35815 35816 35817 35818 35819 35820 35821 35822 35823 35824 35825 35826 35827 35828 35829 35830 35831 35832 35833 35834 35835 35836 35837 35838 35839 35840 35841 35842 35843 35844 35845 35846 35847 35848 35849 35850 35851 35852 35853 35854 35855 35856 35857 35858 35859 35860 35861 35862 35863 35864 35865 35866 35867 35868 35869 35870 35871 35872 35873 35874 35875 35876 35877 35878 35879 35880 35881 35882 35883 35884 35885 35886 35887 35888 35889 35890 35891 35892 35893 35894 35895 35896 35897 35898 35899 35900 35901 35902 35903 35904 35905 35906 35907 35908 35909 35910 35911 35912 35913 35914 35915 35916 35917 35918 35919 35920 35921 35922 35923 35924 35925 35926 35927 35928 35929 35930 35931 35932 35933 35934 35935 35936 35937 35938 35939 35940 35941 35942 35943 35944 35945 35946 35947 35948 35949 35950 35951 35952 35953 35954 35955 35956 35957 35958 35959 35960 35961 35962 35963 35964 35965 35966 35967 35968 35969 35970 35971 35972 35973 35974 35975 35976 35977 35978 35979 35980 35981 35982 35983 35984 35985 35986 35987 35988 35989 35990 35991 35992 35993 35994 35995 35996 35997 35998 35999 36000 36001 36002 36003 36004 36005 36006 36007 36008 36009 36010 36011 36012 36013 36014 36015 36016 36017 36018 36019 36020 36021 36022 36023 36024 36025 36026 36027 36028 36029 36030 36031 36032 36033 36034 36035 36036 36037 36038 36039 36040 36041 36042 36043 36044 36045 36046 36047 36048 36049 36050 36051 36052 36053 36054 36055 36056 36057 36058 36059 36060 36061 36062 36063 36064 36065 36066 36067 36068 36069 36070 36071 36072 36073 36074 36075 36076 36077 36078 36079 36080 36081 36082 36083 36084 36085 36086 36087 36088 36089 36090 36091 36092 36093 36094 36095 36096 36097 36098 36099 36100 36101 36102 36103 36104 36105 36106 36107 36108 36109 36110 36111 36112 36113 36114 36115 36116 36117 36118 36119 36120 36121 36122 36123 36124 36125 36126 36127 36128 36129 36130 36131 36132 36133 36134 36135 36136 36137 36138 36139 36140 36141 36142 36143 36144 36145 36146 36147 36148 36149 36150 36151 36152 36153 36154 36155 36156 36157 36158 36159 36160 36161 36162 36163 36164 36165 36166 36167 36168 36169 36170 36171 36172 36173 36174 36175 36176 36177 36178 36179 36180 36181 36182 36183 36184 36185 36186 36187 36188 36189 36190 36191 36192 36193 36194 36195 36196 36197 36198 36199 36200 36201 36202 36203 36204 36205 36206 36207 36208 36209 36210 36211 36212 36213 36214 36215 36216 36217 36218 36219 36220 36221 36222 36223 36224 36225 36226 36227 36228 36229 36230 36231 36232 36233 36234 36235 36236 36237 36238 36239 36240 36241 36242 36243 36244 36245 36246 36247 36248 36249 36250 36251 36252 36253 36254 36255 36256 36257 36258 36259 36260 36261 36262 36263 36264 36265 36266 36267 36268 36269 36270 36271 36272 36273 36274 36275 36276 36277 36278 36279 36280 36281 36282 36283 36284 36285 36286 36287 36288 36289 36290 36291 36292 36293 36294 36295 36296 36297 36298 36299 36300 36301 36302 36303 36304 36305 36306 36307 36308 36309 36310 36311 36312 36313 36314 36315 36316 36317 36318 36319 36320 36321 36322 36323 36324 36325 36326 36327 36328 36329 36330 36331 36332 36333 36334 36335 36336 36337 36338 36339 36340 36341 36342 36343 36344 36345 36346 36347 36348 36349 36350 36351 36352 36353 36354 36355 36356 36357 36358 36359 36360 36361 36362 36363 36364 36365 36366 36367 36368 36369 36370 36371 36372 36373 36374 36375 36376 36377 36378 36379 36380 36381 36382 36383 36384 36385 36386 36387 36388 36389 36390 36391 36392 36393 36394 36395 36396 36397 36398 36399 36400 36401 36402 36403 36404 36405 36406 36407 36408 36409 36410 36411 36412 36413 36414 36415 36416 36417 36418 36419 36420 36421 36422 36423 36424 36425 36426 36427 36428 36429 36430 36431 36432 36433 36434 36435 36436 36437 36438 36439 36440 36441 36442 36443 36444 36445 36446 36447 36448 36449 36450 36451 36452 36453 36454 36455 36456 36457 36458 36459 36460 36461 36462 36463 36464 36465 36466 36467 36468 36469 36470 36471 36472 36473 36474 36475 36476 36477 36478 36479 36480 36481 36482 36483 36484 36485 36486 36487 36488 36489 36490 36491 36492 36493 36494 36495 36496 36497 36498 36499 36500 36501 36502 36503 36504 36505 36506 36507 36508 36509 36510 36511 36512 36513 36514 36515 36516 36517 36518 36519 36520 36521 36522 36523 36524 36525 36526 36527 36528 36529 36530 36531 36532 36533 36534 36535 36536 36537 36538 36539 36540 36541 36542 36543 36544 36545 36546 36547 36548 36549 36550 36551 36552 36553 36554 36555 36556 36557 36558 36559 36560 36561 36562 36563 36564 36565 36566 36567 36568 36569 36570 36571 36572 36573 36574 36575 36576 36577 36578 36579 36580 36581 36582 36583 36584 36585 36586 36587 36588 36589 36590 36591 36592 36593 36594 36595 36596 36597 36598 36599 36600 36601 36602 36603 36604 36605 36606 36607 36608 36609 36610 36611 36612 36613 36614 36615 36616 36617 36618 36619 36620 36621 36622 36623 36624 36625 36626 36627 36628 36629 36630 36631 36632 36633 36634 36635 36636 36637 36638 36639 36640 36641 36642 36643 36644 36645 36646 36647 36648 36649 36650 36651 36652 36653 36654 36655 36656 36657 36658 36659 36660 36661 36662 36663 36664 36665 36666 36667 36668 36669 36670 36671 36672 36673 36674 36675 36676 36677 36678 36679 36680 36681 36682 36683 36684 36685 36686 36687 36688 36689 36690 36691 36692 36693 36694 36695 36696 36697 36698 36699 36700 36701 36702 36703 36704 36705 36706 36707 36708 36709 36710 36711 36712 36713 36714 36715 36716 36717 36718 36719 36720 36721 36722 36723 36724 36725 36726 36727 36728 36729 36730 36731 36732 36733 36734 36735 36736 36737 36738 36739 36740 36741 36742 36743 36744 36745 36746 36747 36748 36749 36750 36751 36752 36753 36754 36755 36756 36757 36758 36759 36760 36761 36762 36763 36764 36765 36766 36767 36768 36769 36770 36771 36772 36773 36774 36775 36776 36777 36778 36779 36780 36781 36782 36783 36784 36785 36786 36787 36788 36789 36790 36791 36792 36793 36794 36795 36796 36797 36798 36799 36800 36801 36802 36803 36804 36805 36806 36807 36808 36809 36810 36811 36812 36813 36814 36815 36816 36817 36818 36819 36820 36821 36822 36823 36824 36825 36826 36827 36828 36829 36830 36831 36832 36833 36834 36835 36836 36837 36838 36839 36840 36841 36842 36843 36844 36845 36846 36847 36848 36849 36850 36851 36852 36853 36854 36855 36856 36857 36858 36859 36860 36861 36862 36863 36864 36865 36866 36867 36868 36869 36870 36871 36872 36873 36874 36875 36876 36877 36878 36879 36880 36881 36882 36883 36884 36885 36886 36887 36888 36889 36890 36891 36892 36893 36894 36895 36896 36897 36898 36899 36900 36901 36902 36903 36904 36905 36906 36907 36908 36909 36910 36911 36912 36913 36914 36915 36916 36917 36918 36919 36920 36921 36922 36923 36924 36925 36926 36927 36928 36929 36930 36931 36932 36933 36934 36935 36936 36937 36938 36939 36940 36941 36942 36943 36944 36945 36946 36947 36948 36949 36950 36951 36952 36953 36954 36955 36956 36957 36958 36959 36960 36961 36962 36963 36964 36965 36966 36967 36968 36969 36970 36971 36972 36973 36974 36975 36976 36977 36978 36979 36980 36981 36982 36983 36984 36985 36986 36987 36988 36989 36990 36991 36992 36993 36994 36995 36996 36997 36998 36999 37000 37001 37002 37003 37004 37005 37006 37007 37008 37009 37010 37011 37012 37013 37014 37015 37016 37017 37018 37019 37020 37021 37022 37023 37024 37025 37026 37027 37028 37029 37030 37031 37032 37033 37034 37035 37036 37037 37038 37039 37040 37041 37042 37043 37044 37045 37046 37047 37048 37049 37050 37051 37052 37053 37054 37055 37056 37057 37058 37059 37060 37061 37062 37063 37064 37065 37066 37067 37068 37069 37070 37071 37072 37073 37074 37075 37076 37077 37078 37079 37080 37081 37082 37083 37084 37085 37086 37087 37088 37089 37090 37091 37092 37093 37094 37095 37096 37097 37098 37099 37100 37101 37102 37103 37104 37105 37106 37107 37108 37109 37110 37111 37112 37113 37114 37115 37116 37117 37118 37119 37120 37121 37122 37123 37124 37125 37126 37127 37128 37129 37130 37131 37132 37133 37134 37135 37136 37137 37138 37139 37140 37141 37142 37143 37144 37145 37146 37147 37148 37149 37150 37151 37152 37153 37154 37155 37156 37157 37158 37159 37160 37161 37162 37163 37164 37165 37166 37167 37168 37169 37170 37171 37172 37173 37174 37175 37176 37177 37178 37179 37180 37181 37182 37183 37184 37185 37186 37187 37188 37189 37190 37191 37192 37193 37194 37195 37196 37197 37198 37199 37200 37201 37202 37203 37204 37205 37206 37207 37208 37209 37210 37211 37212 37213 37214 37215 37216 37217 37218 37219 37220 37221 37222 37223 37224 37225 37226 37227 37228 37229 37230 37231 37232 37233 37234 37235 37236 37237 37238 37239 37240 37241 37242 37243 37244 37245 37246 37247 37248 37249 37250 37251 37252 37253 37254 37255 37256 37257 37258 37259 37260 37261 37262 37263 37264 37265 37266 37267 37268 37269 37270 37271 37272 37273 37274 37275 37276 37277 37278 37279 37280 37281 37282 37283 37284 37285 37286 37287 37288 37289 37290 37291 37292 37293 37294 37295 37296 37297 37298 37299 37300 37301 37302 37303 37304 37305 37306 37307 37308 37309 37310 37311 37312 37313 37314 37315 37316 37317 37318 37319 37320 37321 37322 37323 37324 37325 37326 37327 37328 37329 37330 37331 37332 37333 37334 37335 37336 37337 37338 37339 37340 37341 37342 37343 37344 37345 37346 37347 37348 37349 37350 37351 37352 37353 37354 37355 37356 37357 37358 37359 37360 37361 37362 37363 37364 37365 37366 37367 37368 37369 37370 37371 37372 37373 37374 37375 37376 37377 37378 37379 37380 37381 37382 37383 37384 37385 37386 37387 37388 37389 37390 37391 37392 37393 37394 37395 37396 37397 37398 37399 37400 37401 37402 37403 37404 37405 37406 37407 37408 37409 37410 37411 37412 37413 37414 37415 37416 37417 37418 37419 37420 37421 37422 37423 37424 37425 37426 37427 37428 37429 37430 37431 37432 37433 37434 37435 37436 37437 37438 37439 37440 37441 37442 37443 37444 37445 37446 37447 37448 37449 37450 37451 37452 37453 37454 37455 37456 37457 37458 37459 37460 37461 37462 37463 37464 37465 37466 37467 37468 37469 37470 37471 37472 37473 37474 37475 37476 37477 37478 37479 37480 37481 37482 37483 37484 37485 37486 37487 37488 37489 37490 37491 37492 37493 37494 37495 37496 37497 37498 37499 37500 37501 37502 37503 37504 37505 37506 37507 37508 37509 37510 37511 37512 37513 37514 37515 37516 37517 37518 37519 37520 37521 37522 37523 37524 37525 37526 37527 37528 37529 37530 37531 37532 37533 37534 37535 37536 37537 37538 37539 37540 37541 37542 37543 37544 37545 37546 37547 37548 37549 37550 37551 37552 37553 37554 37555 37556 37557 37558 37559 37560 37561 37562 37563 37564 37565 37566 37567 37568 37569 37570 37571 37572 37573 37574 37575 37576 37577 37578 37579 37580 37581 37582 37583 37584 37585 37586 37587 37588 37589 37590 37591 37592 37593 37594 37595 37596 37597 37598 37599 37600 37601 37602 37603 37604 37605 37606 37607 37608 37609 37610 37611 37612 37613 37614 37615 37616 37617 37618 37619 37620 37621 37622 37623 37624 37625 37626 37627 37628 37629 37630 37631 37632 37633 37634 37635 37636 37637 37638 37639 37640 37641 37642 37643 37644 37645 37646 37647 37648 37649 37650 37651 37652 37653 37654 37655 37656 37657 37658 37659 37660 37661 37662 37663 37664 37665 37666 37667 37668 37669 37670 37671 37672 37673 37674 37675 37676 37677 37678 37679 37680 37681 37682 37683 37684 37685 37686 37687 37688 37689 37690 37691 37692 37693 37694 37695 37696 37697 37698 37699 37700 37701 37702 37703 37704 37705 37706 37707 37708 37709 37710 37711 37712 37713 37714 37715 37716 37717 37718 37719 37720 37721 37722 37723 37724 37725 37726 37727 37728 37729 37730 37731 37732 37733 37734 37735 37736 37737 37738 37739 37740 37741 37742 37743 37744 37745 37746 37747 37748 37749 37750 37751 37752 37753 37754 37755 37756 37757 37758 37759 37760 37761 37762 37763 37764 37765 37766 37767 37768 37769 37770 37771 37772 37773 37774 37775 37776 37777 37778 37779 37780 37781 37782 37783 37784 37785 37786 37787 37788 37789 37790 37791 37792 37793 37794 37795 37796 37797 37798 37799 37800 37801 37802 37803 37804 37805 37806 37807 37808 37809 37810 37811 37812 37813 37814 37815 37816 37817 37818 37819 37820 37821 37822 37823 37824 37825 37826 37827 37828 37829 37830 37831 37832 37833 37834 37835 37836 37837 37838 37839 37840 37841 37842 37843 37844 37845 37846 37847 37848 37849 37850 37851 37852 37853 37854 37855 37856 37857 37858 37859 37860 37861 37862 37863 37864 37865 37866 37867 37868 37869 37870 37871 37872 37873 37874 37875 37876 37877 37878 37879 37880 37881 37882 37883 37884 37885 37886 37887 37888 37889 37890 37891 37892 37893 37894 37895 37896 37897 37898 37899 37900 37901 37902 37903 37904 37905 37906 37907 37908 37909 37910 37911 37912 37913 37914 37915 37916 37917 37918 37919 37920 37921 37922 37923 37924 37925 37926 37927 37928 37929 37930 37931 37932 37933 37934 37935 37936 37937 37938 37939 37940 37941 37942 37943 37944 37945 37946 37947 37948 37949 37950 37951 37952 37953 37954 37955 37956 37957 37958 37959 37960 37961 37962 37963 37964 37965 37966 37967 37968 37969 37970 37971 37972 37973 37974 37975 37976 37977 37978 37979 37980 37981 37982 37983 37984 37985 37986 37987 37988 37989 37990 37991 37992 37993 37994 37995 37996 37997 37998 37999 38000 38001 38002 38003 38004 38005 38006 38007 38008 38009 38010 38011 38012 38013 38014 38015 38016 38017 38018 38019 38020 38021 38022 38023 38024 38025 38026 38027 38028 38029 38030 38031 38032 38033 38034 38035 38036 38037 38038 38039 38040 38041 38042 38043 38044 38045 38046 38047 38048 38049 38050 38051 38052 38053 38054 38055 38056 38057 38058 38059 38060 38061 38062 38063 38064 38065 38066 38067 38068 38069 38070 38071 38072 38073 38074 38075 38076 38077 38078 38079 38080 38081 38082 38083 38084 38085 38086 38087 38088 38089 38090 38091 38092 38093 38094 38095 38096 38097 38098 38099 38100 38101 38102 38103 38104 38105 38106 38107 38108 38109 38110 38111 38112 38113 38114 38115 38116 38117 38118 38119 38120 38121 38122 38123 38124 38125 38126 38127 38128 38129 38130 38131 38132 38133 38134 38135 38136 38137 38138 38139 38140 38141 38142 38143 38144 38145 38146 38147 38148 38149 38150 38151 38152 38153 38154 38155 38156 38157 38158 38159 38160 38161 38162 38163 38164 38165 38166 38167 38168 38169 38170 38171 38172 38173 38174 38175 38176 38177 38178 38179 38180 38181 38182 38183 38184 38185 38186 38187 38188 38189 38190 38191 38192 38193 38194 38195 38196 38197 38198 38199 38200 38201 38202 38203 38204 38205 38206 38207 38208 38209 38210 38211 38212 38213 38214 38215 38216 38217 38218 38219 38220 38221 38222 38223 38224 38225 38226 38227 38228 38229 38230 38231 38232 38233 38234 38235 38236 38237 38238 38239 38240 38241 38242 38243 38244 38245 38246 38247 38248 38249 38250 38251 38252 38253 38254 38255 38256 38257 38258 38259 38260 38261 38262 38263 38264 38265 38266 38267 38268 38269 38270 38271 38272 38273 38274 38275 38276 38277 38278 38279 38280 38281 38282 38283 38284 38285 38286 38287 38288 38289 38290 38291 38292 38293 38294 38295 38296 38297 38298 38299 38300 38301 38302 38303 38304 38305 38306 38307 38308 38309 38310 38311 38312 38313 38314 38315 38316 38317 38318 38319 38320 38321 38322 38323 38324 38325 38326 38327 38328 38329 38330 38331 38332 38333 38334 38335 38336 38337 38338 38339 38340 38341 38342 38343 38344 38345 38346 38347 38348 38349 38350 38351 38352 38353 38354 38355 38356 38357 38358 38359 38360 38361 38362 38363 38364 38365 38366 38367 38368 38369 38370 38371 38372 38373 38374 38375 38376 38377 38378 38379 38380 38381 38382 38383 38384 38385 38386 38387 38388 38389 38390 38391 38392 38393 38394 38395 38396 38397 38398 38399 38400 38401 38402 38403 38404 38405 38406 38407 38408 38409 38410 38411 38412 38413 38414 38415 38416 38417 38418 38419 38420 38421 38422 38423 38424 38425 38426 38427 38428 38429 38430 38431 38432 38433 38434 38435 38436 38437 38438 38439 38440 38441 38442 38443 38444 38445 38446 38447 38448 38449 38450 38451 38452 38453 38454 38455 38456 38457 38458 38459 38460 38461 38462 38463 38464 38465 38466 38467 38468 38469 38470 38471 38472 38473 38474 38475 38476 38477 38478 38479 38480 38481 38482 38483 38484 38485 38486 38487 38488 38489 38490 38491 38492 38493 38494 38495 38496 38497 38498 38499 38500 38501 38502 38503 38504 38505 38506 38507 38508 38509 38510 38511 38512 38513 38514 38515 38516 38517 38518 38519 38520 38521 38522 38523 38524 38525 38526 38527 38528 38529 38530 38531 38532 38533 38534 38535 38536 38537 38538 38539 38540 38541 38542 38543 38544 38545 38546 38547 38548 38549 38550 38551 38552 38553 38554 38555 38556 38557 38558 38559 38560 38561 38562 38563 38564 38565 38566 38567 38568 38569 38570 38571 38572 38573 38574 38575 38576 38577 38578 38579 38580 38581 38582 38583 38584 38585 38586 38587 38588 38589 38590 38591 38592 38593 38594 38595 38596 38597 38598 38599 38600 38601 38602 38603 38604 38605 38606 38607 38608 38609 38610 38611 38612 38613 38614 38615 38616 38617 38618 38619 38620 38621 38622 38623 38624 38625 38626 38627 38628 38629 38630 38631 38632 38633 38634 38635 38636 38637 38638 38639 38640 38641 38642 38643 38644 38645 38646 38647 38648 38649 38650 38651 38652 38653 38654 38655 38656 38657 38658 38659 38660 38661 38662 38663 38664 38665 38666 38667 38668 38669 38670 38671 38672 38673 38674 38675 38676 38677 38678 38679 38680 38681 38682 38683 38684 38685 38686 38687 38688 38689 38690 38691 38692 38693 38694 38695 38696 38697 38698 38699 38700 38701 38702 38703 38704 38705 38706 38707 38708 38709 38710 38711 38712 38713 38714 38715 38716 38717 38718 38719 38720 38721 38722 38723 38724 38725 38726 38727 38728 38729 38730 38731 38732 38733 38734 38735 38736 38737 38738 38739 38740 38741 38742 38743 38744 38745 38746 38747 38748 38749 38750 38751 38752 38753 38754 38755 38756 38757 38758 38759 38760 38761 38762 38763 38764 38765 38766 38767 38768 38769 38770 38771 38772 38773 38774 38775 38776 38777 38778 38779 38780 38781 38782 38783 38784 38785 38786 38787 38788 38789 38790 38791 38792 38793 38794 38795 38796 38797 38798 38799 38800 38801 38802 38803 38804 38805 38806 38807 38808 38809 38810 38811 38812 38813 38814 38815 38816 38817 38818 38819 38820 38821 38822 38823 38824 38825 38826 38827 38828 38829 38830 38831 38832 38833 38834 38835 38836 38837 38838 38839 38840 38841 38842 38843 38844 38845 38846 38847 38848 38849 38850 38851 38852 38853 38854 38855 38856 38857 38858 38859 38860 38861 38862 38863 38864 38865 38866 38867 38868 38869 38870 38871 38872 38873 38874 38875 38876 38877 38878 38879 38880 38881 38882 38883 38884 38885 38886 38887 38888 38889 38890 38891 38892 38893 38894 38895 38896 38897 38898 38899 38900 38901 38902 38903 38904 38905 38906 38907 38908 38909 38910 38911 38912 38913 38914 38915 38916 38917 38918 38919 38920 38921 38922 38923 38924 38925 38926 38927 38928 38929 38930 38931 38932 38933 38934 38935 38936 38937 38938 38939 38940 38941 38942 38943 38944 38945 38946 38947 38948 38949 38950 38951 38952 38953 38954 38955 38956 38957 38958 38959 38960 38961 38962 38963 38964 38965 38966 38967 38968 38969 38970 38971 38972 38973 38974 38975 38976 38977 38978 38979 38980 38981 38982 38983 38984 38985 38986 38987 38988 38989 38990 38991 38992 38993 38994 38995 38996 38997 38998 38999 39000 39001 39002 39003 39004 39005 39006 39007 39008 39009 39010 39011 39012 39013 39014 39015 39016 39017 39018 39019 39020 39021 39022 39023 39024 39025 39026 39027 39028 39029 39030 39031 39032 39033 39034 39035 39036 39037 39038 39039 39040 39041 39042 39043 39044 39045 39046 39047 39048 39049 39050 39051 39052 39053 39054 39055 39056 39057 39058 39059 39060 39061 39062 39063 39064 39065 39066 39067 39068 39069 39070 39071 39072 39073 39074 39075 39076 39077 39078 39079 39080 39081 39082 39083 39084 39085 39086 39087 39088 39089 39090 39091 39092 39093 39094 39095 39096 39097 39098 39099 39100 39101 39102 39103 39104 39105 39106 39107 39108 39109 39110 39111 39112 39113 39114 39115 39116 39117 39118 39119 39120 39121 39122 39123 39124 39125 39126 39127 39128 39129 39130 39131 39132 39133 39134 39135 39136 39137 39138 39139 39140 39141 39142 39143 39144 39145 39146 39147 39148 39149 39150 39151 39152 39153 39154 39155 39156 39157 39158 39159 39160 39161 39162 39163 39164 39165 39166 39167 39168 39169 39170 39171 39172 39173 39174 39175 39176 39177 39178 39179 39180 39181 39182 39183 39184 39185 39186 39187 39188 39189 39190 39191 39192 39193 39194 39195 39196 39197 39198 39199 39200 39201 39202 39203 39204 39205 39206 39207 39208 39209 39210 39211 39212 39213 39214 39215 39216 39217 39218 39219 39220 39221 39222 39223 39224 39225 39226 39227 39228 39229 39230 39231 39232 39233 39234 39235 39236 39237 39238 39239 39240 39241 39242 39243 39244 39245 39246 39247 39248 39249 39250 39251 39252 39253 39254 39255 39256 39257 39258 39259 39260 39261 39262 39263 39264 39265 39266 39267 39268 39269 39270 39271 39272 39273 39274 39275 39276 39277 39278 39279 39280 39281 39282 39283 39284 39285 39286 39287 39288 39289 39290 39291 39292 39293 39294 39295 39296 39297 39298 39299 39300 39301 39302 39303 39304 39305 39306 39307 39308 39309 39310 39311 39312 39313 39314 39315 39316 39317 39318 39319 39320 39321 39322 39323 39324 39325 39326 39327 39328 39329 39330 39331 39332 39333 39334 39335 39336 39337 39338 39339 39340 39341 39342 39343 39344 39345 39346 39347 39348 39349 39350 39351 39352 39353 39354 39355 39356 39357 39358 39359 39360 39361 39362 39363 39364 39365 39366 39367 39368 39369 39370 39371 39372 39373 39374 39375 39376 39377 39378 39379 39380 39381 39382 39383 39384 39385 39386 39387 39388 39389 39390 39391 39392 39393 39394 39395 39396 39397 39398 39399 39400 39401 39402 39403 39404 39405 39406 39407 39408 39409 39410 39411 39412 39413 39414 39415 39416 39417 39418 39419 39420 39421 39422 39423 39424 39425 39426 39427 39428 39429 39430 39431 39432 39433 39434 39435 39436 39437 39438 39439 39440 39441 39442 39443 39444 39445 39446 39447 39448 39449 39450 39451 39452 39453 39454 39455 39456 39457 39458 39459 39460 39461 39462 39463 39464 39465 39466 39467 39468 39469 39470 39471 39472 39473 39474 39475 39476 39477 39478 39479 39480 39481 39482 39483 39484 39485 39486 39487 39488 39489 39490 39491 39492 39493 39494 39495 39496 39497 39498 39499 39500 39501 39502 39503 39504 39505 39506 39507 39508 39509 39510 39511 39512 39513 39514 39515 39516 39517 39518 39519 39520 39521 39522 39523 39524 39525 39526 39527 39528 39529 39530 39531 39532 39533 39534 39535 39536 39537 39538 39539 39540 39541 39542 39543 39544 39545 39546 39547 39548 39549 39550 39551 39552 39553 39554 39555 39556 39557 39558 39559 39560 39561 39562 39563 39564 39565 39566 39567 39568 39569 39570 39571 39572 39573 39574 39575 39576 39577 39578 39579 39580 39581 39582 39583 39584 39585 39586 39587 39588 39589 39590 39591 39592 39593 39594 39595 39596 39597 39598 39599 39600 39601 39602 39603 39604 39605 39606 39607 39608 39609 39610 39611 39612 39613 39614 39615 39616 39617 39618 39619 39620 39621 39622 39623 39624 39625 39626 39627 39628 39629 39630 39631 39632 39633 39634 39635 39636 39637 39638 39639 39640 39641 39642 39643 39644 39645 39646 39647 39648 39649 39650 39651 39652 39653 39654 39655 39656 39657 39658 39659 39660 39661 39662 39663 39664 39665 39666 39667 39668 39669 39670 39671 39672 39673 39674 39675 39676 39677 39678 39679 39680 39681 39682 39683 39684 39685 39686 39687 39688 39689 39690 39691 39692 39693 39694 39695 39696 39697 39698 39699 39700 39701 39702 39703 39704 39705 39706 39707 39708 39709 39710 39711 39712 39713 39714 39715 39716 39717 39718 39719 39720 39721 39722 39723 39724 39725 39726 39727 39728 39729 39730 39731 39732 39733 39734 39735 39736 39737 39738 39739 39740 39741 39742 39743 39744 39745 39746 39747 39748 39749 39750 39751 39752 39753 39754 39755 39756 39757 39758 39759 39760 39761 39762 39763 39764 39765 39766 39767 39768 39769 39770 39771 39772 39773 39774 39775 39776 39777 39778 39779 39780 39781 39782 39783 39784 39785 39786 39787 39788 39789 39790 39791 39792 39793 39794 39795 39796 39797 39798 39799 39800 39801 39802 39803 39804 39805 39806 39807 39808 39809 39810 39811 39812 39813 39814 39815 39816 39817 39818 39819 39820 39821 39822 39823 39824 39825 39826 39827 39828 39829 39830 39831 39832 39833 39834 39835 39836 39837 39838 39839 39840 39841 39842 39843 39844 39845 39846 39847 39848 39849 39850 39851 39852 39853 39854 39855 39856 39857 39858 39859 39860 39861 39862 39863 39864 39865 39866 39867 39868 39869 39870 39871 39872 39873 39874 39875 39876 39877 39878 39879 39880 39881 39882 39883 39884 39885 39886 39887 39888 39889 39890 39891 39892 39893 39894 39895 39896 39897 39898 39899 39900 39901 39902 39903 39904 39905 39906 39907 39908 39909 39910 39911 39912 39913 39914 39915 39916 39917 39918 39919 39920 39921 39922 39923 39924 39925 39926 39927 39928 39929 39930 39931 39932 39933 39934 39935 39936 39937 39938 39939 39940 39941 39942 39943 39944 39945 39946 39947 39948 39949 39950 39951 39952 39953 39954 39955 39956 39957 39958 39959 39960 39961 39962 39963 39964 39965 39966 39967 39968 39969 39970 39971 39972 39973 39974 39975 39976 39977 39978 39979 39980 39981 39982 39983 39984 39985 39986 39987 39988 39989 39990 39991 39992 39993 39994 39995 39996 39997 39998 39999 40000 40001 40002 40003 40004 40005 40006 40007 40008 40009 40010 40011 40012 40013 40014 40015 40016 40017 40018 40019 40020 40021 40022 40023 40024 40025 40026 40027 40028 40029 40030 40031 40032 40033 40034 40035 40036 40037 40038 40039 40040 40041 40042 40043 40044 40045 40046 40047 40048 40049 40050 40051 40052 40053 40054 40055 40056 40057 40058 40059 40060 40061 40062 40063 40064 40065 40066 40067 40068 40069 40070 40071 40072 40073 40074 40075 40076 40077 40078 40079 40080 40081 40082 40083 40084 40085 40086 40087 40088 40089 40090 40091 40092 40093 40094 40095 40096 40097 40098 40099 40100 40101 40102 40103 40104 40105 40106 40107 40108 40109 40110 40111 40112 40113 40114 40115 40116 40117 40118 40119 40120 40121 40122 40123 40124 40125 40126 40127 40128 40129 40130 40131 40132 40133 40134 40135 40136 40137 40138 40139 40140 40141 40142 40143 40144 40145 40146 40147 40148 40149 40150 40151 40152 40153 40154 40155 40156 40157 40158 40159 40160 40161 40162 40163 40164 40165 40166 40167 40168 40169 40170 40171 40172 40173 40174 40175 40176 40177 40178 40179 40180 40181 40182 40183 40184 40185 40186 40187 40188 40189 40190 40191 40192 40193 40194 40195 40196 40197 40198 40199 40200 40201 40202 40203 40204 40205 40206 40207 40208 40209 40210 40211 40212 40213 40214 40215 40216 40217 40218 40219 40220 40221 40222 40223 40224 40225 40226 40227 40228 40229 40230 40231 40232 40233 40234 40235 40236 40237 40238 40239 40240 40241 40242 40243 40244 40245 40246 40247 40248 40249 40250 40251 40252 40253 40254 40255 40256 40257 40258 40259 40260 40261 40262 40263 40264 40265 40266 40267 40268 40269 40270 40271 40272 40273 40274 40275 40276 40277 40278 40279 40280 40281 40282 40283 40284 40285 40286 40287 40288 40289 40290 40291 40292 40293 40294 40295 40296 40297 40298 40299 40300 40301 40302 40303 40304 40305 40306 40307 40308 40309 40310 40311 40312 40313 40314 40315 40316 40317 40318 40319 40320 40321 40322 40323 40324 40325 40326 40327 40328 40329 40330 40331 40332 40333 40334 40335 40336 40337 40338 40339 40340 40341 40342 40343 40344 40345 40346 40347 40348 40349 40350 40351 40352 40353 40354 40355 40356 40357 40358 40359 40360 40361 40362 40363 40364 40365 40366 40367 40368 40369 40370 40371 40372 40373 40374 40375 40376 40377 40378 40379 40380 40381 40382 40383 40384 40385 40386 40387 40388 40389 40390 40391 40392 40393 40394 40395 40396 40397 40398 40399 40400 40401 40402 40403 40404 40405 40406 40407 40408 40409 40410 40411 40412 40413 40414 40415 40416 40417 40418 40419 40420 40421 40422 40423 40424 40425 40426 40427 40428 40429 40430 40431 40432 40433 40434 40435 40436 40437 40438 40439 40440 40441 40442 40443 40444 40445 40446 40447 40448 40449 40450 40451 40452 40453 40454 40455 40456 40457 40458 40459 40460 40461 40462 40463 40464 40465 40466 40467 40468 40469 40470 40471 40472 40473 40474 40475 40476 40477 40478 40479 40480 40481 40482 40483 40484 40485 40486 40487 40488 40489 40490 40491 40492 40493 40494 40495 40496 40497 40498 40499 40500 40501 40502 40503 40504 40505 40506 40507 40508 40509 40510 40511 40512 40513 40514 40515 40516 40517 40518 40519 40520 40521 40522 40523 40524 40525 40526 40527 40528 40529 40530 40531 40532 40533 40534 40535 40536 40537 40538 40539 40540 40541 40542 40543 40544 40545 40546 40547 40548 40549 40550 40551 40552 40553 40554 40555 40556 40557 40558 40559 40560 40561 40562 40563 40564 40565 40566 40567 40568 40569 40570 40571 40572 40573 40574 40575 40576 40577 40578 40579 40580 40581 40582 40583 40584 40585 40586 40587 40588 40589 40590 40591 40592 40593 40594 40595 40596 40597 40598 40599 40600 40601 40602 40603 40604 40605 40606 40607 40608 40609 40610 40611 40612 40613 40614 40615 40616 40617 40618 40619 40620 40621 40622 40623 40624 40625 40626 40627 40628 40629 40630 40631 40632 40633 40634 40635 40636 40637 40638 40639 40640 40641 40642 40643 40644 40645 40646 40647 40648 40649 40650 40651 40652 40653 40654 40655 40656 40657 40658 40659 40660 40661 40662 40663 40664 40665 40666 40667 40668 40669 40670 40671 40672 40673 40674 40675 40676 40677 40678 40679 40680 40681 40682 40683 40684 40685 40686 40687 40688 40689 40690 40691 40692 40693 40694 40695 40696 40697 40698 40699 40700 40701 40702 40703 40704 40705 40706 40707 40708 40709 40710 40711 40712 40713 40714 40715 40716 40717 40718 40719 40720 40721 40722 40723 40724 40725 40726 40727 40728 40729 40730 40731 40732 40733 40734 40735 40736 40737 40738 40739 40740 40741 40742 40743 40744 40745 40746 40747 40748 40749 40750 40751 40752 40753 40754 40755 40756 40757 40758 40759 40760 40761 40762 40763 40764 40765 40766 40767 40768 40769 40770 40771 40772 40773 40774 40775 40776 40777 40778 40779 40780 40781 40782 40783 40784 40785 40786 40787 40788 40789 40790 40791 40792 40793 40794 40795 40796 40797 40798 40799 40800 40801 40802 40803 40804 40805 40806 40807 40808 40809 40810 40811 40812 40813 40814 40815 40816 40817 40818 40819 40820 40821 40822 40823 40824 40825 40826 40827 40828 40829 40830 40831 40832 40833 40834 40835 40836 40837 40838 40839 40840 40841 40842 40843 40844 40845 40846 40847 40848 40849 40850 40851 40852 40853 40854 40855 40856 40857 40858 40859 40860 40861 40862 40863 40864 40865 40866 40867 40868 40869 40870 40871 40872 40873 40874 40875 40876 40877 40878 40879 40880 40881 40882 40883 40884 40885 40886 40887 40888 40889 40890 40891 40892 40893 40894 40895 40896 40897 40898 40899 40900 40901 40902 40903 40904 40905 40906 40907 40908 40909 40910 40911 40912 40913 40914 40915 40916 40917 40918 40919 40920 40921 40922 40923 40924 40925 40926 40927 40928 40929 40930 40931 40932 40933 40934 40935 40936 40937 40938 40939 40940 40941 40942 40943 40944 40945 40946 40947 40948 40949 40950 40951 40952 40953 40954 40955 40956 40957 40958 40959 40960 40961 40962 40963 40964 40965 40966 40967 40968 40969 40970 40971 40972 40973 40974 40975 40976 40977 40978 40979 40980 40981 40982 40983 40984 40985 40986 40987 40988 40989 40990 40991 40992 40993 40994 40995 40996 40997 40998 40999 41000 41001 41002 41003 41004 41005 41006 41007 41008 41009 41010 41011 41012 41013 41014 41015 41016 41017 41018 41019 41020 41021 41022 41023 41024 41025 41026 41027 41028 41029 41030 41031 41032 41033 41034 41035 41036 41037 41038 41039 41040 41041 41042 41043 41044 41045 41046 41047 41048 41049 41050 41051 41052 41053 41054 41055 41056 41057 41058 41059 41060 41061 41062 41063 41064 41065 41066 41067 41068 41069 41070 41071 41072 41073 41074 41075 41076 41077 41078 41079 41080 41081 41082 41083 41084 41085 41086 41087 41088 41089 41090 41091 41092 41093 41094 41095 41096 41097 41098 41099 41100 41101 41102 41103 41104 41105 41106 41107 41108 41109 41110 41111 41112 41113 41114 41115 41116 41117 41118 41119 41120 41121 41122 41123 41124 41125 41126 41127 41128 41129 41130 41131 41132 41133 41134 41135 41136 41137 41138 41139 41140 41141 41142 41143 41144 41145 41146 41147 41148 41149 41150 41151 41152 41153 41154 41155 41156 41157 41158 41159 41160 41161 41162 41163 41164 41165 41166 41167 41168 41169 41170 41171 41172 41173 41174 41175 41176 41177 41178 41179 41180 41181 41182 41183 41184 41185 41186 41187 41188 41189 41190 41191 41192 41193 41194 41195 41196 41197 41198 41199 41200 41201 41202 41203 41204 41205 41206 41207 41208 41209 41210 41211 41212 41213 41214 41215 41216 41217 41218 41219 41220 41221 41222 41223 41224 41225 41226 41227 41228 41229 41230 41231 41232 41233 41234 41235 41236 41237 41238 41239 41240 41241 41242 41243 41244 41245 41246 41247 41248 41249 41250 41251 41252 41253 41254 41255 41256 41257 41258 41259 41260 41261 41262 41263 41264 41265 41266 41267 41268 41269 41270 41271 41272 41273 41274 41275 41276 41277 41278 41279 41280 41281 41282 41283 41284 41285 41286 41287 41288 41289 41290 41291 41292 41293 41294 41295 41296 41297 41298 41299 41300 41301 41302 41303 41304 41305 41306 41307 41308 41309 41310 41311 41312 41313 41314 41315 41316 41317 41318 41319 41320 41321 41322 41323 41324 41325 41326 41327 41328 41329 41330 41331 41332 41333 41334 41335 41336 41337 41338 41339 41340 41341 41342 41343 41344 41345 41346 41347 41348 41349 41350 41351 41352 41353 41354 41355 41356 41357 41358 41359 41360 41361 41362 41363 41364 41365 41366 41367 41368 41369 41370 41371 41372 41373 41374 41375 41376 41377 41378 41379 41380 41381 41382 41383 41384 41385 41386 41387 41388 41389 41390 41391 41392 41393 41394 41395 41396 41397 41398 41399 41400 41401 41402 41403 41404 41405 41406 41407 41408 41409 41410 41411 41412 41413 41414 41415 41416 41417 41418 41419 41420 41421 41422 41423 41424 41425 41426 41427 41428 41429 41430 41431 41432 41433 41434 41435 41436 41437 41438 41439 41440 41441 41442 41443 41444 41445 41446 41447 41448 41449 41450 41451 41452 41453 41454 41455 41456 41457 41458 41459 41460 41461 41462 41463 41464 41465 41466 41467 41468 41469 41470 41471 41472 41473 41474 41475 41476 41477 41478 41479 41480 41481 41482 41483 41484 41485 41486 41487 41488 41489 41490 41491 41492 41493 41494 41495 41496 41497 41498 41499 41500 41501 41502 41503 41504 41505 41506 41507 41508 41509 41510 41511 41512 41513 41514 41515 41516 41517 41518 41519 41520 41521 41522 41523 41524 41525 41526 41527 41528 41529 41530 41531 41532 41533 41534 41535 41536 41537 41538 41539 41540 41541 41542 41543 41544 41545 41546 41547 41548 41549 41550 41551 41552 41553 41554 41555 41556 41557 41558 41559 41560 41561 41562 41563 41564 41565 41566 41567 41568 41569 41570 41571 41572 41573 41574 41575 41576 41577 41578 41579 41580 41581 41582 41583 41584 41585 41586 41587 41588 41589 41590 41591 41592 41593 41594 41595 41596 41597 41598 41599 41600 41601 41602 41603 41604 41605 41606 41607 41608 41609 41610 41611 41612 41613 41614 41615 41616 41617 41618 41619 41620 41621 41622 41623 41624 41625 41626 41627 41628 41629 41630 41631 41632 41633 41634 41635 41636 41637 41638 41639 41640 41641 41642 41643 41644 41645 41646 41647 41648 41649 41650 41651 41652 41653 41654 41655 41656 41657 41658 41659 41660 41661 41662 41663 41664 41665 41666 41667 41668 41669 41670 41671 41672 41673 41674 41675 41676 41677 41678 41679 41680 41681 41682 41683 41684 41685 41686 41687 41688 41689 41690 41691 41692 41693 41694 41695 41696 41697 41698 41699 41700 41701 41702 41703 41704 41705 41706 41707 41708 41709 41710 41711 41712 41713 41714 41715 41716 41717 41718 41719 41720 41721 41722 41723 41724 41725 41726 41727 41728 41729 41730 41731 41732 41733 41734 41735 41736 41737 41738 41739 41740 41741 41742 41743 41744 41745 41746 41747 41748 41749 41750 41751 41752 41753 41754 41755 41756 41757 41758 41759 41760 41761 41762 41763 41764 41765 41766 41767 41768 41769 41770 41771 41772 41773 41774 41775 41776 41777 41778 41779 41780 41781 41782 41783 41784 41785 41786 41787 41788 41789 41790 41791 41792 41793 41794 41795 41796 41797 41798 41799 41800 41801 41802 41803 41804 41805 41806 41807 41808 41809 41810 41811 41812 41813 41814 41815 41816 41817 41818 41819 41820 41821 41822 41823 41824 41825 41826 41827 41828 41829 41830 41831 41832 41833 41834 41835 41836 41837 41838 41839 41840 41841 41842 41843 41844 41845 41846 41847 41848 41849 41850 41851 41852 41853 41854 41855 41856 41857 41858 41859 41860 41861 41862 41863 41864 41865 41866 41867 41868 41869 41870 41871 41872 41873 41874 41875 41876 41877 41878 41879 41880 41881 41882 41883 41884 41885 41886 41887 41888 41889 41890 41891 41892 41893 41894 41895 41896 41897 41898 41899 41900 41901 41902 41903 41904 41905 41906 41907 41908 41909 41910 41911 41912 41913 41914 41915 41916 41917 41918 41919 41920 41921 41922 41923 41924 41925 41926 41927 41928 41929 41930 41931 41932 41933 41934 41935 41936 41937 41938 41939 41940 41941 41942 41943 41944 41945 41946 41947 41948 41949 41950 41951 41952 41953 41954 41955 41956 41957 41958 41959 41960 41961 41962 41963 41964 41965 41966 41967 41968 41969 41970 41971 41972 41973 41974 41975 41976 41977 41978 41979 41980 41981 41982 41983 41984 41985 41986 41987 41988 41989 41990 41991 41992 41993 41994 41995 41996 41997 41998 41999 42000 42001 42002 42003 42004 42005 42006 42007 42008 42009 42010 42011 42012 42013 42014 42015 42016 42017 42018 42019 42020 42021 42022 42023 42024 42025 42026 42027 42028 42029 42030 42031 42032 42033 42034 42035 42036 42037 42038 42039 42040 42041 42042 42043 42044 42045 42046 42047 42048 42049 42050 42051 42052 42053 42054 42055 42056 42057 42058 42059 42060 42061 42062 42063 42064 42065 42066 42067 42068 42069 42070 42071 42072 42073 42074 42075 42076 42077 42078 42079 42080 42081 42082 42083 42084 42085 42086 42087 42088 42089 42090 42091 42092 42093 42094 42095 42096 42097 42098 42099 42100 42101 42102 42103 42104 42105 42106 42107 42108 42109 42110 42111 42112 42113 42114 42115 42116 42117 42118 42119 42120 42121 42122 42123 42124 42125 42126 42127 42128 42129 42130 42131 42132 42133 42134 42135 42136 42137 42138 42139 42140 42141 42142 42143 42144 42145 42146 42147 42148 42149 42150 42151 42152 42153 42154 42155 42156 42157 42158 42159 42160 42161 42162 42163 42164 42165 42166 42167 42168 42169 42170 42171 42172 42173 42174 42175 42176 42177 42178 42179 42180 42181 42182 42183 42184 42185 42186 42187 42188 42189 42190 42191 42192 42193 42194 42195 42196 42197 42198 42199 42200 42201 42202 42203 42204 42205 42206 42207 42208 42209 42210 42211 42212 42213 42214 42215 42216 42217 42218 42219 42220 42221 42222 42223 42224 42225 42226 42227 42228 42229 42230 42231 42232 42233 42234 42235 42236 42237 42238 42239 42240 42241 42242 42243 42244 42245 42246 42247 42248 42249 42250 42251 42252 42253 42254 42255 42256 42257 42258 42259 42260 42261 42262 42263 42264 42265 42266 42267 42268 42269 42270 42271 42272 42273 42274 42275 42276 42277 42278 42279 42280 42281 42282 42283 42284 42285 42286 42287 42288 42289 42290 42291 42292 42293 42294 42295 42296 42297 42298 42299 42300 42301 42302 42303 42304 42305 42306 42307 42308 42309 42310 42311 42312 42313 42314 42315 42316 42317 42318 42319 42320 42321 42322 42323 42324 42325 42326 42327 42328 42329 42330 42331 42332 42333 42334 42335 42336 42337 42338 42339 42340 42341 42342 42343 42344 42345 42346 42347 42348 42349 42350 42351 42352 42353 42354 42355 42356 42357 42358 42359 42360 42361 42362 42363 42364 42365 42366 42367 42368 42369 42370 42371 42372 42373 42374 42375 42376 42377 42378 42379 42380 42381 42382 42383 42384 42385 42386 42387 42388 42389 42390 42391 42392 42393 42394 42395 42396 42397 42398 42399 42400 42401 42402 42403 42404 42405 42406 42407 42408 42409 42410 42411 42412 42413 42414 42415 42416 42417 42418 42419 42420 42421 42422 42423 42424 42425 42426 42427 42428 42429 42430 42431 42432 42433 42434 42435 42436 42437 42438 42439 42440 42441 42442 42443 42444 42445 42446 42447 42448 42449 42450 42451 42452 42453 42454 42455 42456 42457 42458 42459 42460 42461 42462 42463 42464 42465 42466 42467 42468 42469 42470 42471 42472 42473 42474 42475 42476 42477 42478 42479 42480 42481 42482 42483 42484 42485 42486 42487 42488 42489 42490 42491 42492 42493 42494 42495 42496 42497 42498 42499 42500 42501 42502 42503 42504 42505 42506 42507 42508 42509 42510 42511 42512 42513 42514 42515 42516 42517 42518 42519 42520 42521 42522 42523 42524 42525 42526 42527 42528 42529 42530 42531 42532 42533 42534 42535 42536 42537 42538 42539 42540 42541 42542 42543 42544 42545 42546 42547 42548 42549 42550 42551 42552 42553 42554 42555 42556 42557 42558 42559 42560 42561 42562 42563 42564 42565 42566 42567 42568 42569 42570 42571 42572 42573 42574 42575 42576 42577 42578 42579 42580 42581 42582 42583 42584 42585 42586 42587 42588 42589 42590 42591 42592 42593 42594 42595 42596 42597 42598 42599 42600 42601 42602 42603 42604 42605 42606 42607 42608 42609 42610 42611 42612 42613 42614 42615 42616 42617 42618 42619 42620 42621 42622 42623 42624 42625 42626 42627 42628 42629 42630 42631 42632 42633 42634 42635 42636 42637 42638 42639 42640 42641 42642 42643 42644 42645 42646 42647 42648 42649 42650 42651 42652 42653 42654 42655 42656 42657 42658 42659 42660 42661 42662 42663 42664 42665 42666 42667 42668 42669 42670 42671 42672 42673 42674 42675 42676 42677 42678 42679 42680 42681 42682 42683 42684 42685 42686 42687 42688 42689 42690 42691 42692 42693 42694 42695 42696 42697 42698 42699 42700 42701 42702 42703 42704 42705 42706 42707 42708 42709 42710 42711 42712 42713 42714 42715 42716 42717 42718 42719 42720 42721 42722 42723 42724 42725 42726 42727 42728 42729 42730 42731 42732 42733 42734 42735 42736 42737 42738 42739 42740 42741 42742 42743 42744 42745 42746 42747 42748 42749 42750 42751 42752 42753 42754 42755 42756 42757 42758 42759 42760 42761 42762 42763 42764 42765 42766 42767 42768 42769 42770 42771 42772 42773 42774 42775 42776 42777 42778 42779 42780 42781 42782 42783 42784 42785 42786 42787 42788 42789 42790 42791 42792 42793 42794 42795 42796 42797 42798 42799 42800 42801 42802 42803 42804 42805 42806 42807 42808 42809 42810 42811 42812 42813 42814 42815 42816 42817 42818 42819 42820 42821 42822 42823 42824 42825 42826 42827 42828 42829 42830 42831 42832 42833 42834 42835 42836 42837 42838 42839 42840 42841 42842 42843 42844 42845 42846 42847 42848 42849 42850 42851 42852 42853 42854 42855 42856 42857 42858 42859 42860 42861 42862 42863 42864 42865 42866 42867 42868 42869 42870 42871 42872 42873 42874 42875 42876 42877 42878 42879 42880 42881 42882 42883 42884 42885 42886 42887 42888 42889 42890 42891 42892 42893 42894 42895 42896 42897 42898 42899 42900 42901 42902 42903 42904 42905 42906 42907 42908 42909 42910 42911 42912 42913 42914 42915 42916 42917 42918 42919 42920 42921 42922 42923 42924 42925 42926 42927 42928 42929 42930 42931 42932 42933 42934 42935 42936 42937 42938 42939 42940 42941 42942 42943 42944 42945 42946 42947 42948 42949 42950 42951 42952 42953 42954 42955 42956 42957 42958 42959 42960 42961 42962 42963 42964 42965 42966 42967 42968 42969 42970 42971 42972 42973 42974 42975 42976 42977 42978 42979 42980 42981 42982 42983 42984 42985 42986 42987 42988 42989 42990 42991 42992 42993 42994 42995 42996 42997 42998 42999 43000 43001 43002 43003 43004 43005 43006 43007 43008 43009 43010 43011 43012 43013 43014 43015 43016 43017 43018 43019 43020 43021 43022 43023 43024 43025 43026 43027 43028 43029 43030 43031 43032 43033 43034 43035 43036 43037 43038 43039 43040 43041 43042 43043 43044 43045 43046 43047 43048 43049 43050 43051 43052 43053 43054 43055 43056 43057 43058 43059 43060 43061 43062 43063 43064 43065 43066 43067 43068 43069 43070 43071 43072 43073 43074 43075 43076 43077 43078 43079 43080 43081 43082 43083 43084 43085 43086 43087 43088 43089 43090 43091 43092 43093 43094 43095 43096 43097 43098 43099 43100 43101 43102 43103 43104 43105 43106 43107 43108 43109 43110 43111 43112 43113 43114 43115 43116 43117 43118 43119 43120 43121 43122 43123 43124 43125 43126 43127 43128 43129 43130 43131 43132 43133 43134 43135 43136 43137 43138 43139 43140 43141 43142 43143 43144 43145 43146 43147 43148 43149 43150 43151 43152 43153 43154 43155 43156 43157 43158 43159 43160 43161 43162 43163 43164 43165 43166 43167 43168 43169 43170 43171 43172 43173 43174 43175 43176 43177 43178 43179 43180 43181 43182 43183 43184 43185 43186 43187 43188 43189 43190 43191 43192 43193 43194 43195 43196 43197 43198 43199 43200 43201 43202 43203 43204 43205 43206 43207 43208 43209 43210 43211 43212 43213 43214 43215 43216 43217 43218 43219 43220 43221 43222 43223 43224 43225 43226 43227 43228 43229 43230 43231 43232 43233 43234 43235 43236 43237 43238 43239 43240 43241 43242 43243 43244 43245 43246 43247 43248 43249 43250 43251 43252 43253 43254 43255 43256 43257 43258 43259 43260 43261 43262 43263 43264 43265 43266 43267 43268 43269 43270 43271 43272 43273 43274 43275 43276 43277 43278 43279 43280 43281 43282 43283 43284 43285 43286 43287 43288 43289 43290 43291 43292 43293 43294 43295 43296 43297 43298 43299 43300 43301 43302 43303 43304 43305 43306 43307 43308 43309 43310 43311 43312 43313 43314 43315 43316 43317 43318 43319 43320 43321 43322 43323 43324 43325 43326 43327 43328 43329 43330 43331 43332 43333 43334 43335 43336 43337 43338 43339 43340 43341 43342 43343 43344 43345 43346 43347 43348 43349 43350 43351 43352 43353 43354 43355 43356 43357 43358 43359 43360 43361 43362 43363 43364 43365 43366 43367 43368 43369 43370 43371 43372 43373 43374 43375 43376 43377 43378 43379 43380 43381 43382 43383 43384 43385 43386 43387 43388 43389 43390 43391 43392 43393 43394 43395 43396 43397 43398 43399 43400 43401 43402 43403 43404 43405 43406 43407 43408 43409 43410 43411 43412 43413 43414 43415 43416 43417 43418 43419 43420 43421 43422 43423 43424 43425 43426 43427 43428 43429 43430 43431 43432 43433 43434 43435 43436 43437 43438 43439 43440 43441 43442 43443 43444 43445 43446 43447 43448 43449 43450 43451 43452 43453 43454 43455 43456 43457 43458 43459 43460 43461 43462 43463 43464 43465 43466 43467 43468 43469 43470 43471 43472 43473 43474 43475 43476 43477 43478 43479 43480 43481 43482 43483 43484 43485 43486 43487 43488 43489 43490 43491 43492 43493 43494 43495 43496 43497 43498 43499 43500 43501 43502 43503 43504 43505 43506 43507 43508 43509 43510 43511 43512 43513 43514 43515 43516 43517 43518 43519 43520 43521 43522 43523 43524 43525 43526 43527 43528 43529 43530 43531 43532 43533 43534 43535 43536 43537 43538 43539 43540 43541 43542 43543 43544 43545 43546 43547 43548 43549 43550 43551 43552 43553 43554 43555 43556 43557 43558 43559 43560 43561 43562 43563 43564 43565 43566 43567 43568 43569 43570 43571 43572 43573 43574 43575 43576 43577 43578 43579 43580 43581 43582 43583 43584 43585 43586 43587 43588 43589 43590 43591 43592 43593 43594 43595 43596 43597 43598 43599 43600 43601 43602 43603 43604 43605 43606 43607 43608 43609 43610 43611 43612 43613 43614 43615 43616 43617 43618 43619 43620 43621 43622 43623 43624 43625 43626 43627 43628 43629 43630 43631 43632 43633 43634 43635 43636 43637 43638 43639 43640 43641 43642 43643 43644 43645 43646 43647 43648 43649 43650 43651 43652 43653 43654 43655 43656 43657 43658 43659 43660 43661 43662 43663 43664 43665 43666 43667 43668 43669 43670 43671 43672 43673 43674 43675 43676 43677 43678 43679 43680 43681 43682 43683 43684 43685 43686 43687 43688 43689 43690 43691 43692 43693 43694 43695 43696 43697 43698 43699 43700 43701 43702 43703 43704 43705 43706 43707 43708 43709 43710 43711 43712 43713 43714 43715 43716 43717 43718 43719 43720 43721 43722 43723 43724 43725 43726 43727 43728 43729 43730 43731 43732 43733 43734 43735 43736 43737 43738 43739 43740 43741 43742 43743 43744 43745 43746 43747 43748 43749 43750 43751 43752 43753 43754 43755 43756 43757 43758 43759 43760 43761 43762 43763 43764 43765 43766 43767 43768 43769 43770 43771 43772 43773 43774 43775 43776 43777 43778 43779 43780 43781 43782 43783 43784 43785 43786 43787 43788 43789 43790 43791 43792 43793 43794 43795 43796 43797 43798 43799 43800 43801 43802 43803 43804 43805 43806 43807 43808 43809 43810 43811 43812 43813 43814 43815 43816 43817 43818 43819 43820 43821 43822 43823 43824 43825 43826 43827 43828 43829 43830 43831 43832 43833 43834 43835 43836 43837 43838 43839 43840 43841 43842 43843 43844 43845 43846 43847 43848 43849 43850 43851 43852 43853 43854 43855 43856 43857 43858 43859 43860 43861 43862 43863 43864 43865 43866 43867 43868 43869 43870 43871 43872 43873 43874 43875 43876 43877 43878 43879 43880 43881 43882 43883 43884 43885 43886 43887 43888 43889 43890 43891 43892 43893 43894 43895 43896 43897 43898 43899 43900 43901 43902 43903 43904 43905 43906 43907 43908 43909 43910 43911 43912 43913 43914 43915 43916 43917 43918 43919 43920 43921 43922 43923 43924 43925 43926 43927 43928 43929 43930 43931 43932 43933 43934 43935 43936 43937 43938 43939 43940 43941 43942 43943 43944 43945 43946 43947 43948 43949 43950 43951 43952 43953 43954 43955 43956 43957 43958 43959 43960 43961 43962 43963 43964 43965 43966 43967 43968 43969 43970 43971 43972 43973 43974 43975 43976 43977 43978 43979 43980 43981 43982 43983 43984 43985 43986 43987 43988 43989 43990 43991 43992 43993 43994 43995 43996 43997 43998 43999 44000 44001 44002 44003 44004 44005 44006 44007 44008 44009 44010 44011 44012 44013 44014 44015 44016 44017 44018 44019 44020 44021 44022 44023 44024 44025 44026 44027 44028 44029 44030 44031 44032 44033 44034 44035 44036 44037 44038 44039 44040 44041 44042 44043 44044 44045 44046 44047 44048 44049 44050 44051 44052 44053 44054 44055 44056 44057 44058 44059 44060 44061 44062 44063 44064 44065 44066 44067 44068 44069 44070 44071 44072 44073 44074 44075 44076 44077 44078 44079 44080 44081 44082 44083 44084 44085 44086 44087 44088 44089 44090 44091 44092 44093 44094 44095 44096 44097 44098 44099 44100 44101 44102 44103 44104 44105 44106 44107 44108 44109 44110 44111 44112 44113 44114 44115 44116 44117 44118 44119 44120 44121 44122 44123 44124 44125 44126 44127 44128 44129 44130 44131 44132 44133 44134 44135 44136 44137 44138 44139 44140 44141 44142 44143 44144 44145 44146 44147 44148 44149 44150 44151 44152 44153 44154 44155 44156 44157 44158 44159 44160 44161 44162 44163 44164 44165 44166 44167 44168 44169 44170 44171 44172 44173 44174 44175 44176 44177 44178 44179 44180 44181 44182 44183 44184 44185 44186 44187 44188 44189 44190 44191 44192 44193 44194 44195 44196 44197 44198 44199 44200 44201 44202 44203 44204 44205 44206 44207 44208 44209 44210 44211 44212 44213 44214 44215 44216 44217 44218 44219 44220 44221 44222 44223 44224 44225 44226 44227 44228 44229 44230 44231 44232 44233 44234 44235 44236 44237 44238 44239 44240 44241 44242 44243 44244 44245 44246 44247 44248 44249 44250 44251 44252 44253 44254 44255 44256 44257 44258 44259 44260 44261 44262 44263 44264 44265 44266 44267 44268 44269 44270 44271 44272 44273 44274 44275 44276 44277 44278 44279 44280 44281 44282 44283 44284 44285 44286 44287 44288 44289 44290 44291 44292 44293 44294 44295 44296 44297 44298 44299 44300 44301 44302 44303 44304 44305 44306 44307 44308 44309 44310 44311 44312 44313 44314 44315 44316 44317 44318 44319 44320 44321 44322 44323 44324 44325 44326 44327 44328 44329 44330 44331 44332 44333 44334 44335 44336 44337 44338 44339 44340 44341 44342 44343 44344 44345 44346 44347 44348 44349 44350 44351 44352 44353 44354 44355 44356 44357 44358 44359 44360 44361 44362 44363 44364 44365 44366 44367 44368 44369 44370 44371 44372 44373 44374 44375 44376 44377 44378 44379 44380 44381 44382 44383 44384 44385 44386 44387 44388 44389 44390 44391 44392 44393 44394 44395 44396 44397 44398 44399 44400 44401 44402 44403 44404 44405 44406 44407 44408 44409 44410 44411 44412 44413 44414 44415 44416 44417 44418 44419 44420 44421 44422 44423 44424 44425 44426 44427 44428 44429 44430 44431 44432 44433 44434 44435 44436 44437 44438 44439 44440 44441 44442 44443 44444 44445 44446 44447 44448 44449 44450 44451 44452 44453 44454 44455 44456 44457 44458 44459 44460 44461 44462 44463 44464 44465 44466 44467 44468 44469 44470 44471 44472 44473 44474 44475 44476 44477 44478 44479 44480 44481 44482 44483 44484 44485 44486 44487 44488 44489 44490 44491 44492 44493 44494 44495 44496 44497 44498 44499 44500 44501 44502 44503 44504 44505 44506 44507 44508 44509 44510 44511 44512 44513 44514 44515 44516 44517 44518 44519 44520 44521 44522 44523 44524 44525 44526 44527 44528 44529 44530 44531 44532 44533 44534 44535 44536 44537 44538 44539 44540 44541 44542 44543 44544 44545 44546 44547 44548 44549 44550 44551 44552 44553 44554 44555 44556 44557 44558 44559 44560 44561 44562 44563 44564 44565 44566 44567 44568 44569 44570 44571 44572 44573 44574 44575 44576 44577 44578 44579 44580 44581 44582 44583 44584 44585 44586 44587 44588 44589 44590 44591 44592 44593 44594 44595 44596 44597 44598 44599 44600 44601 44602 44603 44604 44605 44606 44607 44608 44609 44610 44611 44612 44613 44614 44615 44616 44617 44618 44619 44620 44621 44622 44623 44624 44625 44626 44627 44628 44629 44630 44631 44632 44633 44634 44635 44636 44637 44638 44639 44640 44641 44642 44643 44644 44645 44646 44647 44648 44649 44650 44651 44652 44653 44654 44655 44656 44657 44658 44659 44660 44661 44662 44663 44664 44665 44666 44667 44668 44669 44670 44671 44672 44673 44674 44675 44676 44677 44678 44679 44680 44681 44682 44683 44684 44685 44686 44687 44688 44689 44690 44691 44692 44693 44694 44695 44696 44697 44698 44699 44700 44701 44702 44703 44704 44705 44706 44707 44708 44709 44710 44711 44712 44713 44714 44715 44716 44717 44718 44719 44720 44721 44722 44723 44724 44725 44726 44727 44728 44729 44730 44731 44732 44733 44734 44735 44736 44737 44738 44739 44740 44741 44742 44743 44744 44745 44746 44747 44748 44749 44750 44751 44752 44753 44754 44755 44756 44757 44758 44759 44760 44761 44762 44763 44764 44765 44766 44767 44768 44769 44770 44771 44772 44773 44774 44775 44776 44777 44778 44779 44780 44781 44782 44783 44784 44785 44786 44787 44788 44789 44790 44791 44792 44793 44794 44795 44796 44797 44798 44799 44800 44801 44802 44803 44804 44805 44806 44807 44808 44809 44810 44811 44812 44813 44814 44815 44816 44817 44818 44819 44820 44821 44822 44823 44824 44825 44826 44827 44828 44829 44830 44831 44832 44833 44834 44835 44836 44837 44838 44839 44840 44841 44842 44843 44844 44845 44846 44847 44848 44849 44850 44851 44852 44853 44854 44855 44856 44857 44858 44859 44860 44861 44862 44863 44864 44865 44866 44867 44868 44869 44870 44871 44872 44873 44874 44875 44876 44877 44878 44879 44880 44881 44882 44883 44884 44885 44886 44887 44888 44889 44890 44891 44892 44893 44894 44895 44896 44897 44898 44899 44900 44901 44902 44903 44904 44905 44906 44907 44908 44909 44910 44911 44912 44913 44914 44915 44916 44917 44918 44919 44920 44921 44922 44923 44924 44925 44926 44927 44928 44929 44930 44931 44932 44933 44934 44935 44936 44937 44938 44939 44940 44941 44942 44943 44944 44945 44946 44947 44948 44949 44950 44951 44952 44953 44954 44955 44956 44957 44958 44959 44960 44961 44962 44963 44964 44965 44966 44967 44968 44969 44970 44971 44972 44973 44974 44975 44976 44977 44978 44979 44980 44981 44982 44983 44984 44985 44986 44987 44988 44989 44990 44991 44992 44993 44994 44995 44996 44997 44998 44999 45000 45001 45002 45003 45004 45005 45006 45007 45008 45009 45010 45011 45012 45013 45014 45015 45016 45017 45018 45019 45020 45021 45022 45023 45024 45025 45026 45027 45028 45029 45030 45031 45032 45033 45034 45035 45036 45037 45038 45039 45040 45041 45042 45043 45044 45045 45046 45047 45048 45049 45050 45051 45052 45053 45054 45055 45056 45057 45058 45059 45060 45061 45062 45063 45064 45065 45066 45067 45068 45069 45070 45071 45072 45073 45074 45075 45076 45077 45078 45079 45080 45081 45082 45083 45084 45085 45086 45087 45088 45089 45090 45091 45092 45093 45094 45095 45096 45097 45098 45099 45100 45101 45102 45103 45104 45105 45106 45107 45108 45109 45110 45111 45112 45113 45114 45115 45116 45117 45118 45119 45120 45121 45122 45123 45124 45125 45126 45127 45128 45129 45130 45131 45132 45133 45134 45135 45136 45137 45138 45139 45140 45141 45142 45143 45144 45145 45146 45147 45148 45149 45150 45151 45152 45153 45154 45155 45156 45157 45158 45159 45160 45161 45162 45163 45164 45165 45166 45167 45168 45169 45170 45171 45172 45173 45174 45175 45176 45177 45178 45179 45180 45181 45182 45183 45184 45185 45186 45187 45188 45189 45190 45191 45192 45193 45194 45195 45196 45197 45198 45199 45200 45201 45202 45203 45204 45205 45206 45207 45208 45209 45210 45211 45212 45213 45214 45215 45216 45217 45218 45219 45220 45221 45222 45223 45224 45225 45226 45227 45228 45229 45230 45231 45232 45233 45234 45235 45236 45237 45238 45239 45240 45241 45242 45243 45244 45245 45246 45247 45248 45249 45250 45251 45252 45253 45254 45255 45256 45257 45258 45259 45260 45261 45262 45263 45264 45265 45266 45267 45268 45269 45270 45271 45272 45273 45274 45275 45276 45277 45278 45279 45280 45281 45282 45283 45284 45285 45286 45287 45288 45289 45290 45291 45292 45293 45294 45295 45296 45297 45298 45299 45300 45301 45302 45303 45304 45305 45306 45307 45308 45309 45310 45311 45312 45313 45314 45315 45316 45317 45318 45319 45320 45321 45322 45323 45324 45325 45326 45327 45328 45329 45330 45331 45332 45333 45334 45335 45336 45337 45338 45339 45340 45341 45342 45343 45344 45345 45346 45347 45348 45349 45350 45351 45352 45353 45354 45355 45356 45357 45358 45359 45360 45361 45362 45363 45364 45365 45366 45367 45368 45369 45370 45371 45372 45373 45374 45375 45376 45377 45378 45379 45380 45381 45382 45383 45384 45385 45386 45387 45388 45389 45390 45391 45392 45393 45394 45395 45396 45397 45398 45399 45400 45401 45402 45403 45404 45405 45406 45407 45408 45409 45410 45411 45412 45413 45414 45415 45416 45417 45418 45419 45420 45421 45422 45423 45424 45425 45426 45427 45428 45429 45430 45431 45432 45433 45434 45435 45436 45437 45438 45439 45440 45441 45442 45443 45444 45445 45446 45447 45448 45449 45450 45451 45452 45453 45454 45455 45456 45457 45458 45459 45460 45461 45462 45463 45464 45465 45466 45467 45468 45469 45470 45471 45472 45473 45474 45475 45476 45477 45478 45479 45480 45481 45482 45483 45484 45485 45486 45487 45488 45489 45490 45491 45492 45493 45494 45495 45496 45497 45498 45499 45500 45501 45502 45503 45504 45505 45506 45507 45508 45509 45510 45511 45512 45513 45514 45515 45516 45517 45518 45519 45520 45521 45522 45523 45524 45525 45526 45527 45528 45529 45530 45531 45532 45533 45534 45535 45536 45537 45538 45539 45540 45541 45542 45543 45544 45545 45546 45547 45548 45549 45550 45551 45552 45553 45554 45555 45556 45557 45558 45559 45560 45561 45562 45563 45564 45565 45566 45567 45568 45569 45570 45571 45572 45573 45574 45575 45576 45577 45578 45579 45580 45581 45582 45583 45584 45585 45586 45587 45588 45589 45590 45591 45592 45593 45594 45595 45596 45597 45598 45599 45600 45601 45602 45603 45604 45605 45606 45607 45608 45609 45610 45611 45612 45613 45614 45615 45616 45617 45618 45619 45620 45621 45622 45623 45624 45625 45626 45627 45628 45629 45630 45631 45632 45633 45634 45635 45636 45637 45638 45639 45640 45641 45642 45643 45644 45645 45646 45647 45648 45649 45650 45651 45652 45653 45654 45655 45656 45657 45658 45659 45660 45661 45662 45663 45664 45665 45666 45667 45668 45669 45670 45671 45672 45673 45674 45675 45676 45677 45678 45679 45680 45681 45682 45683 45684 45685 45686 45687 45688 45689 45690 45691 45692 45693 45694 45695 45696 45697 45698 45699 45700 45701 45702 45703 45704 45705 45706 45707 45708 45709 45710 45711 45712 45713 45714 45715 45716 45717 45718 45719 45720 45721 45722 45723 45724 45725 45726 45727 45728 45729 45730 45731 45732 45733 45734 45735 45736 45737 45738 45739 45740 45741 45742 45743 45744 45745 45746 45747 45748 45749 45750 45751 45752 45753 45754 45755 45756 45757 45758 45759 45760 45761 45762 45763 45764 45765 45766 45767 45768 45769 45770 45771 45772 45773 45774 45775 45776 45777 45778 45779 45780 45781 45782 45783 45784 45785 45786 45787 45788 45789 45790 45791 45792 45793 45794 45795 45796 45797 45798 45799 45800 45801 45802 45803 45804 45805 45806 45807 45808 45809 45810 45811 45812 45813 45814 45815 45816 45817 45818 45819 45820 45821 45822 45823 45824 45825 45826 45827 45828 45829 45830 45831 45832 45833 45834 45835 45836 45837 45838 45839 45840 45841 45842 45843 45844 45845 45846 45847 45848 45849 45850 45851 45852 45853 45854 45855 45856 45857 45858 45859 45860 45861 45862 45863 45864 45865 45866 45867 45868 45869 45870 45871 45872 45873 45874 45875 45876 45877 45878 45879 45880 45881 45882 45883 45884 45885 45886 45887 45888 45889 45890 45891 45892 45893 45894 45895 45896 45897 45898 45899 45900 45901 45902 45903 45904 45905 45906 45907 45908 45909 45910 45911 45912 45913 45914 45915 45916 45917 45918 45919 45920 45921 45922 45923 45924 45925 45926 45927 45928 45929 45930 45931 45932 45933 45934 45935 45936 45937 45938 45939 45940 45941 45942 45943 45944 45945 45946 45947 45948 45949 45950 45951 45952 45953 45954 45955 45956 45957 45958 45959 45960 45961 45962 45963 45964 45965 45966 45967 45968 45969 45970 45971 45972 45973 45974 45975 45976 45977 45978 45979 45980 45981 45982 45983 45984 45985 45986 45987 45988 45989 45990 45991 45992 45993 45994 45995 45996 45997 45998 45999 46000 46001 46002 46003 46004 46005 46006 46007 46008 46009 46010 46011 46012 46013 46014 46015 46016 46017 46018 46019 46020 46021 46022 46023 46024 46025 46026 46027 46028 46029 46030 46031 46032 46033 46034 46035 46036 46037 46038 46039 46040 46041 46042 46043 46044 46045 46046 46047 46048 46049 46050 46051 46052 46053 46054 46055 46056 46057 46058 46059 46060 46061 46062 46063 46064 46065 46066 46067 46068 46069 46070 46071 46072 46073 46074 46075 46076 46077 46078 46079 46080 46081 46082 46083 46084 46085 46086 46087 46088 46089 46090 46091 46092 46093 46094 46095 46096 46097 46098 46099 46100 46101 46102 46103 46104 46105 46106 46107 46108 46109 46110 46111 46112 46113 46114 46115 46116 46117 46118 46119 46120 46121 46122 46123 46124 46125 46126 46127 46128 46129 46130 46131 46132 46133 46134 46135 46136 46137 46138 46139 46140 46141 46142 46143 46144 46145 46146 46147 46148 46149 46150 46151 46152 46153 46154 46155 46156 46157 46158 46159 46160 46161 46162 46163 46164 46165 46166 46167 46168 46169 46170 46171 46172 46173 46174 46175 46176 46177 46178 46179 46180 46181 46182 46183 46184 46185 46186 46187 46188 46189 46190 46191 46192 46193 46194 46195 46196 46197 46198 46199 46200 46201 46202 46203 46204 46205 46206 46207 46208 46209 46210 46211 46212 46213 46214 46215 46216 46217 46218 46219 46220 46221 46222 46223 46224 46225 46226 46227 46228 46229 46230 46231 46232 46233 46234 46235 46236 46237 46238 46239 46240 46241 46242 46243 46244 46245 46246 46247 46248 46249 46250 46251 46252 46253 46254 46255 46256 46257 46258 46259 46260 46261 46262 46263 46264 46265 46266 46267 46268 46269 46270 46271 46272 46273 46274 46275 46276 46277 46278 46279 46280 46281 46282 46283 46284 46285 46286 46287 46288 46289 46290 46291 46292 46293 46294 46295 46296 46297 46298 46299 46300 46301 46302 46303 46304 46305 46306 46307 46308 46309 46310 46311 46312 46313 46314 46315 46316 46317 46318 46319 46320 46321 46322 46323 46324 46325 46326 46327 46328 46329 46330 46331 46332 46333 46334 46335 46336 46337 46338 46339 46340 46341 46342 46343 46344 46345 46346 46347 46348 46349 46350 46351 46352 46353 46354 46355 46356 46357 46358 46359 46360 46361 46362 46363 46364 46365 46366 46367 46368 46369 46370 46371 46372 46373 46374 46375 46376 46377 46378 46379 46380 46381 46382 46383 46384 46385 46386 46387 46388 46389 46390 46391 46392 46393 46394 46395 46396 46397 46398 46399 46400 46401 46402 46403 46404 46405 46406 46407 46408 46409 46410 46411 46412 46413 46414 46415 46416 46417 46418 46419 46420 46421 46422 46423 46424 46425 46426 46427 46428 46429 46430 46431 46432 46433 46434 46435 46436 46437 46438 46439 46440 46441 46442 46443 46444 46445 46446 46447 46448 46449 46450 46451 46452 46453 46454 46455 46456 46457 46458 46459 46460 46461 46462 46463 46464 46465 46466 46467 46468 46469 46470 46471 46472 46473 46474 46475 46476 46477 46478 46479 46480 46481 46482 46483 46484 46485 46486 46487 46488 46489 46490 46491 46492 46493 46494 46495 46496 46497 46498 46499 46500 46501 46502 46503 46504 46505 46506 46507 46508 46509 46510 46511 46512 46513 46514 46515 46516 46517 46518 46519 46520 46521 46522 46523 46524 46525 46526 46527 46528 46529 46530 46531 46532 46533 46534 46535 46536 46537 46538 46539 46540 46541 46542 46543 46544 46545 46546 46547 46548 46549 46550 46551 46552 46553 46554 46555 46556 46557 46558 46559 46560 46561 46562 46563 46564 46565 46566 46567 46568 46569 46570 46571 46572 46573 46574 46575 46576 46577 46578 46579 46580 46581 46582 46583 46584 46585 46586 46587 46588 46589 46590 46591 46592 46593 46594 46595 46596 46597 46598 46599 46600 46601 46602 46603 46604 46605 46606 46607 46608 46609 46610 46611 46612 46613 46614 46615 46616 46617 46618 46619 46620 46621 46622 46623 46624 46625 46626 46627 46628 46629 46630 46631 46632 46633 46634 46635 46636 46637 46638 46639 46640 46641 46642 46643 46644 46645 46646 46647 46648 46649 46650 46651 46652 46653 46654 46655 46656 46657 46658 46659 46660 46661 46662 46663 46664 46665 46666 46667 46668 46669 46670 46671 46672 46673 46674 46675 46676 46677 46678 46679 46680 46681 46682 46683 46684 46685 46686 46687 46688 46689 46690 46691 46692 46693 46694 46695 46696 46697 46698 46699 46700 46701 46702 46703 46704 46705 46706 46707 46708 46709 46710 46711 46712 46713 46714 46715 46716 46717 46718 46719 46720 46721 46722 46723 46724 46725 46726 46727 46728 46729 46730 46731 46732 46733 46734 46735 46736 46737 46738 46739 46740 46741 46742 46743 46744 46745 46746 46747 46748 46749 46750 46751 46752 46753 46754 46755 46756 46757 46758 46759 46760 46761 46762 46763 46764 46765 46766 46767 46768 46769 46770 46771 46772 46773 46774 46775 46776 46777 46778 46779 46780 46781 46782 46783 46784 46785 46786 46787 46788 46789 46790 46791 46792 46793 46794 46795 46796 46797 46798 46799 46800 46801 46802 46803 46804 46805 46806 46807 46808 46809 46810 46811 46812 46813 46814 46815 46816 46817 46818 46819 46820 46821 46822 46823 46824 46825 46826 46827 46828 46829 46830 46831 46832 46833 46834 46835 46836 46837 46838 46839 46840 46841 46842 46843 46844 46845 46846 46847 46848 46849 46850 46851 46852 46853 46854 46855 46856 46857 46858 46859 46860 46861 46862 46863 46864 46865 46866 46867 46868 46869 46870 46871 46872 46873 46874 46875 46876 46877 46878 46879 46880 46881 46882 46883 46884 46885 46886 46887 46888 46889 46890 46891 46892 46893 46894 46895 46896 46897 46898 46899 46900 46901 46902 46903 46904 46905 46906 46907 46908 46909 46910 46911 46912 46913 46914 46915 46916 46917 46918 46919 46920 46921 46922 46923 46924 46925 46926 46927 46928 46929 46930 46931 46932 46933 46934 46935 46936 46937 46938 46939 46940 46941 46942 46943 46944 46945 46946 46947 46948 46949 46950 46951 46952 46953 46954 46955 46956 46957 46958 46959 46960 46961 46962 46963 46964 46965 46966 46967 46968 46969 46970 46971 46972 46973 46974 46975 46976 46977 46978 46979 46980 46981 46982 46983 46984 46985 46986 46987 46988 46989 46990 46991 46992 46993 46994 46995 46996 46997 46998 46999 47000 47001 47002 47003 47004 47005 47006 47007 47008 47009 47010 47011 47012 47013 47014 47015 47016 47017 47018 47019 47020 47021 47022 47023 47024 47025 47026 47027 47028 47029 47030 47031 47032 47033 47034 47035 47036 47037 47038 47039 47040 47041 47042 47043 47044 47045 47046 47047 47048 47049 47050 47051 47052 47053 47054 47055 47056 47057 47058 47059 47060 47061 47062 47063 47064 47065 47066 47067 47068 47069 47070 47071 47072 47073 47074 47075 47076 47077 47078 47079 47080 47081 47082 47083 47084 47085 47086 47087 47088 47089 47090 47091 47092 47093 47094 47095 47096 47097 47098 47099 47100 47101 47102 47103 47104 47105 47106 47107 47108 47109 47110 47111 47112 47113 47114 47115 47116 47117 47118 47119 47120 47121 47122 47123 47124 47125 47126 47127 47128 47129 47130 47131 47132 47133 47134 47135 47136 47137 47138 47139 47140 47141 47142 47143 47144 47145 47146 47147 47148 47149 47150 47151 47152 47153 47154 47155 47156 47157 47158 47159 47160 47161 47162 47163 47164 47165 47166 47167 47168 47169 47170 47171 47172 47173 47174 47175 47176 47177 47178 47179 47180 47181 47182 47183 47184 47185 47186 47187 47188 47189 47190 47191 47192 47193 47194 47195 47196 47197 47198 47199 47200 47201 47202 47203 47204 47205 47206 47207 47208 47209 47210 47211 47212 47213 47214 47215 47216 47217 47218 47219 47220 47221 47222 47223 47224 47225 47226 47227 47228 47229 47230 47231 47232 47233 47234 47235 47236 47237 47238 47239 47240 47241 47242 47243 47244 47245 47246 47247 47248 47249 47250 47251 47252 47253 47254 47255 47256 47257 47258 47259 47260 47261 47262 47263 47264 47265 47266 47267 47268 47269 47270 47271 47272 47273 47274 47275 47276 47277 47278 47279 47280 47281 47282 47283 47284 47285 47286 47287 47288 47289 47290 47291 47292 47293 47294 47295 47296 47297 47298 47299 47300 47301 47302 47303 47304 47305 47306 47307 47308 47309 47310 47311 47312 47313 47314 47315 47316 47317 47318 47319 47320 47321 47322 47323 47324 47325 47326 47327 47328 47329 47330 47331 47332 47333 47334 47335 47336 47337 47338 47339 47340 47341 47342 47343 47344 47345 47346 47347 47348 47349 47350 47351 47352 47353 47354 47355 47356 47357 47358 47359 47360 47361 47362 47363 47364 47365 47366 47367 47368 47369 47370 47371 47372 47373 47374 47375 47376 47377 47378 47379 47380 47381 47382 47383 47384 47385 47386 47387 47388 47389 47390 47391 47392 47393 47394 47395 47396 47397 47398 47399 47400 47401 47402 47403 47404 47405 47406 47407 47408 47409 47410 47411 47412 47413 47414 47415 47416 47417 47418 47419 47420 47421 47422 47423 47424 47425 47426 47427 47428 47429 47430 47431 47432 47433 47434 47435 47436 47437 47438 47439 47440 47441 47442 47443 47444 47445 47446 47447 47448 47449 47450 47451 47452 47453 47454 47455 47456 47457 47458 47459 47460 47461 47462 47463 47464 47465 47466 47467 47468 47469 47470 47471 47472 47473 47474 47475 47476 47477 47478 47479 47480 47481 47482 47483 47484 47485 47486 47487 47488 47489 47490 47491 47492 47493 47494 47495 47496 47497 47498 47499 47500 47501 47502 47503 47504 47505 47506 47507 47508 47509 47510 47511 47512 47513 47514 47515 47516 47517 47518 47519 47520 47521 47522 47523 47524 47525 47526 47527 47528 47529 47530 47531 47532 47533 47534 47535 47536 47537 47538 47539 47540 47541 47542 47543 47544 47545 47546 47547 47548 47549 47550 47551 47552 47553 47554 47555 47556 47557 47558 47559 47560 47561 47562 47563 47564 47565 47566 47567 47568 47569 47570 47571 47572 47573 47574 47575 47576 47577 47578 47579 47580 47581 47582 47583 47584 47585 47586 47587 47588 47589 47590 47591 47592 47593 47594 47595 47596 47597 47598 47599 47600 47601 47602 47603 47604 47605 47606 47607 47608 47609 47610 47611 47612 47613 47614 47615 47616 47617 47618 47619 47620 47621 47622 47623 47624 47625 47626 47627 47628 47629 47630 47631 47632 47633 47634 47635 47636 47637 47638 47639 47640 47641 47642 47643 47644 47645 47646 47647 47648 47649 47650 47651 47652 47653 47654 47655 47656 47657 47658 47659 47660 47661 47662 47663 47664 47665 47666 47667 47668 47669 47670 47671 47672 47673 47674 47675 47676 47677 47678 47679 47680 47681 47682 47683 47684 47685 47686 47687 47688 47689 47690 47691 47692 47693 47694 47695 47696 47697 47698 47699 47700 47701 47702 47703 47704 47705 47706 47707 47708 47709 47710 47711 47712 47713 47714 47715 47716 47717 47718 47719 47720 47721 47722 47723 47724 47725 47726 47727 47728 47729 47730 47731 47732 47733 47734 47735 47736 47737 47738 47739 47740 47741 47742 47743 47744 47745 47746 47747 47748 47749 47750 47751 47752 47753 47754 47755 47756 47757 47758 47759 47760 47761 47762 47763 47764 47765 47766 47767 47768 47769 47770 47771 47772 47773 47774 47775 47776 47777 47778 47779 47780 47781 47782 47783 47784 47785 47786 47787 47788 47789 47790 47791 47792 47793 47794 47795 47796 47797 47798 47799 47800 47801 47802 47803 47804 47805 47806 47807 47808 47809 47810 47811 47812 47813 47814 47815 47816 47817 47818 47819 47820 47821 47822 47823 47824 47825 47826 47827 47828 47829 47830 47831 47832 47833 47834 47835 47836 47837 47838 47839 47840 47841 47842 47843 47844 47845 47846 47847 47848 47849 47850 47851 47852 47853 47854 47855 47856 47857 47858 47859 47860 47861 47862 47863 47864 47865 47866 47867 47868 47869 47870 47871 47872 47873 47874 47875 47876 47877 47878 47879 47880 47881 47882 47883 47884 47885 47886 47887 47888 47889 47890 47891 47892 47893 47894 47895 47896 47897 47898 47899 47900 47901 47902 47903 47904 47905 47906 47907 47908 47909 47910 47911 47912 47913 47914 47915 47916 47917 47918 47919 47920 47921 47922 47923 47924 47925 47926 47927 47928 47929 47930 47931 47932 47933 47934 47935 47936 47937 47938 47939 47940 47941 47942 47943 47944 47945 47946 47947 47948 47949 47950 47951 47952 47953 47954 47955 47956 47957 47958 47959 47960 47961 47962 47963 47964 47965 47966 47967 47968 47969 47970 47971 47972 47973 47974 47975 47976 47977 47978 47979 47980 47981 47982 47983 47984 47985 47986 47987 47988 47989 47990 47991 47992 47993 47994 47995 47996 47997 47998 47999 48000 48001 48002 48003 48004 48005 48006 48007 48008 48009 48010 48011 48012 48013 48014 48015 48016 48017 48018 48019 48020 48021 48022 48023 48024 48025 48026 48027 48028 48029 48030 48031 48032 48033 48034 48035 48036 48037 48038 48039 48040 48041 48042 48043 48044 48045 48046 48047 48048 48049 48050 48051 48052 48053 48054 48055 48056 48057 48058 48059 48060 48061 48062 48063 48064 48065 48066 48067 48068 48069 48070 48071 48072 48073 48074 48075 48076 48077 48078 48079 48080 48081 48082 48083 48084 48085 48086 48087 48088 48089 48090 48091 48092 48093 48094 48095 48096 48097 48098 48099 48100 48101 48102 48103 48104 48105 48106 48107 48108 48109 48110 48111 48112 48113 48114 48115 48116 48117 48118 48119 48120 48121 48122 48123 48124 48125 48126 48127 48128 48129 48130 48131 48132 48133 48134 48135 48136 48137 48138 48139 48140 48141 48142 48143 48144 48145 48146 48147 48148 48149 48150 48151 48152 48153 48154 48155 48156 48157 48158 48159 48160 48161 48162 48163 48164 48165 48166 48167 48168 48169 48170 48171 48172 48173 48174 48175 48176 48177 48178 48179 48180 48181 48182 48183 48184 48185 48186 48187 48188 48189 48190 48191 48192 48193 48194 48195 48196 48197 48198 48199 48200 48201 48202 48203 48204 48205 48206 48207 48208 48209 48210 48211 48212 48213 48214 48215 48216 48217 48218 48219 48220 48221 48222 48223 48224 48225 48226 48227 48228 48229 48230 48231 48232 48233 48234 48235 48236 48237 48238 48239 48240 48241 48242 48243 48244 48245 48246 48247 48248 48249 48250 48251 48252 48253 48254 48255 48256 48257 48258 48259 48260 48261 48262 48263 48264 48265 48266 48267 48268 48269 48270 48271 48272 48273 48274 48275 48276 48277 48278 48279 48280 48281 48282 48283 48284 48285 48286 48287 48288 48289 48290 48291 48292 48293 48294 48295 48296 48297 48298 48299 48300 48301 48302 48303 48304 48305 48306 48307 48308 48309 48310 48311 48312 48313 48314 48315 48316 48317 48318 48319 48320 48321 48322 48323 48324 48325 48326 48327 48328 48329 48330 48331 48332 48333 48334 48335 48336 48337 48338 48339 48340 48341 48342 48343 48344 48345 48346 48347 48348 48349 48350 48351 48352 48353 48354 48355 48356 48357 48358 48359 48360 48361 48362 48363 48364 48365 48366 48367 48368 48369 48370 48371 48372 48373 48374 48375 48376 48377 48378 48379 48380 48381 48382 48383 48384 48385 48386 48387 48388 48389 48390 48391 48392 48393 48394 48395 48396 48397 48398 48399 48400 48401 48402 48403 48404 48405 48406 48407 48408 48409 48410 48411 48412 48413 48414 48415 48416 48417 48418 48419 48420 48421 48422 48423 48424 48425 48426 48427 48428 48429 48430 48431 48432 48433 48434 48435 48436 48437 48438 48439 48440 48441 48442 48443 48444 48445 48446 48447 48448 48449 48450 48451 48452 48453 48454 48455 48456 48457 48458 48459 48460 48461 48462 48463 48464 48465 48466 48467 48468 48469 48470 48471 48472 48473 48474 48475 48476 48477 48478 48479 48480 48481 48482 48483 48484 48485 48486 48487 48488 48489 48490 48491 48492 48493 48494 48495 48496 48497 48498 48499 48500 48501 48502 48503 48504 48505 48506 48507 48508 48509 48510 48511 48512 48513 48514 48515 48516 48517 48518 48519 48520 48521 48522 48523 48524 48525 48526 48527 48528 48529 48530 48531 48532 48533 48534 48535 48536 48537 48538 48539 48540 48541 48542 48543 48544 48545 48546 48547 48548 48549 48550 48551 48552 48553 48554 48555 48556 48557 48558 48559 48560 48561 48562 48563 48564 48565 48566 48567 48568 48569 48570 48571 48572 48573 48574 48575 48576 48577 48578 48579 48580 48581 48582 48583 48584 48585 48586 48587 48588 48589 48590 48591 48592 48593 48594 48595 48596 48597 48598 48599 48600 48601 48602 48603 48604 48605 48606 48607 48608 48609 48610 48611 48612 48613 48614 48615 48616 48617 48618 48619 48620 48621 48622 48623 48624 48625 48626 48627 48628 48629 48630 48631 48632 48633 48634 48635 48636 48637 48638 48639 48640 48641 48642 48643 48644 48645 48646 48647 48648 48649 48650 48651 48652 48653 48654 48655 48656 48657 48658 48659 48660 48661 48662 48663 48664 48665 48666 48667 48668 48669 48670 48671 48672 48673 48674 48675 48676 48677 48678 48679 48680 48681 48682 48683 48684 48685 48686 48687 48688 48689 48690 48691 48692 48693 48694 48695 48696 48697 48698 48699 48700 48701 48702 48703 48704 48705 48706 48707 48708 48709 48710 48711 48712 48713 48714 48715 48716 48717 48718 48719 48720 48721 48722 48723 48724 48725 48726 48727 48728 48729 48730 48731 48732 48733 48734 48735 48736 48737 48738 48739 48740 48741 48742 48743 48744 48745 48746 48747 48748 48749 48750 48751 48752 48753 48754 48755 48756 48757 48758 48759 48760 48761 48762 48763 48764 48765 48766 48767 48768 48769 48770 48771 48772 48773 48774 48775 48776 48777 48778 48779 48780 48781 48782 48783 48784 48785 48786 48787 48788 48789 48790 48791 48792 48793 48794 48795 48796 48797 48798 48799 48800 48801 48802 48803 48804 48805 48806 48807 48808 48809 48810 48811 48812 48813 48814 48815 48816 48817 48818 48819 48820 48821 48822 48823 48824 48825 48826 48827 48828 48829 48830 48831 48832 48833 48834 48835 48836 48837 48838 48839 48840 48841 48842 48843 48844 48845 48846 48847 48848 48849 48850 48851 48852 48853 48854 48855 48856 48857 48858 48859 48860 48861 48862 48863 48864 48865 48866 48867 48868 48869 48870 48871 48872 48873 48874 48875 48876 48877 48878 48879 48880 48881 48882 48883 48884 48885 48886 48887 48888 48889 48890 48891 48892 48893 48894 48895 48896 48897 48898 48899 48900 48901 48902 48903 48904 48905 48906 48907 48908 48909 48910 48911 48912 48913 48914 48915 48916 48917 48918 48919 48920 48921 48922 48923 48924 48925 48926 48927 48928 48929 48930 48931 48932 48933 48934 48935 48936 48937 48938 48939 48940 48941 48942 48943 48944 48945 48946 48947 48948 48949 48950 48951 48952 48953 48954 48955 48956 48957 48958 48959 48960 48961 48962 48963 48964 48965 48966 48967 48968 48969 48970 48971 48972 48973 48974 48975 48976 48977 48978 48979 48980 48981 48982 48983 48984 48985 48986 48987 48988 48989 48990 48991 48992 48993 48994 48995 48996 48997 48998 48999 49000 49001 49002 49003 49004 49005 49006 49007 49008 49009 49010 49011 49012 49013 49014 49015 49016 49017 49018 49019 49020 49021 49022 49023 49024 49025 49026 49027 49028 49029 49030 49031 49032 49033 49034 49035 49036 49037 49038 49039 49040 49041 49042 49043 49044 49045 49046 49047 49048 49049 49050 49051 49052 49053 49054 49055 49056 49057 49058 49059 49060 49061 49062 49063 49064 49065 49066 49067 49068 49069 49070 49071 49072 49073 49074 49075 49076 49077 49078 49079 49080 49081 49082 49083 49084 49085 49086 49087 49088 49089 49090 49091 49092 49093 49094 49095 49096 49097 49098 49099 49100 49101 49102 49103 49104 49105 49106 49107 49108 49109 49110 49111 49112 49113 49114 49115 49116 49117 49118 49119 49120 49121 49122 49123 49124 49125 49126 49127 49128 49129 49130 49131 49132 49133 49134 49135 49136 49137 49138 49139 49140 49141 49142 49143 49144 49145 49146 49147 49148 49149 49150 49151 49152 49153 49154 49155 49156 49157 49158 49159 49160 49161 49162 49163 49164 49165 49166 49167 49168 49169 49170 49171 49172 49173 49174 49175 49176 49177 49178 49179 49180 49181 49182 49183 49184 49185 49186 49187 49188 49189 49190 49191 49192 49193 49194 49195 49196 49197 49198 49199 49200 49201 49202 49203 49204 49205 49206 49207 49208 49209 49210 49211 49212 49213 49214 49215 49216 49217 49218 49219 49220 49221 49222 49223 49224 49225 49226 49227 49228 49229 49230 49231 49232 49233 49234 49235 49236 49237 49238 49239 49240 49241 49242 49243 49244 49245 49246 49247 49248 49249 49250 49251 49252 49253 49254 49255 49256 49257 49258 49259 49260 49261 49262 49263 49264 49265 49266 49267 49268 49269 49270 49271 49272 49273 49274 49275 49276 49277 49278 49279 49280 49281 49282 49283 49284 49285 49286 49287 49288 49289 49290 49291 49292 49293 49294 49295 49296 49297 49298 49299 49300 49301 49302 49303 49304 49305 49306 49307 49308 49309 49310 49311 49312 49313 49314 49315 49316 49317 49318 49319 49320 49321 49322 49323 49324 49325 49326 49327 49328 49329 49330 49331 49332 49333 49334 49335 49336 49337 49338 49339 49340 49341 49342 49343 49344 49345 49346 49347 49348 49349 49350 49351 49352 49353 49354 49355 49356 49357 49358 49359 49360 49361 49362 49363 49364 49365 49366 49367 49368 49369 49370 49371 49372 49373 49374 49375 49376 49377 49378 49379 49380 49381 49382 49383 49384 49385 49386 49387 49388 49389 49390 49391 49392 49393 49394 49395 49396 49397 49398 49399 49400 49401 49402 49403 49404 49405 49406 49407 49408 49409 49410 49411 49412 49413 49414 49415 49416 49417 49418 49419 49420 49421 49422 49423 49424 49425 49426 49427 49428 49429 49430 49431 49432 49433 49434 49435 49436 49437 49438 49439 49440 49441 49442 49443 49444 49445 49446 49447 49448 49449 49450 49451 49452 49453 49454 49455 49456 49457 49458 49459 49460 49461 49462 49463 49464 49465 49466 49467 49468 49469 49470 49471 49472 49473 49474 49475 49476 49477 49478 49479 49480 49481 49482 49483 49484 49485 49486 49487 49488 49489 49490 49491 49492 49493 49494 49495 49496 49497 49498 49499 49500 49501 49502 49503 49504 49505 49506 49507 49508 49509 49510 49511 49512 49513 49514 49515 49516 49517 49518 49519 49520 49521 49522 49523 49524 49525 49526 49527 49528 49529 49530 49531 49532 49533 49534 49535 49536 49537 49538 49539 49540 49541 49542 49543 49544 49545 49546 49547 49548 49549 49550 49551 49552 49553 49554 49555 49556 49557 49558 49559 49560 49561 49562 49563 49564 49565 49566 49567 49568 49569 49570 49571 49572 49573 49574 49575 49576 49577 49578 49579 49580 49581 49582 49583 49584 49585 49586 49587 49588 49589 49590 49591 49592 49593 49594 49595 49596 49597 49598 49599 49600 49601 49602 49603 49604 49605 49606 49607 49608 49609 49610 49611 49612 49613 49614 49615 49616 49617 49618 49619 49620 49621 49622 49623 49624 49625 49626 49627 49628 49629 49630 49631 49632 49633 49634 49635 49636 49637 49638 49639 49640 49641 49642 49643 49644 49645 49646 49647 49648 49649 49650 49651 49652 49653 49654 49655 49656 49657 49658 49659 49660 49661 49662 49663 49664 49665 49666 49667 49668 49669 49670 49671 49672 49673 49674 49675 49676 49677 49678 49679 49680 49681 49682 49683 49684 49685 49686 49687 49688 49689 49690 49691 49692 49693 49694 49695 49696 49697 49698 49699 49700 49701 49702 49703 49704 49705 49706 49707 49708 49709 49710 49711 49712 49713 49714 49715 49716 49717 49718 49719 49720 49721 49722 49723 49724 49725 49726 49727 49728 49729 49730 49731 49732 49733 49734 49735 49736 49737 49738 49739 49740 49741 49742 49743 49744 49745 49746 49747 49748 49749 49750 49751 49752 49753 49754 49755 49756 49757 49758 49759 49760 49761 49762 49763 49764 49765 49766 49767 49768 49769 49770 49771 49772 49773 49774 49775 49776 49777 49778 49779 49780 49781 49782 49783 49784 49785 49786 49787 49788 49789 49790 49791 49792 49793 49794 49795 49796 49797 49798 49799 49800 49801 49802 49803 49804 49805 49806 49807 49808 49809 49810 49811 49812 49813 49814 49815 49816 49817 49818 49819 49820 49821 49822 49823 49824 49825 49826 49827 49828 49829 49830 49831 49832 49833 49834 49835 49836 49837 49838 49839 49840 49841 49842 49843 49844 49845 49846 49847 49848 49849 49850 49851 49852 49853 49854 49855 49856 49857 49858 49859 49860 49861 49862 49863 49864 49865 49866 49867 49868 49869 49870 49871 49872 49873 49874 49875 49876 49877 49878 49879 49880 49881 49882 49883 49884 49885 49886 49887 49888 49889 49890 49891 49892 49893 49894 49895 49896 49897 49898 49899 49900 49901 49902 49903 49904 49905 49906 49907 49908 49909 49910 49911 49912 49913 49914 49915 49916 49917 49918 49919 49920 49921 49922 49923 49924 49925 49926 49927 49928 49929 49930 49931 49932 49933 49934 49935 49936 49937 49938 49939 49940 49941 49942 49943 49944 49945 49946 49947 49948 49949 49950 49951 49952 49953 49954 49955 49956 49957 49958 49959 49960 49961 49962 49963 49964 49965 49966 49967 49968 49969 49970 49971 49972 49973 49974 49975 49976 49977 49978 49979 49980 49981 49982 49983 49984 49985 49986 49987 49988 49989 49990 49991 49992 49993 49994 49995 49996 49997 49998 49999 50000 50001 50002 50003 50004 50005 50006 50007 50008 50009 50010 50011 50012 50013 50014 50015 50016 50017 50018 50019 50020 50021 50022 50023 50024 50025 50026 50027 50028 50029 50030 50031 50032 50033 50034 50035 50036 50037 50038 50039 50040 50041 50042 50043 50044 50045 50046 50047 50048 50049 50050 50051 50052 50053 50054 50055 50056 50057 50058 50059 50060 50061 50062 50063 50064 50065 50066 50067 50068 50069 50070 50071 50072 50073 50074 50075 50076 50077 50078 50079 50080 50081 50082 50083 50084 50085 50086 50087 50088 50089 50090 50091 50092 50093 50094 50095 50096 50097 50098 50099 50100 50101 50102 50103 50104 50105 50106 50107 50108 50109 50110 50111 50112 50113 50114 50115 50116 50117 50118 50119 50120 50121 50122 50123 50124 50125 50126 50127 50128 50129 50130 50131 50132 50133 50134 50135 50136 50137 50138 50139 50140 50141 50142 50143 50144 50145 50146 50147 50148 50149 50150 50151 50152 50153 50154 50155 50156 50157 50158 50159 50160 50161 50162 50163 50164 50165 50166 50167 50168 50169 50170 50171 50172 50173 50174 50175 50176 50177 50178 50179 50180 50181 50182 50183 50184 50185 50186 50187 50188 50189 50190 50191 50192 50193 50194 50195 50196 50197 50198 50199 50200 50201 50202 50203 50204 50205 50206 50207 50208 50209 50210 50211 50212 50213 50214 50215 50216 50217 50218 50219 50220 50221 50222 50223 50224 50225 50226 50227 50228 50229 50230 50231 50232 50233 50234 50235 50236 50237 50238 50239 50240 50241 50242 50243 50244 50245 50246 50247 50248 50249 50250 50251 50252 50253 50254 50255 50256 50257 50258 50259 50260 50261 50262 50263 50264 50265 50266 50267 50268 50269 50270 50271 50272 50273 50274 50275 50276 50277 50278 50279 50280 50281 50282 50283 50284 50285 50286 50287 50288 50289 50290 50291 50292 50293 50294 50295 50296 50297 50298 50299 50300 50301 50302 50303 50304 50305 50306 50307 50308 50309 50310 50311 50312 50313 50314 50315 50316 50317 50318 50319 50320 50321 50322 50323 50324 50325 50326 50327 50328 50329 50330 50331 50332 50333 50334 50335 50336 50337 50338 50339 50340 50341 50342 50343 50344 50345 50346 50347 50348 50349 50350 50351 50352 50353 50354 50355 50356 50357 50358 50359 50360 50361 50362 50363 50364 50365 50366 50367 50368 50369 50370 50371 50372 50373 50374 50375 50376 50377 50378 50379 50380 50381 50382 50383 50384 50385 50386 50387 50388 50389 50390 50391 50392 50393 50394 50395 50396 50397 50398 50399 50400 50401 50402 50403 50404 50405 50406 50407 50408 50409 50410 50411 50412 50413 50414 50415 50416 50417 50418 50419 50420 50421 50422 50423 50424 50425 50426 50427 50428 50429 50430 50431 50432 50433 50434 50435 50436 50437 50438 50439 50440 50441 50442 50443 50444 50445 50446 50447 50448 50449 50450 50451 50452 50453 50454 50455 50456 50457 50458 50459 50460 50461 50462 50463 50464 50465 50466 50467 50468 50469 50470 50471 50472 50473 50474 50475 50476 50477 50478 50479 50480 50481 50482 50483 50484 50485 50486 50487 50488 50489 50490 50491 50492 50493 50494 50495 50496 50497 50498 50499 50500 50501 50502 50503 50504 50505 50506 50507 50508 50509 50510 50511 50512 50513 50514 50515 50516 50517 50518 50519 50520 50521 50522 50523 50524 50525 50526 50527 50528 50529 50530 50531 50532 50533 50534 50535 50536 50537 50538 50539 50540 50541 50542 50543 50544 50545 50546 50547 50548 50549 50550 50551 50552 50553 50554 50555 50556 50557 50558 50559 50560 50561 50562 50563 50564 50565 50566 50567 50568 50569 50570 50571 50572 50573 50574 50575 50576 50577 50578 50579 50580 50581 50582 50583 50584 50585 50586 50587 50588 50589 50590 50591 50592 50593 50594 50595 50596 50597 50598 50599 50600 50601 50602 50603 50604 50605 50606 50607 50608 50609 50610 50611 50612 50613 50614 50615 50616 50617 50618 50619 50620 50621 50622 50623 50624 50625 50626 50627 50628 50629 50630 50631 50632 50633 50634 50635 50636 50637 50638 50639 50640 50641 50642 50643 50644 50645 50646 50647 50648 50649 50650 50651 50652 50653 50654 50655 50656 50657 50658 50659 50660 50661 50662 50663 50664 50665 50666 50667 50668 50669 50670 50671 50672 50673 50674 50675 50676 50677 50678 50679 50680 50681 50682 50683 50684 50685 50686 50687 50688 50689 50690 50691 50692 50693 50694 50695 50696 50697 50698 50699 50700 50701 50702 50703 50704 50705 50706 50707 50708 50709 50710 50711 50712 50713 50714 50715 50716 50717 50718 50719 50720 50721 50722 50723 50724 50725 50726 50727 50728 50729 50730 50731 50732 50733 50734 50735 50736 50737 50738 50739 50740 50741 50742 50743 50744 50745 50746 50747 50748 50749 50750 50751 50752 50753 50754 50755 50756 50757 50758 50759 50760 50761 50762 50763 50764 50765 50766 50767 50768 50769 50770 50771 50772 50773 50774 50775 50776 50777 50778 50779 50780 50781 50782 50783 50784 50785 50786 50787 50788 50789 50790 50791 50792 50793 50794 50795 50796 50797 50798 50799 50800 50801 50802 50803 50804 50805 50806 50807 50808 50809 50810 50811 50812 50813 50814 50815 50816 50817 50818 50819 50820 50821 50822 50823 50824 50825 50826 50827 50828 50829 50830 50831 50832 50833 50834 50835 50836 50837 50838 50839 50840 50841 50842 50843 50844 50845 50846 50847 50848 50849 50850 50851 50852 50853 50854 50855 50856 50857 50858 50859 50860 50861 50862 50863 50864 50865 50866 50867 50868 50869 50870 50871 50872 50873 50874 50875 50876 50877 50878 50879 50880 50881 50882 50883 50884 50885 50886 50887 50888 50889 50890 50891 50892 50893 50894 50895 50896 50897 50898 50899 50900 50901 50902 50903 50904 50905 50906 50907 50908 50909 50910 50911 50912 50913 50914 50915 50916 50917 50918 50919 50920 50921 50922 50923 50924 50925 50926 50927 50928 50929 50930 50931 50932 50933 50934 50935 50936 50937 50938 50939 50940 50941 50942 50943 50944 50945 50946 50947 50948 50949 50950 50951 50952 50953 50954 50955 50956 50957 50958 50959 50960 50961 50962 50963 50964 50965 50966 50967 50968 50969 50970 50971 50972 50973 50974 50975 50976 50977 50978 50979 50980 50981 50982 50983 50984 50985 50986 50987 50988 50989 50990 50991 50992 50993 50994 50995 50996 50997 50998 50999 51000 51001 51002 51003 51004 51005 51006 51007 51008 51009 51010 51011 51012 51013 51014 51015 51016 51017 51018 51019 51020 51021 51022 51023 51024 51025 51026 51027 51028 51029 51030 51031 51032 51033 51034 51035 51036 51037 51038 51039 51040 51041 51042 51043 51044 51045 51046 51047 51048 51049 51050 51051 51052 51053 51054 51055 51056 51057 51058 51059 51060 51061 51062 51063 51064 51065 51066 51067 51068 51069 51070 51071 51072 51073 51074 51075 51076 51077 51078 51079 51080 51081 51082 51083 51084 51085 51086 51087 51088 51089 51090 51091 51092 51093 51094 51095 51096 51097 51098 51099 51100 51101 51102 51103 51104 51105 51106 51107 51108 51109 51110 51111 51112 51113 51114 51115 51116 51117 51118 51119 51120 51121 51122 51123 51124 51125 51126 51127 51128 51129 51130 51131 51132 51133 51134 51135 51136 51137 51138 51139 51140 51141 51142 51143 51144 51145 51146 51147 51148 51149 51150 51151 51152 51153 51154 51155 51156 51157 51158 51159 51160 51161 51162 51163 51164 51165 51166 51167 51168 51169 51170 51171 51172 51173 51174 51175 51176 51177 51178 51179 51180 51181 51182 51183 51184 51185 51186 51187 51188 51189 51190 51191 51192 51193 51194 51195 51196 51197 51198 51199 51200 51201 51202 51203 51204 51205 51206 51207 51208 51209 51210 51211 51212 51213 51214 51215 51216 51217 51218 51219 51220 51221 51222 51223 51224 51225 51226 51227 51228 51229 51230 51231 51232 51233 51234 51235 51236 51237 51238 51239 51240 51241 51242 51243 51244 51245 51246 51247 51248 51249 51250 51251 51252 51253 51254 51255 51256 51257 51258 51259 51260 51261 51262 51263 51264 51265 51266 51267 51268 51269 51270 51271 51272 51273 51274 51275 51276 51277 51278 51279 51280 51281 51282 51283 51284 51285 51286 51287 51288 51289 51290 51291 51292 51293 51294 51295 51296 51297 51298 51299 51300 51301 51302 51303 51304 51305 51306 51307 51308 51309 51310 51311 51312 51313 51314 51315 51316 51317 51318 51319 51320 51321 51322 51323 51324 51325 51326 51327 51328 51329 51330 51331 51332 51333 51334 51335 51336 51337 51338 51339 51340 51341 51342 51343 51344 51345 51346 51347 51348 51349 51350 51351 51352 51353 51354 51355 51356 51357 51358 51359 51360 51361 51362 51363 51364 51365 51366 51367 51368 51369 51370 51371 51372 51373 51374 51375 51376 51377 51378 51379 51380 51381 51382 51383 51384 51385 51386 51387 51388 51389 51390 51391 51392 51393 51394 51395 51396 51397 51398 51399 51400 51401 51402 51403 51404 51405 51406 51407 51408 51409 51410 51411 51412 51413 51414 51415 51416 51417 51418 51419 51420 51421 51422 51423 51424 51425 51426 51427 51428 51429 51430 51431 51432 51433 51434 51435 51436 51437 51438 51439 51440 51441 51442 51443 51444 51445 51446 51447 51448 51449 51450 51451 51452 51453 51454 51455 51456 51457 51458 51459 51460 51461 51462 51463 51464 51465 51466 51467 51468 51469 51470 51471 51472 51473 51474 51475 51476 51477 51478 51479 51480 51481 51482 51483 51484 51485 51486 51487 51488 51489 51490 51491 51492 51493 51494 51495 51496 51497 51498 51499 51500 51501 51502 51503 51504 51505 51506 51507 51508 51509 51510 51511 51512 51513 51514 51515 51516 51517 51518 51519 51520 51521 51522 51523 51524 51525 51526 51527 51528 51529 51530 51531 51532 51533 51534 51535 51536 51537 51538 51539 51540 51541 51542 51543 51544 51545 51546 51547 51548 51549 51550 51551 51552 51553 51554 51555 51556 51557 51558 51559 51560 51561 51562 51563 51564 51565 51566 51567 51568 51569 51570 51571 51572 51573 51574 51575 51576 51577 51578 51579 51580 51581 51582 51583 51584 51585 51586 51587 51588 51589 51590 51591 51592 51593 51594 51595 51596 51597 51598 51599 51600 51601 51602 51603 51604 51605 51606 51607 51608 51609 51610 51611 51612 51613 51614 51615 51616 51617 51618 51619 51620 51621 51622 51623 51624 51625 51626 51627 51628 51629 51630 51631 51632 51633 51634 51635 51636 51637 51638 51639 51640 51641 51642 51643 51644 51645 51646 51647 51648 51649 51650 51651 51652 51653 51654 51655 51656 51657 51658 51659 51660 51661 51662 51663 51664 51665 51666 51667 51668 51669 51670 51671 51672 51673 51674 51675 51676 51677 51678 51679 51680 51681 51682 51683 51684 51685 51686 51687 51688 51689 51690 51691 51692 51693 51694 51695 51696 51697 51698 51699 51700 51701 51702 51703 51704 51705 51706 51707 51708 51709 51710 51711 51712 51713 51714 51715 51716 51717 51718 51719 51720 51721 51722 51723 51724 51725 51726 51727 51728 51729 51730 51731 51732 51733 51734 51735 51736 51737 51738 51739 51740 51741 51742 51743 51744 51745 51746 51747 51748 51749 51750 51751 51752 51753 51754 51755 51756 51757 51758 51759 51760 51761 51762 51763 51764 51765 51766 51767 51768 51769 51770 51771 51772 51773 51774 51775 51776 51777 51778 51779 51780 51781 51782 51783 51784 51785 51786 51787 51788 51789 51790 51791 51792 51793 51794 51795 51796 51797 51798 51799 51800 51801 51802 51803 51804 51805 51806 51807 51808 51809 51810 51811 51812 51813 51814 51815 51816 51817 51818 51819 51820 51821 51822 51823 51824 51825 51826 51827 51828 51829 51830 51831 51832 51833 51834 51835 51836 51837 51838 51839 51840 51841 51842 51843 51844 51845 51846 51847 51848 51849 51850 51851 51852 51853 51854 51855 51856 51857 51858 51859 51860 51861 51862 51863 51864 51865 51866 51867 51868 51869 51870 51871 51872 51873 51874 51875 51876 51877 51878 51879 51880 51881 51882 51883 51884 51885 51886 51887 51888 51889 51890 51891 51892 51893 51894 51895 51896 51897 51898 51899 51900 51901 51902 51903 51904 51905 51906 51907 51908 51909 51910 51911 51912 51913 51914 51915 51916 51917 51918 51919 51920 51921 51922 51923 51924 51925 51926 51927 51928 51929 51930 51931 51932 51933 51934 51935 51936 51937 51938 51939 51940 51941 51942 51943 51944 51945 51946 51947 51948 51949 51950 51951 51952 51953 51954 51955 51956 51957 51958 51959 51960 51961 51962 51963 51964 51965 51966 51967 51968 51969 51970 51971 51972 51973 51974 51975 51976 51977 51978 51979 51980 51981 51982 51983 51984 51985 51986 51987 51988 51989 51990 51991 51992 51993 51994 51995 51996 51997 51998 51999 52000 52001 52002 52003 52004 52005 52006 52007 52008 52009 52010 52011 52012 52013 52014 52015 52016 52017 52018 52019 52020 52021 52022 52023 52024 52025 52026 52027 52028 52029 52030 52031 52032 52033 52034 52035 52036 52037 52038 52039 52040 52041 52042 52043 52044 52045 52046 52047 52048 52049 52050 52051 52052 52053 52054 52055 52056 52057 52058 52059 52060 52061 52062 52063 52064 52065 52066 52067 52068 52069 52070 52071 52072 52073 52074 52075 52076 52077 52078 52079 52080 52081 52082 52083 52084 52085 52086 52087 52088 52089 52090 52091 52092 52093 52094 52095 52096 52097 52098 52099 52100 52101 52102 52103 52104 52105 52106 52107 52108 52109 52110 52111 52112 52113 52114 52115 52116 52117 52118 52119 52120 52121 52122 52123 52124 52125 52126 52127 52128 52129 52130 52131 52132 52133 52134 52135 52136 52137 52138 52139 52140 52141 52142 52143 52144 52145 52146 52147 52148 52149 52150 52151 52152 52153 52154 52155 52156 52157 52158 52159 52160 52161 52162 52163 52164 52165 52166 52167 52168 52169 52170 52171 52172 52173 52174 52175 52176 52177 52178 52179 52180 52181 52182 52183 52184 52185 52186 52187 52188 52189 52190 52191 52192 52193 52194 52195 52196 52197 52198 52199 52200 52201 52202 52203 52204 52205 52206 52207 52208 52209 52210 52211 52212 52213 52214 52215 52216 52217 52218 52219 52220 52221 52222 52223 52224 52225 52226 52227 52228 52229 52230 52231 52232 52233 52234 52235 52236 52237 52238 52239 52240 52241 52242 52243 52244 52245 52246 52247 52248 52249 52250 52251 52252 52253 52254 52255 52256 52257 52258 52259 52260 52261 52262 52263 52264 52265 52266 52267 52268 52269 52270 52271 52272 52273 52274 52275 52276 52277 52278 52279 52280 52281 52282 52283 52284 52285 52286 52287 52288 52289 52290 52291 52292 52293 52294 52295 52296 52297 52298 52299 52300 52301 52302 52303 52304 52305 52306 52307 52308 52309 52310 52311 52312 52313 52314 52315 52316 52317 52318 52319 52320 52321 52322 52323 52324 52325 52326 52327 52328 52329 52330 52331 52332 52333 52334 52335 52336 52337 52338 52339 52340 52341 52342 52343 52344 52345 52346 52347 52348 52349 52350 52351 52352 52353 52354 52355 52356 52357 52358 52359 52360 52361 52362 52363 52364 52365 52366 52367 52368 52369 52370 52371 52372 52373 52374 52375 52376 52377 52378 52379 52380 52381 52382 52383 52384 52385 52386 52387 52388 52389 52390 52391 52392 52393 52394 52395 52396 52397 52398 52399 52400 52401 52402 52403 52404 52405 52406 52407 52408 52409 52410 52411 52412 52413 52414 52415 52416 52417 52418 52419 52420 52421 52422 52423 52424 52425 52426 52427 52428 52429 52430 52431 52432 52433 52434 52435 52436 52437 52438 52439 52440 52441 52442 52443 52444 52445 52446 52447 52448 52449 52450 52451 52452 52453 52454 52455 52456 52457 52458 52459 52460 52461 52462 52463 52464 52465 52466 52467 52468 52469 52470 52471 52472 52473 52474 52475 52476 52477 52478 52479 52480 52481 52482 52483 52484 52485 52486 52487 52488 52489 52490 52491 52492 52493 52494 52495 52496 52497 52498 52499 52500 52501 52502 52503 52504 52505 52506 52507 52508 52509 52510 52511 52512 52513 52514 52515 52516 52517 52518 52519 52520 52521 52522 52523 52524 52525 52526 52527 52528 52529 52530 52531 52532 52533 52534 52535 52536 52537 52538 52539 52540 52541 52542 52543 52544 52545 52546 52547 52548 52549 52550 52551 52552 52553 52554 52555 52556 52557 52558 52559 52560 52561 52562 52563 52564 52565 52566 52567 52568 52569 52570 52571 52572 52573 52574 52575 52576 52577 52578 52579 52580 52581 52582 52583 52584 52585 52586 52587 52588 52589 52590 52591 52592 52593 52594 52595 52596 52597 52598 52599 52600 52601 52602 52603 52604 52605 52606 52607 52608 52609 52610 52611 52612 52613 52614 52615 52616 52617 52618 52619 52620 52621 52622 52623 52624 52625 52626 52627 52628 52629 52630 52631 52632 52633 52634 52635 52636 52637 52638 52639 52640 52641 52642 52643 52644 52645 52646 52647 52648 52649 52650 52651 52652 52653 52654 52655 52656 52657 52658 52659 52660 52661 52662 52663 52664 52665 52666 52667 52668 52669 52670 52671 52672 52673 52674 52675 52676 52677 52678 52679 52680 52681 52682 52683 52684 52685 52686 52687 52688 52689 52690 52691 52692 52693 52694 52695 52696 52697 52698 52699 52700 52701 52702 52703 52704 52705 52706 52707 52708 52709 52710 52711 52712 52713 52714 52715 52716 52717 52718 52719 52720 52721 52722 52723 52724 52725 52726 52727 52728 52729 52730 52731 52732 52733 52734 52735 52736 52737 52738 52739 52740 52741 52742 52743 52744 52745 52746 52747 52748 52749 52750 52751 52752 52753 52754 52755 52756 52757 52758 52759 52760 52761 52762 52763 52764 52765 52766 52767 52768 52769 52770 52771 52772 52773 52774 52775 52776 52777 52778 52779 52780 52781 52782 52783 52784 52785 52786 52787 52788 52789 52790 52791 52792 52793 52794 52795 52796 52797 52798 52799 52800 52801 52802 52803 52804 52805 52806 52807 52808 52809 52810 52811 52812 52813 52814 52815 52816 52817 52818 52819 52820 52821 52822 52823 52824 52825 52826 52827 52828 52829 52830 52831 52832 52833 52834 52835 52836 52837 52838 52839 52840 52841 52842 52843 52844 52845 52846 52847 52848 52849 52850 52851 52852 52853 52854 52855 52856 52857 52858 52859 52860 52861 52862 52863 52864 52865 52866 52867 52868 52869 52870 52871 52872 52873 52874 52875 52876 52877 52878 52879 52880 52881 52882 52883 52884 52885 52886 52887 52888 52889 52890 52891 52892 52893 52894 52895 52896 52897 52898 52899 52900 52901 52902 52903 52904 52905 52906 52907 52908 52909 52910 52911 52912 52913 52914 52915 52916 52917 52918 52919 52920 52921 52922 52923 52924 52925 52926 52927 52928 52929 52930 52931 52932 52933 52934 52935 52936 52937 52938 52939 52940 52941 52942 52943 52944 52945 52946 52947 52948 52949 52950 52951 52952 52953 52954 52955 52956 52957 52958 52959 52960 52961 52962 52963 52964 52965 52966 52967 52968 52969 52970 52971 52972 52973 52974 52975 52976 52977 52978 52979 52980 52981 52982 52983 52984 52985 52986 52987 52988 52989 52990 52991 52992 52993 52994 52995 52996 52997 52998 52999 53000 53001 53002 53003 53004 53005 53006 53007 53008 53009 53010 53011 53012 53013 53014 53015 53016 53017 53018 53019 53020 53021 53022 53023 53024 53025 53026 53027 53028 53029 53030 53031 53032 53033 53034 53035 53036 53037 53038 53039 53040 53041 53042 53043 53044 53045 53046 53047 53048 53049 53050 53051 53052 53053 53054 53055 53056 53057 53058 53059 53060 53061 53062 53063 53064 53065 53066 53067 53068 53069 53070 53071 53072 53073 53074 53075 53076 53077 53078 53079 53080 53081 53082 53083 53084 53085 53086 53087 53088 53089 53090 53091 53092 53093 53094 53095 53096 53097 53098 53099 53100 53101 53102 53103 53104 53105 53106 53107 53108 53109 53110 53111 53112 53113 53114 53115 53116 53117 53118 53119 53120 53121 53122 53123 53124 53125 53126 53127 53128 53129 53130 53131 53132 53133 53134 53135 53136 53137 53138 53139 53140 53141 53142 53143 53144 53145 53146 53147 53148 53149 53150 53151 53152 53153 53154 53155 53156 53157 53158 53159 53160 53161 53162 53163 53164 53165 53166 53167 53168 53169 53170 53171 53172 53173 53174 53175 53176 53177 53178 53179 53180 53181 53182 53183 53184 53185 53186 53187 53188 53189 53190 53191 53192 53193 53194 53195 53196 53197 53198 53199 53200 53201 53202 53203 53204 53205 53206 53207 53208 53209 53210 53211 53212 53213 53214 53215 53216 53217 53218 53219 53220 53221 53222 53223 53224 53225 53226 53227 53228 53229 53230 53231 53232 53233 53234 53235 53236 53237 53238 53239 53240 53241 53242 53243 53244 53245 53246 53247 53248 53249 53250 53251 53252 53253 53254 53255 53256 53257 53258 53259 53260 53261 53262 53263 53264 53265 53266 53267 53268 53269 53270 53271 53272 53273 53274 53275 53276 53277 53278 53279 53280 53281 53282 53283 53284 53285 53286 53287 53288 53289 53290 53291 53292 53293 53294 53295 53296 53297 53298 53299 53300 53301 53302 53303 53304 53305 53306 53307 53308 53309 53310 53311 53312 53313 53314 53315 53316 53317 53318 53319 53320 53321 53322 53323 53324 53325 53326 53327 53328 53329 53330 53331 53332 53333 53334 53335 53336 53337 53338 53339 53340 53341 53342 53343 53344 53345 53346 53347 53348 53349 53350 53351 53352 53353 53354 53355 53356 53357 53358 53359 53360 53361 53362 53363 53364 53365 53366 53367 53368 53369 53370 53371 53372 53373 53374 53375 53376 53377 53378 53379 53380 53381 53382 53383 53384 53385 53386 53387 53388 53389 53390 53391 53392 53393 53394 53395 53396 53397 53398 53399 53400 53401 53402 53403 53404 53405 53406 53407 53408 53409 53410 53411 53412 53413 53414 53415 53416 53417 53418 53419 53420 53421 53422 53423 53424 53425 53426 53427 53428 53429 53430 53431 53432 53433 53434 53435 53436 53437 53438 53439 53440 53441 53442 53443 53444 53445 53446 53447 53448 53449 53450 53451 53452 53453 53454 53455 53456 53457 53458 53459 53460 53461 53462 53463 53464 53465 53466 53467 53468 53469 53470 53471 53472 53473 53474 53475 53476 53477 53478 53479 53480 53481 53482 53483 53484 53485 53486 53487 53488 53489 53490 53491 53492 53493 53494 53495 53496 53497 53498 53499 53500 53501 53502 53503 53504 53505 53506 53507 53508 53509 53510 53511 53512 53513 53514 53515 53516 53517 53518 53519 53520 53521 53522 53523 53524 53525 53526 53527 53528 53529 53530 53531 53532 53533 53534 53535 53536 53537 53538 53539 53540 53541 53542 53543 53544 53545 53546 53547 53548 53549 53550 53551 53552 53553 53554 53555 53556 53557 53558 53559 53560 53561 53562 53563 53564 53565 53566 53567 53568 53569 53570 53571 53572 53573 53574 53575 53576 53577 53578 53579 53580 53581 53582 53583 53584 53585 53586 53587 53588 53589 53590 53591 53592 53593 53594 53595 53596 53597 53598 53599 53600 53601 53602 53603 53604 53605 53606 53607 53608 53609 53610 53611 53612 53613 53614 53615 53616 53617 53618 53619 53620 53621 53622 53623 53624 53625 53626 53627 53628 53629 53630 53631 53632 53633 53634 53635 53636 53637 53638 53639 53640 53641 53642 53643 53644 53645 53646 53647 53648 53649 53650 53651 53652 53653 53654 53655 53656 53657 53658 53659 53660 53661 53662 53663 53664 53665 53666 53667 53668 53669 53670 53671 53672 53673 53674 53675 53676 53677 53678 53679 53680 53681 53682 53683 53684 53685 53686 53687 53688 53689 53690 53691 53692 53693 53694 53695 53696 53697 53698 53699 53700 53701 53702 53703 53704 53705 53706 53707 53708 53709 53710 53711 53712 53713 53714 53715 53716 53717 53718 53719 53720 53721 53722 53723 53724 53725 53726 53727 53728 53729 53730 53731 53732 53733 53734 53735 53736 53737 53738 53739 53740 53741 53742 53743 53744 53745 53746 53747 53748 53749 53750 53751 53752 53753 53754 53755 53756 53757 53758 53759 53760 53761 53762 53763 53764 53765 53766 53767 53768 53769 53770 53771 53772 53773 53774 53775 53776 53777 53778 53779 53780 53781 53782 53783 53784 53785 53786 53787 53788 53789 53790 53791 53792 53793 53794 53795 53796 53797 53798 53799 53800 53801 53802 53803 53804 53805 53806 53807 53808 53809 53810 53811 53812 53813 53814 53815 53816 53817 53818 53819 53820 53821 53822 53823 53824 53825 53826 53827 53828 53829 53830 53831 53832 53833 53834 53835 53836 53837 53838 53839 53840 53841 53842 53843 53844 53845 53846 53847 53848 53849 53850 53851 53852 53853 53854 53855 53856 53857 53858 53859 53860 53861 53862 53863 53864 53865 53866 53867 53868 53869 53870 53871 53872 53873 53874 53875 53876 53877 53878 53879 53880 53881 53882 53883 53884 53885 53886 53887 53888 53889 53890 53891 53892 53893 53894 53895 53896 53897 53898 53899 53900 53901 53902 53903 53904 53905 53906 53907 53908 53909 53910 53911 53912 53913 53914 53915 53916 53917 53918 53919 53920 53921 53922 53923 53924 53925 53926 53927 53928 53929 53930 53931 53932 53933 53934 53935 53936 53937 53938 53939 53940 53941 53942 53943 53944 53945 53946 53947 53948 53949 53950 53951 53952 53953 53954 53955 53956 53957 53958 53959 53960 53961 53962 53963 53964 53965 53966 53967 53968 53969 53970 53971 53972 53973 53974 53975 53976 53977 53978 53979 53980 53981 53982 53983 53984 53985 53986 53987 53988 53989 53990 53991 53992 53993 53994 53995 53996 53997 53998 53999 54000 54001 54002 54003 54004 54005 54006 54007 54008 54009 54010 54011 54012 54013 54014 54015 54016 54017 54018 54019 54020 54021 54022 54023 54024 54025 54026 54027 54028 54029 54030 54031 54032 54033 54034 54035 54036 54037 54038 54039 54040 54041 54042 54043 54044 54045 54046 54047 54048 54049 54050 54051 54052 54053 54054 54055 54056 54057 54058 54059 54060 54061 54062 54063 54064 54065 54066 54067 54068 54069 54070 54071 54072 54073 54074 54075 54076 54077 54078 54079 54080 54081 54082 54083 54084 54085 54086 54087 54088 54089 54090 54091 54092 54093 54094 54095 54096 54097 54098 54099 54100 54101 54102 54103 54104 54105 54106 54107 54108 54109 54110 54111 54112 54113 54114 54115 54116 54117 54118 54119 54120 54121 54122 54123 54124 54125 54126 54127 54128 54129 54130 54131 54132 54133 54134 54135 54136 54137 54138 54139 54140 54141 54142 54143 54144 54145 54146 54147 54148 54149 54150 54151 54152 54153 54154 54155 54156 54157 54158 54159 54160 54161 54162 54163 54164 54165 54166 54167 54168 54169 54170 54171 54172 54173 54174 54175 54176 54177 54178 54179 54180 54181 54182 54183 54184 54185 54186 54187 54188 54189 54190 54191 54192 54193 54194 54195 54196 54197 54198 54199 54200 54201 54202 54203 54204 54205 54206 54207 54208 54209 54210 54211 54212 54213 54214 54215 54216 54217 54218 54219 54220 54221 54222 54223 54224 54225 54226 54227 54228 54229 54230 54231 54232 54233 54234 54235 54236 54237 54238 54239 54240 54241 54242 54243 54244 54245 54246 54247 54248 54249 54250 54251 54252 54253 54254 54255 54256 54257 54258 54259 54260 54261 54262 54263 54264 54265 54266 54267 54268 54269 54270 54271 54272 54273 54274 54275 54276 54277 54278 54279 54280 54281 54282 54283 54284 54285 54286 54287 54288 54289 54290 54291 54292 54293 54294 54295 54296 54297 54298 54299 54300 54301 54302 54303 54304 54305 54306 54307 54308 54309 54310 54311 54312 54313 54314 54315 54316 54317 54318 54319 54320 54321 54322 54323 54324 54325 54326 54327 54328 54329 54330 54331 54332 54333 54334 54335 54336 54337 54338 54339 54340 54341 54342 54343 54344 54345 54346 54347 54348 54349 54350 54351 54352 54353 54354 54355 54356 54357 54358 54359 54360 54361 54362 54363 54364 54365 54366 54367 54368 54369 54370 54371 54372 54373 54374 54375 54376 54377 54378 54379 54380 54381 54382 54383 54384 54385 54386 54387 54388 54389 54390 54391 54392 54393 54394 54395 54396 54397 54398 54399 54400 54401 54402 54403 54404 54405 54406 54407 54408 54409 54410 54411 54412 54413 54414 54415 54416 54417 54418 54419 54420 54421 54422 54423 54424 54425 54426 54427 54428 54429 54430 54431 54432 54433 54434 54435 54436 54437 54438 54439 54440 54441 54442 54443 54444 54445 54446 54447 54448 54449 54450 54451 54452 54453 54454 54455 54456 54457 54458 54459 54460 54461 54462 54463 54464 54465 54466 54467 54468 54469 54470 54471 54472 54473 54474 54475 54476 54477 54478 54479 54480 54481 54482 54483 54484 54485 54486 54487 54488 54489 54490 54491 54492 54493 54494 54495 54496 54497 54498 54499 54500 54501 54502 54503 54504 54505 54506 54507 54508 54509 54510 54511 54512 54513 54514 54515 54516 54517 54518 54519 54520 54521 54522 54523 54524 54525 54526 54527 54528 54529 54530 54531 54532 54533 54534 54535 54536 54537 54538 54539 54540 54541 54542 54543 54544 54545 54546 54547 54548 54549 54550 54551 54552 54553 54554 54555 54556 54557 54558 54559 54560 54561 54562 54563 54564 54565 54566 54567 54568 54569 54570 54571 54572 54573 54574 54575 54576 54577 54578 54579 54580 54581 54582 54583 54584 54585 54586 54587 54588 54589 54590 54591 54592 54593 54594 54595 54596 54597 54598 54599 54600 54601 54602 54603 54604 54605 54606 54607 54608 54609 54610 54611 54612 54613 54614 54615 54616 54617 54618 54619 54620 54621 54622 54623 54624 54625 54626 54627 54628 54629 54630 54631 54632 54633 54634 54635 54636 54637 54638 54639 54640 54641 54642 54643 54644 54645 54646 54647 54648 54649 54650 54651 54652 54653 54654 54655 54656 54657 54658 54659 54660 54661 54662 54663 54664 54665 54666 54667 54668 54669 54670 54671 54672 54673 54674 54675 54676 54677 54678 54679 54680 54681 54682 54683 54684 54685 54686 54687 54688 54689 54690 54691 54692 54693 54694 54695 54696 54697 54698 54699 54700 54701 54702 54703 54704 54705 54706 54707 54708 54709 54710 54711 54712 54713 54714 54715 54716 54717 54718 54719 54720 54721 54722 54723 54724 54725 54726 54727 54728 54729 54730 54731 54732 54733 54734 54735 54736 54737 54738 54739 54740 54741 54742 54743 54744 54745 54746 54747 54748 54749 54750 54751 54752 54753 54754 54755 54756 54757 54758 54759 54760 54761 54762 54763 54764 54765 54766 54767 54768 54769 54770 54771 54772 54773 54774 54775 54776 54777 54778 54779 54780 54781 54782 54783 54784 54785 54786 54787 54788 54789 54790 54791 54792 54793 54794 54795 54796 54797 54798 54799 54800 54801 54802 54803 54804 54805 54806 54807 54808 54809 54810 54811 54812 54813 54814 54815 54816 54817 54818 54819 54820 54821 54822 54823 54824 54825 54826 54827 54828 54829 54830 54831 54832 54833 54834 54835 54836 54837 54838 54839 54840 54841 54842 54843 54844 54845 54846 54847 54848 54849 54850 54851 54852 54853 54854 54855 54856 54857 54858 54859 54860 54861 54862 54863 54864 54865 54866 54867 54868 54869 54870 54871 54872 54873 54874 54875 54876 54877 54878 54879 54880 54881 54882 54883 54884 54885 54886 54887 54888 54889 54890 54891 54892 54893 54894 54895 54896 54897 54898 54899 54900 54901 54902 54903 54904 54905 54906 54907 54908 54909 54910 54911 54912 54913 54914 54915 54916 54917 54918 54919 54920 54921 54922 54923 54924 54925 54926 54927 54928 54929 54930 54931 54932 54933 54934 54935 54936 54937 54938 54939 54940 54941 54942 54943 54944 54945 54946 54947 54948 54949 54950 54951 54952 54953 54954 54955 54956 54957 54958 54959 54960 54961 54962 54963 54964 54965 54966 54967 54968 54969 54970 54971 54972 54973 54974 54975 54976 54977 54978 54979 54980 54981 54982 54983 54984 54985 54986 54987 54988 54989 54990 54991 54992 54993 54994 54995 54996 54997 54998 54999 55000 55001 55002 55003 55004 55005 55006 55007 55008 55009 55010 55011 55012 55013 55014 55015 55016 55017 55018 55019 55020 55021 55022 55023 55024 55025 55026 55027 55028 55029 55030 55031 55032 55033 55034 55035 55036 55037 55038 55039 55040 55041 55042 55043 55044 55045 55046 55047 55048 55049 55050 55051 55052 55053 55054 55055 55056 55057 55058 55059 55060 55061 55062 55063 55064 55065 55066 55067 55068 55069 55070 55071 55072 55073 55074 55075 55076 55077 55078 55079 55080 55081 55082 55083 55084 55085 55086 55087 55088 55089 55090 55091 55092 55093 55094 55095 55096 55097 55098 55099 55100 55101 55102 55103 55104 55105 55106 55107 55108 55109 55110 55111 55112 55113 55114 55115 55116 55117 55118 55119 55120 55121 55122 55123 55124 55125 55126 55127 55128 55129 55130 55131 55132 55133 55134 55135 55136 55137 55138 55139 55140 55141 55142 55143 55144 55145 55146 55147 55148 55149 55150 55151 55152 55153 55154 55155 55156 55157 55158 55159 55160 55161 55162 55163 55164 55165 55166 55167 55168 55169 55170 55171 55172 55173 55174 55175 55176 55177 55178 55179 55180 55181 55182 55183 55184 55185 55186 55187 55188 55189 55190 55191 55192 55193 55194 55195 55196 55197 55198 55199 55200 55201 55202 55203 55204 55205 55206 55207 55208 55209 55210 55211 55212 55213 55214 55215 55216 55217 55218 55219 55220 55221 55222 55223 55224 55225 55226 55227 55228 55229 55230 55231 55232 55233 55234 55235 55236 55237 55238 55239 55240 55241 55242 55243 55244 55245 55246 55247 55248 55249 55250 55251 55252 55253 55254 55255 55256 55257 55258 55259 55260 55261 55262 55263 55264 55265 55266 55267 55268 55269 55270 55271 55272 55273 55274 55275 55276 55277 55278 55279 55280 55281 55282 55283 55284 55285 55286 55287 55288 55289 55290 55291 55292 55293 55294 55295 55296 55297 55298 55299 55300 55301 55302 55303 55304 55305 55306 55307 55308 55309 55310 55311 55312 55313 55314 55315 55316 55317 55318 55319 55320 55321 55322 55323 55324 55325 55326 55327 55328 55329 55330 55331 55332 55333 55334 55335 55336 55337 55338 55339 55340 55341 55342 55343 55344 55345 55346 55347 55348 55349 55350 55351 55352 55353 55354 55355 55356 55357 55358 55359 55360 55361 55362 55363 55364 55365 55366 55367 55368 55369 55370 55371 55372 55373 55374 55375 55376 55377 55378 55379 55380 55381 55382 55383 55384 55385 55386 55387 55388 55389 55390 55391 55392 55393 55394 55395 55396 55397 55398 55399 55400 55401 55402 55403 55404 55405 55406 55407 55408 55409 55410 55411 55412 55413 55414 55415 55416 55417 55418 55419 55420 55421 55422 55423 55424 55425 55426 55427 55428 55429 55430 55431 55432 55433 55434 55435 55436 55437 55438 55439 55440 55441 55442 55443 55444 55445 55446 55447 55448 55449 55450 55451 55452 55453 55454 55455 55456 55457 55458 55459 55460 55461 55462 55463 55464 55465 55466 55467 55468 55469 55470 55471 55472 55473 55474 55475 55476 55477 55478 55479 55480 55481 55482 55483 55484 55485 55486 55487 55488 55489 55490 55491 55492 55493 55494 55495 55496 55497 55498 55499 55500 55501 55502 55503 55504 55505 55506 55507 55508 55509 55510 55511 55512 55513 55514 55515 55516 55517 55518 55519 55520 55521 55522 55523 55524 55525 55526 55527 55528 55529 55530 55531 55532 55533 55534 55535 55536 55537 55538 55539 55540 55541 55542 55543 55544 55545 55546 55547 55548 55549 55550 55551 55552 55553 55554 55555 55556 55557 55558 55559 55560 55561 55562 55563 55564 55565 55566 55567 55568 55569 55570 55571 55572 55573 55574 55575 55576 55577 55578 55579 55580 55581 55582 55583 55584 55585 55586 55587 55588 55589 55590 55591 55592 55593 55594 55595 55596 55597 55598 55599 55600 55601 55602 55603 55604 55605 55606 55607 55608 55609 55610 55611 55612 55613 55614 55615 55616 55617 55618 55619 55620 55621 55622 55623 55624 55625 55626 55627 55628 55629 55630 55631 55632 55633 55634 55635 55636 55637 55638 55639 55640 55641 55642 55643 55644 55645 55646 55647 55648 55649 55650 55651 55652 55653 55654 55655 55656 55657 55658 55659 55660 55661 55662 55663 55664 55665 55666 55667 55668 55669 55670 55671 55672 55673 55674 55675 55676 55677 55678 55679 55680 55681 55682 55683 55684 55685 55686 55687 55688 55689 55690 55691 55692 55693 55694 55695 55696 55697 55698 55699 55700 55701 55702 55703 55704 55705 55706 55707 55708 55709 55710 55711 55712 55713 55714 55715 55716 55717 55718 55719 55720 55721 55722 55723 55724 55725 55726 55727 55728 55729 55730 55731 55732 55733 55734 55735 55736 55737 55738 55739 55740 55741 55742 55743 55744 55745 55746 55747 55748 55749 55750 55751 55752 55753 55754 55755 55756 55757 55758 55759 55760 55761 55762 55763 55764 55765 55766 55767 55768 55769 55770 55771 55772 55773 55774 55775 55776 55777 55778 55779 55780 55781 55782 55783 55784 55785 55786 55787 55788 55789 55790 55791 55792 55793 55794 55795 55796 55797 55798 55799 55800 55801 55802 55803 55804 55805 55806 55807 55808 55809 55810 55811 55812 55813 55814 55815 55816 55817 55818 55819 55820 55821 55822 55823 55824 55825 55826 55827 55828 55829 55830 55831 55832 55833 55834 55835 55836 55837 55838 55839 55840 55841 55842 55843 55844 55845 55846 55847 55848 55849 55850 55851 55852 55853 55854 55855 55856 55857 55858 55859 55860 55861 55862 55863 55864 55865 55866 55867 55868 55869 55870 55871 55872 55873 55874 55875 55876 55877 55878 55879 55880 55881 55882 55883 55884 55885 55886 55887 55888 55889 55890 55891 55892 55893 55894 55895 55896 55897 55898 55899 55900 55901 55902 55903 55904 55905 55906 55907 55908 55909 55910 55911 55912 55913 55914 55915 55916 55917 55918 55919 55920 55921 55922 55923 55924 55925 55926 55927 55928 55929 55930 55931 55932 55933 55934 55935 55936 55937 55938 55939 55940 55941 55942 55943 55944 55945 55946 55947 55948 55949 55950 55951 55952 55953 55954 55955 55956 55957 55958 55959 55960 55961 55962 55963 55964 55965 55966 55967 55968 55969 55970 55971 55972 55973 55974 55975 55976 55977 55978 55979 55980 55981 55982 55983 55984 55985 55986 55987 55988 55989 55990 55991 55992 55993 55994 55995 55996 55997 55998 55999 56000 56001 56002 56003 56004 56005 56006 56007 56008 56009 56010 56011 56012 56013 56014 56015 56016 56017 56018 56019 56020 56021 56022 56023 56024 56025 56026 56027 56028 56029 56030 56031 56032 56033 56034 56035 56036 56037 56038 56039 56040 56041 56042 56043 56044 56045 56046 56047 56048 56049 56050 56051 56052 56053 56054 56055 56056 56057 56058 56059 56060 56061 56062 56063 56064 56065 56066 56067 56068 56069 56070 56071 56072 56073 56074 56075 56076 56077 56078 56079 56080 56081 56082 56083 56084 56085 56086 56087 56088 56089 56090 56091 56092 56093 56094 56095 56096 56097 56098 56099 56100 56101 56102 56103 56104 56105 56106 56107 56108 56109 56110 56111 56112 56113 56114 56115 56116 56117 56118 56119 56120 56121 56122 56123 56124 56125 56126 56127 56128 56129 56130 56131 56132 56133 56134 56135 56136 56137 56138 56139 56140 56141 56142 56143 56144 56145 56146 56147 56148 56149 56150 56151 56152 56153 56154 56155 56156 56157 56158 56159 56160 56161 56162 56163 56164 56165 56166 56167 56168 56169 56170 56171 56172 56173 56174 56175 56176 56177 56178 56179 56180 56181 56182 56183 56184 56185 56186 56187 56188 56189 56190 56191 56192 56193 56194 56195 56196 56197 56198 56199 56200 56201 56202 56203 56204 56205 56206 56207 56208 56209 56210 56211 56212 56213 56214 56215 56216 56217 56218 56219 56220 56221 56222 56223 56224 56225 56226 56227 56228 56229 56230 56231 56232 56233 56234 56235 56236 56237 56238 56239 56240 56241 56242 56243 56244 56245 56246 56247 56248 56249 56250 56251 56252 56253 56254 56255 56256 56257 56258 56259 56260 56261 56262 56263 56264 56265 56266 56267 56268 56269 56270 56271 56272 56273 56274 56275 56276 56277 56278 56279 56280 56281 56282 56283 56284 56285 56286 56287 56288 56289 56290 56291 56292 56293 56294 56295 56296 56297 56298 56299 56300 56301 56302 56303 56304 56305 56306 56307 56308 56309 56310 56311 56312 56313 56314 56315 56316 56317 56318 56319 56320 56321 56322 56323 56324 56325 56326 56327 56328 56329 56330 56331 56332 56333 56334 56335 56336 56337 56338 56339 56340 56341 56342 56343 56344 56345 56346 56347 56348 56349 56350 56351 56352 56353 56354 56355 56356 56357 56358 56359 56360 56361 56362 56363 56364 56365 56366 56367 56368 56369 56370 56371 56372 56373 56374 56375 56376 56377 56378 56379 56380 56381 56382 56383 56384 56385 56386 56387 56388 56389 56390 56391 56392 56393 56394 56395 56396 56397 56398 56399 56400 56401 56402 56403 56404 56405 56406 56407 56408 56409 56410 56411 56412 56413 56414 56415 56416 56417 56418 56419 56420 56421 56422 56423 56424 56425 56426 56427 56428 56429 56430 56431 56432 56433 56434 56435 56436 56437 56438 56439 56440 56441 56442 56443 56444 56445 56446 56447 56448 56449 56450 56451 56452 56453 56454 56455 56456 56457 56458 56459 56460 56461 56462 56463 56464 56465 56466 56467 56468 56469 56470 56471 56472 56473 56474 56475 56476 56477 56478 56479 56480 56481 56482 56483 56484 56485 56486 56487 56488 56489 56490 56491 56492 56493 56494 56495 56496 56497 56498 56499 56500 56501 56502 56503 56504 56505 56506 56507 56508 56509 56510 56511 56512 56513 56514 56515 56516 56517 56518 56519 56520 56521 56522 56523 56524 56525 56526 56527 56528 56529 56530 56531 56532 56533 56534 56535 56536 56537 56538 56539 56540 56541 56542 56543 56544 56545 56546 56547 56548 56549 56550 56551 56552 56553 56554 56555 56556 56557 56558 56559 56560 56561 56562 56563 56564 56565 56566 56567 56568 56569 56570 56571 56572 56573 56574 56575 56576 56577 56578 56579 56580 56581 56582 56583 56584 56585 56586 56587 56588 56589 56590 56591 56592 56593 56594 56595 56596 56597 56598 56599 56600 56601 56602 56603 56604 56605 56606 56607 56608 56609 56610 56611 56612 56613 56614 56615 56616 56617 56618 56619 56620 56621 56622 56623 56624 56625 56626 56627 56628 56629 56630 56631 56632 56633 56634 56635 56636 56637 56638 56639 56640 56641 56642 56643 56644 56645 56646 56647 56648 56649 56650 56651 56652 56653 56654 56655 56656 56657 56658 56659 56660 56661 56662 56663 56664 56665 56666 56667 56668 56669 56670 56671 56672 56673 56674 56675 56676 56677 56678 56679 56680 56681 56682 56683 56684 56685 56686 56687 56688 56689 56690 56691 56692 56693 56694 56695 56696 56697 56698 56699 56700 56701 56702 56703 56704 56705 56706 56707 56708 56709 56710 56711 56712 56713 56714 56715 56716 56717 56718 56719 56720 56721 56722 56723 56724 56725 56726 56727 56728 56729 56730 56731 56732 56733 56734 56735 56736 56737 56738 56739 56740 56741 56742 56743 56744 56745 56746 56747 56748 56749 56750 56751 56752 56753 56754 56755 56756 56757 56758 56759 56760 56761 56762 56763 56764 56765 56766 56767 56768 56769 56770 56771 56772 56773 56774 56775 56776 56777 56778 56779 56780 56781 56782 56783 56784 56785 56786 56787 56788 56789 56790 56791 56792 56793 56794 56795 56796 56797 56798 56799 56800 56801 56802 56803 56804 56805 56806 56807 56808 56809 56810 56811 56812 56813 56814 56815 56816 56817 56818 56819 56820 56821 56822 56823 56824 56825 56826 56827 56828 56829 56830 56831 56832 56833 56834 56835 56836 56837 56838 56839 56840 56841 56842 56843 56844 56845 56846 56847 56848 56849 56850 56851 56852 56853 56854 56855 56856 56857 56858 56859 56860 56861 56862 56863 56864 56865 56866 56867 56868 56869 56870 56871 56872 56873 56874 56875 56876 56877 56878 56879 56880 56881 56882 56883 56884 56885 56886 56887 56888 56889 56890 56891 56892 56893 56894 56895 56896 56897 56898 56899 56900 56901 56902 56903 56904 56905 56906 56907 56908 56909 56910 56911 56912 56913 56914 56915 56916 56917 56918 56919 56920 56921 56922 56923 56924 56925 56926 56927 56928 56929 56930 56931 56932 56933 56934 56935 56936 56937 56938 56939 56940 56941 56942 56943 56944 56945 56946 56947 56948 56949 56950 56951 56952 56953 56954 56955 56956 56957 56958 56959 56960 56961 56962 56963 56964 56965 56966 56967 56968 56969 56970 56971 56972 56973 56974 56975 56976 56977 56978 56979 56980 56981 56982 56983 56984 56985 56986 56987 56988 56989 56990 56991 56992 56993 56994 56995 56996 56997 56998 56999 57000 57001 57002 57003 57004 57005 57006 57007 57008 57009 57010 57011 57012 57013 57014 57015 57016 57017 57018 57019 57020 57021 57022 57023 57024 57025 57026 57027 57028 57029 57030 57031 57032 57033 57034 57035 57036 57037 57038 57039 57040 57041 57042 57043 57044 57045 57046 57047 57048 57049 57050 57051 57052 57053 57054 57055 57056 57057 57058 57059 57060 57061 57062 57063 57064 57065 57066 57067 57068 57069 57070 57071 57072 57073 57074 57075 57076 57077 57078 57079 57080 57081 57082 57083 57084 57085 57086 57087 57088 57089 57090 57091 57092 57093 57094 57095 57096 57097 57098 57099 57100 57101 57102 57103 57104 57105 57106 57107 57108 57109 57110 57111 57112 57113 57114 57115 57116 57117 57118 57119 57120 57121 57122 57123 57124 57125 57126 57127 57128 57129 57130 57131 57132 57133 57134 57135 57136 57137 57138 57139 57140 57141 57142 57143 57144 57145 57146 57147 57148 57149 57150 57151 57152 57153 57154 57155 57156 57157 57158 57159 57160 57161 57162 57163 57164 57165 57166 57167 57168 57169 57170 57171 57172 57173 57174 57175 57176 57177 57178 57179 57180 57181 57182 57183 57184 57185 57186 57187 57188 57189 57190 57191 57192 57193 57194 57195 57196 57197 57198 57199 57200 57201 57202 57203 57204 57205 57206 57207 57208 57209 57210 57211 57212 57213 57214 57215 57216 57217 57218 57219 57220 57221 57222 57223 57224 57225 57226 57227 57228 57229 57230 57231 57232 57233 57234 57235 57236 57237 57238 57239 57240 57241 57242 57243 57244 57245 57246 57247 57248 57249 57250 57251 57252 57253 57254 57255 57256 57257 57258 57259 57260 57261 57262 57263 57264 57265 57266 57267 57268 57269 57270 57271 57272 57273 57274 57275 57276 57277 57278 57279 57280 57281 57282 57283 57284 57285 57286 57287 57288 57289 57290 57291 57292 57293 57294 57295 57296 57297 57298 57299 57300 57301 57302 57303 57304 57305 57306 57307 57308 57309 57310 57311 57312 57313 57314 57315 57316 57317 57318 57319 57320 57321 57322 57323 57324 57325 57326 57327 57328 57329 57330 57331 57332 57333 57334 57335 57336 57337 57338 57339 57340 57341 57342 57343 57344 57345 57346 57347 57348 57349 57350 57351 57352 57353 57354 57355 57356 57357 57358 57359 57360 57361 57362 57363 57364 57365 57366 57367 57368 57369 57370 57371 57372 57373 57374 57375 57376 57377 57378 57379 57380 57381 57382 57383 57384 57385 57386 57387 57388 57389 57390 57391 57392 57393 57394 57395 57396 57397 57398 57399 57400 57401 57402 57403 57404 57405 57406 57407 57408 57409 57410 57411 57412 57413 57414 57415 57416 57417 57418 57419 57420 57421 57422 57423 57424 57425 57426 57427 57428 57429 57430 57431 57432 57433 57434 57435 57436 57437 57438 57439 57440 57441 57442 57443 57444 57445 57446 57447 57448 57449 57450 57451 57452 57453 57454 57455 57456 57457 57458 57459 57460 57461 57462 57463 57464 57465 57466 57467 57468 57469 57470 57471 57472 57473 57474 57475 57476 57477 57478 57479 57480 57481 57482 57483 57484 57485 57486 57487 57488 57489 57490 57491 57492 57493 57494 57495 57496 57497 57498 57499 57500 57501 57502 57503 57504 57505 57506 57507 57508 57509 57510 57511 57512 57513 57514 57515 57516 57517 57518 57519 57520 57521 57522 57523 57524 57525 57526 57527 57528 57529 57530 57531 57532 57533 57534 57535 57536 57537 57538 57539 57540 57541 57542 57543 57544 57545 57546 57547 57548 57549 57550 57551 57552 57553 57554 57555 57556 57557 57558 57559 57560 57561 57562 57563 57564 57565 57566 57567 57568 57569 57570 57571 57572 57573 57574 57575 57576 57577 57578 57579 57580 57581 57582 57583 57584 57585 57586 57587 57588 57589 57590 57591 57592 57593 57594 57595 57596 57597 57598 57599 57600 57601 57602 57603 57604 57605 57606 57607 57608 57609 57610 57611 57612 57613 57614 57615 57616 57617 57618 57619 57620 57621 57622 57623 57624 57625 57626 57627 57628 57629 57630 57631 57632 57633 57634 57635 57636 57637 57638 57639 57640 57641 57642 57643 57644 57645 57646 57647 57648 57649 57650 57651 57652 57653 57654 57655 57656 57657 57658 57659 57660 57661 57662 57663 57664 57665 57666 57667 57668 57669 57670 57671 57672 57673 57674 57675 57676 57677 57678 57679 57680 57681 57682 57683 57684 57685 57686 57687 57688 57689 57690 57691 57692 57693 57694 57695 57696 57697 57698 57699 57700 57701 57702 57703 57704 57705 57706 57707 57708 57709 57710 57711 57712 57713 57714 57715 57716 57717 57718 57719 57720 57721 57722 57723 57724 57725 57726 57727 57728 57729 57730 57731 57732 57733 57734 57735 57736 57737 57738 57739 57740 57741 57742 57743 57744 57745 57746 57747 57748 57749 57750 57751 57752 57753 57754 57755 57756 57757 57758 57759 57760 57761 57762 57763 57764 57765 57766 57767 57768 57769 57770 57771 57772 57773 57774 57775 57776 57777 57778 57779 57780 57781 57782 57783 57784 57785 57786 57787 57788 57789 57790 57791 57792 57793 57794 57795 57796 57797 57798 57799 57800 57801 57802 57803 57804 57805 57806 57807 57808 57809 57810 57811 57812 57813 57814 57815 57816 57817 57818 57819 57820 57821 57822 57823 57824 57825 57826 57827 57828 57829 57830 57831 57832 57833 57834 57835 57836 57837 57838 57839 57840 57841 57842 57843 57844 57845 57846 57847 57848 57849 57850 57851 57852 57853 57854 57855 57856 57857 57858 57859 57860 57861 57862 57863 57864 57865 57866 57867 57868 57869 57870 57871 57872 57873 57874 57875 57876 57877 57878 57879 57880 57881 57882 57883 57884 57885 57886 57887 57888 57889 57890 57891 57892 57893 57894 57895 57896 57897 57898 57899 57900 57901 57902 57903 57904 57905 57906 57907 57908 57909 57910 57911 57912 57913 57914 57915 57916 57917 57918 57919 57920 57921 57922 57923 57924 57925 57926 57927 57928 57929 57930 57931 57932 57933 57934 57935 57936 57937 57938 57939 57940 57941 57942 57943 57944 57945 57946 57947 57948 57949 57950 57951 57952 57953 57954 57955 57956 57957 57958 57959 57960 57961 57962 57963 57964 57965 57966 57967 57968 57969 57970 57971 57972 57973 57974 57975 57976 57977 57978 57979 57980 57981 57982 57983 57984 57985 57986 57987 57988 57989 57990 57991 57992 57993 57994 57995 57996 57997 57998 57999 58000 58001 58002 58003 58004 58005 58006 58007 58008 58009 58010 58011 58012 58013 58014 58015 58016 58017 58018 58019 58020 58021 58022 58023 58024 58025 58026 58027 58028 58029 58030 58031 58032 58033 58034 58035 58036 58037 58038 58039 58040 58041 58042 58043 58044 58045 58046 58047 58048 58049 58050 58051 58052 58053 58054 58055 58056 58057 58058 58059 58060 58061 58062 58063 58064 58065 58066 58067 58068 58069 58070 58071 58072 58073 58074 58075 58076 58077 58078 58079 58080 58081 58082 58083 58084 58085 58086 58087 58088 58089 58090 58091 58092 58093 58094 58095 58096 58097 58098 58099 58100 58101 58102 58103 58104 58105 58106 58107 58108 58109 58110 58111 58112 58113 58114 58115 58116 58117 58118 58119 58120 58121 58122 58123 58124 58125 58126 58127 58128 58129 58130 58131 58132 58133 58134 58135 58136 58137 58138 58139 58140 58141 58142 58143 58144 58145 58146 58147 58148 58149 58150 58151 58152 58153 58154 58155 58156 58157 58158 58159 58160 58161 58162 58163 58164 58165 58166 58167 58168 58169 58170 58171 58172 58173 58174 58175 58176 58177 58178 58179 58180 58181 58182 58183 58184 58185 58186 58187 58188 58189 58190 58191 58192 58193 58194 58195 58196 58197 58198 58199 58200 58201 58202 58203 58204 58205 58206 58207 58208 58209 58210 58211 58212 58213 58214 58215 58216 58217 58218 58219 58220 58221 58222 58223 58224 58225 58226 58227 58228 58229 58230 58231 58232 58233 58234 58235 58236 58237 58238 58239 58240 58241 58242 58243 58244 58245 58246 58247 58248 58249 58250 58251 58252 58253 58254 58255 58256 58257 58258 58259 58260 58261 58262 58263 58264 58265 58266 58267 58268 58269 58270 58271 58272 58273 58274 58275 58276 58277 58278 58279 58280 58281 58282 58283 58284 58285 58286 58287 58288 58289 58290 58291 58292 58293 58294 58295 58296 58297 58298 58299 58300 58301 58302 58303 58304 58305 58306 58307 58308 58309 58310 58311 58312 58313 58314 58315 58316 58317 58318 58319 58320 58321 58322 58323 58324 58325 58326 58327 58328 58329 58330 58331 58332 58333 58334 58335 58336 58337 58338 58339 58340 58341 58342 58343 58344 58345 58346 58347 58348 58349 58350 58351 58352 58353 58354 58355 58356 58357 58358 58359 58360 58361 58362 58363 58364 58365 58366 58367 58368 58369 58370 58371 58372 58373 58374 58375 58376 58377 58378 58379 58380 58381 58382 58383 58384 58385 58386 58387 58388 58389 58390 58391 58392 58393 58394 58395 58396 58397 58398 58399 58400 58401 58402 58403 58404 58405 58406 58407 58408 58409 58410 58411 58412 58413 58414 58415 58416 58417 58418 58419 58420 58421 58422 58423 58424 58425 58426 58427 58428 58429 58430 58431 58432 58433 58434 58435 58436 58437 58438 58439 58440 58441 58442 58443 58444 58445 58446 58447 58448 58449 58450 58451 58452 58453 58454 58455 58456 58457 58458 58459 58460 58461 58462 58463 58464 58465 58466 58467 58468 58469 58470 58471 58472 58473 58474 58475 58476 58477 58478 58479 58480 58481 58482 58483 58484 58485 58486 58487 58488 58489 58490 58491 58492 58493 58494 58495 58496 58497 58498 58499 58500 58501 58502 58503 58504 58505 58506 58507 58508 58509 58510 58511 58512 58513 58514 58515 58516 58517 58518 58519 58520 58521 58522 58523 58524 58525 58526 58527 58528 58529 58530 58531 58532 58533 58534 58535 58536 58537 58538 58539 58540 58541 58542 58543 58544 58545 58546 58547 58548 58549 58550 58551 58552 58553 58554 58555 58556 58557 58558 58559 58560 58561 58562 58563 58564 58565 58566 58567 58568 58569 58570 58571 58572 58573 58574 58575 58576 58577 58578 58579 58580 58581 58582 58583 58584 58585 58586 58587 58588 58589 58590 58591 58592 58593 58594 58595 58596 58597 58598 58599 58600 58601 58602 58603 58604 58605 58606 58607 58608 58609 58610 58611 58612 58613 58614 58615 58616 58617 58618 58619 58620 58621 58622 58623 58624 58625 58626 58627 58628 58629 58630 58631 58632 58633 58634 58635 58636 58637 58638 58639 58640 58641 58642 58643 58644 58645 58646 58647 58648 58649 58650 58651 58652 58653 58654 58655 58656 58657 58658 58659 58660 58661 58662 58663 58664 58665 58666 58667 58668 58669 58670 58671 58672 58673 58674 58675 58676 58677 58678 58679 58680 58681 58682 58683 58684 58685 58686 58687 58688 58689 58690 58691 58692 58693 58694 58695 58696 58697 58698 58699 58700 58701 58702 58703 58704 58705 58706 58707 58708 58709 58710 58711 58712 58713 58714 58715 58716 58717 58718 58719 58720 58721 58722 58723 58724 58725 58726 58727 58728 58729 58730 58731 58732 58733 58734 58735 58736 58737 58738 58739 58740 58741 58742 58743 58744 58745 58746 58747 58748 58749 58750 58751 58752 58753 58754 58755 58756 58757 58758 58759 58760 58761 58762 58763 58764 58765 58766 58767 58768 58769 58770 58771 58772 58773 58774 58775 58776 58777 58778 58779 58780 58781 58782 58783 58784 58785 58786 58787 58788 58789 58790 58791 58792 58793 58794 58795 58796 58797 58798 58799 58800 58801 58802 58803 58804 58805 58806 58807 58808 58809 58810 58811 58812 58813 58814 58815 58816 58817 58818 58819 58820 58821 58822 58823 58824 58825 58826 58827 58828 58829 58830 58831 58832 58833 58834 58835 58836 58837 58838 58839 58840 58841 58842 58843 58844 58845 58846 58847 58848 58849 58850 58851 58852 58853 58854 58855 58856 58857 58858 58859 58860 58861 58862 58863 58864 58865 58866 58867 58868 58869 58870 58871 58872 58873 58874 58875 58876 58877 58878 58879 58880 58881 58882 58883 58884 58885 58886 58887 58888 58889 58890 58891 58892 58893 58894 58895 58896 58897 58898 58899 58900 58901 58902 58903 58904 58905 58906 58907 58908 58909 58910 58911 58912 58913 58914 58915 58916 58917 58918 58919 58920 58921 58922 58923 58924 58925 58926 58927 58928 58929 58930 58931 58932 58933 58934 58935 58936 58937 58938 58939 58940 58941 58942 58943 58944 58945 58946 58947 58948 58949 58950 58951 58952 58953 58954 58955 58956 58957 58958 58959 58960 58961 58962 58963 58964 58965 58966 58967 58968 58969 58970 58971 58972 58973 58974 58975 58976 58977 58978 58979 58980 58981 58982 58983 58984 58985 58986 58987 58988 58989 58990 58991 58992 58993 58994 58995 58996 58997 58998 58999 59000 59001 59002 59003 59004 59005 59006 59007 59008 59009 59010 59011 59012 59013 59014 59015 59016 59017 59018 59019 59020 59021 59022 59023 59024 59025 59026 59027 59028 59029 59030 59031 59032 59033 59034 59035 59036 59037 59038 59039 59040 59041 59042 59043 59044 59045 59046 59047 59048 59049 59050 59051 59052 59053 59054 59055 59056 59057 59058 59059 59060 59061 59062 59063 59064 59065 59066 59067 59068 59069 59070 59071 59072 59073 59074 59075 59076 59077 59078 59079 59080 59081 59082 59083 59084 59085 59086 59087 59088 59089 59090 59091 59092 59093 59094 59095 59096 59097 59098 59099 59100 59101 59102 59103 59104 59105 59106 59107 59108 59109 59110 59111 59112 59113 59114 59115 59116 59117 59118 59119 59120 59121 59122 59123 59124 59125 59126 59127 59128 59129 59130 59131 59132 59133 59134 59135 59136 59137 59138 59139 59140 59141 59142 59143 59144 59145 59146 59147 59148 59149 59150 59151 59152 59153 59154 59155 59156 59157 59158 59159 59160 59161 59162 59163 59164 59165 59166 59167 59168 59169 59170 59171 59172 59173 59174 59175 59176 59177 59178 59179 59180 59181 59182 59183 59184 59185 59186 59187 59188 59189 59190 59191 59192 59193 59194 59195 59196 59197 59198 59199 59200 59201 59202 59203 59204 59205 59206 59207 59208 59209 59210 59211 59212 59213 59214 59215 59216 59217 59218 59219 59220 59221 59222 59223 59224 59225 59226 59227 59228 59229 59230 59231 59232 59233 59234 59235 59236 59237 59238 59239 59240 59241 59242 59243 59244 59245 59246 59247 59248 59249 59250 59251 59252 59253 59254 59255 59256 59257 59258 59259 59260 59261 59262 59263 59264 59265 59266 59267 59268 59269 59270 59271 59272 59273 59274 59275 59276 59277 59278 59279 59280 59281 59282 59283 59284 59285 59286 59287 59288 59289 59290 59291 59292 59293 59294 59295 59296 59297 59298 59299 59300 59301 59302 59303 59304 59305 59306 59307 59308 59309 59310 59311 59312 59313 59314 59315 59316 59317 59318 59319 59320 59321 59322 59323 59324 59325 59326 59327 59328 59329 59330 59331 59332 59333 59334 59335 59336 59337 59338 59339 59340 59341 59342 59343 59344 59345 59346 59347 59348 59349 59350 59351 59352 59353 59354 59355 59356 59357 59358 59359 59360 59361 59362 59363 59364 59365 59366 59367 59368 59369 59370 59371 59372 59373 59374 59375 59376 59377 59378 59379 59380 59381 59382 59383 59384 59385 59386 59387 59388 59389 59390 59391 59392 59393 59394 59395 59396 59397 59398 59399 59400 59401 59402 59403 59404 59405 59406 59407 59408 59409 59410 59411 59412 59413 59414 59415 59416 59417 59418 59419 59420 59421 59422 59423 59424 59425 59426 59427 59428 59429 59430 59431 59432 59433 59434 59435 59436 59437 59438 59439 59440 59441 59442 59443 59444 59445 59446 59447 59448 59449 59450 59451 59452 59453 59454 59455 59456 59457 59458 59459 59460 59461 59462 59463 59464 59465 59466 59467 59468 59469 59470 59471 59472 59473 59474 59475 59476 59477 59478 59479 59480 59481 59482 59483 59484 59485 59486 59487 59488 59489 59490 59491 59492 59493 59494 59495 59496 59497 59498 59499 59500 59501 59502 59503 59504 59505 59506 59507 59508 59509 59510 59511 59512 59513 59514 59515 59516 59517 59518 59519 59520 59521 59522 59523 59524 59525 59526 59527 59528 59529 59530 59531 59532 59533 59534 59535 59536 59537 59538 59539 59540 59541 59542 59543 59544 59545 59546 59547 59548 59549 59550 59551 59552 59553 59554 59555 59556 59557 59558 59559 59560 59561 59562 59563 59564 59565 59566 59567 59568 59569 59570 59571 59572 59573 59574 59575 59576 59577 59578 59579 59580 59581 59582 59583 59584 59585 59586 59587 59588 59589 59590 59591 59592 59593 59594 59595 59596 59597 59598 59599 59600 59601 59602 59603 59604 59605 59606 59607 59608 59609 59610 59611 59612 59613 59614 59615 59616 59617 59618 59619 59620 59621 59622 59623 59624 59625 59626 59627 59628 59629 59630 59631 59632 59633 59634 59635 59636 59637 59638 59639 59640 59641 59642 59643 59644 59645 59646 59647 59648 59649 59650 59651 59652 59653 59654 59655 59656 59657 59658 59659 59660 59661 59662 59663 59664 59665 59666 59667 59668 59669 59670 59671 59672 59673 59674 59675 59676 59677 59678 59679 59680 59681 59682 59683 59684 59685 59686 59687 59688 59689 59690 59691 59692 59693 59694 59695 59696 59697 59698 59699 59700 59701 59702 59703 59704 59705 59706 59707 59708 59709 59710 59711 59712 59713 59714 59715 59716 59717 59718 59719 59720 59721 59722 59723 59724 59725 59726 59727 59728 59729 59730 59731 59732 59733 59734 59735 59736 59737 59738 59739 59740 59741 59742 59743 59744 59745 59746 59747 59748 59749 59750 59751 59752 59753 59754 59755 59756 59757 59758 59759 59760 59761 59762 59763 59764 59765 59766 59767 59768 59769 59770 59771 59772 59773 59774 59775 59776 59777 59778 59779 59780 59781 59782 59783 59784 59785 59786 59787 59788 59789 59790 59791 59792 59793 59794 59795 59796 59797 59798 59799 59800 59801 59802 59803 59804 59805 59806 59807 59808 59809 59810 59811 59812 59813 59814 59815 59816 59817 59818 59819 59820 59821 59822 59823 59824 59825 59826 59827 59828 59829 59830 59831 59832 59833 59834 59835 59836 59837 59838 59839 59840 59841 59842 59843 59844 59845 59846 59847 59848 59849 59850 59851 59852 59853 59854 59855 59856 59857 59858 59859 59860 59861 59862 59863 59864 59865 59866 59867 59868 59869 59870 59871 59872 59873 59874 59875 59876 59877 59878 59879 59880 59881 59882 59883 59884 59885 59886 59887 59888 59889 59890 59891 59892 59893 59894 59895 59896 59897 59898 59899 59900 59901 59902 59903 59904 59905 59906 59907 59908 59909 59910 59911 59912 59913 59914 59915 59916 59917 59918 59919 59920 59921 59922 59923 59924 59925 59926 59927 59928 59929 59930 59931 59932 59933 59934 59935 59936 59937 59938 59939 59940 59941 59942 59943 59944 59945 59946 59947 59948 59949 59950 59951 59952 59953 59954 59955 59956 59957 59958 59959 59960 59961 59962 59963 59964 59965 59966 59967 59968 59969 59970 59971 59972 59973 59974 59975 59976 59977 59978 59979 59980 59981 59982 59983 59984 59985 59986 59987 59988 59989 59990 59991 59992 59993 59994 59995 59996 59997 59998 59999 60000 60001 60002 60003 60004 60005 60006 60007 60008 60009 60010 60011 60012 60013 60014 60015 60016 60017 60018 60019 60020 60021 60022 60023 60024 60025 60026 60027 60028 60029 60030 60031 60032 60033 60034 60035 60036 60037 60038 60039 60040 60041 60042 60043 60044 60045 60046 60047 60048 60049 60050 60051 60052 60053 60054 60055 60056 60057 60058 60059 60060 60061 60062 60063 60064 60065 60066 60067 60068 60069 60070 60071 60072 60073 60074 60075 60076 60077 60078 60079 60080 60081 60082 60083 60084 60085 60086 60087 60088 60089 60090 60091 60092 60093 60094 60095 60096 60097 60098 60099 60100 60101 60102 60103 60104 60105 60106 60107 60108 60109 60110 60111 60112 60113 60114 60115 60116 60117 60118 60119 60120 60121 60122 60123 60124 60125 60126 60127 60128 60129 60130 60131 60132 60133 60134 60135 60136 60137 60138 60139 60140 60141 60142 60143 60144 60145 60146 60147 60148 60149 60150 60151 60152 60153 60154 60155 60156 60157 60158 60159 60160 60161 60162 60163 60164 60165 60166 60167 60168 60169 60170 60171 60172 60173 60174 60175 60176 60177 60178 60179 60180 60181 60182 60183 60184 60185 60186 60187 60188 60189 60190 60191 60192 60193 60194 60195 60196 60197 60198 60199 60200 60201 60202 60203 60204 60205 60206 60207 60208 60209 60210 60211 60212 60213 60214 60215 60216 60217 60218 60219 60220 60221 60222 60223 60224 60225 60226 60227 60228 60229 60230 60231 60232 60233 60234 60235 60236 60237 60238 60239 60240 60241 60242 60243 60244 60245 60246 60247 60248 60249 60250 60251 60252 60253 60254 60255 60256 60257 60258 60259 60260 60261 60262 60263 60264 60265 60266 60267 60268 60269 60270 60271 60272 60273 60274 60275 60276 60277 60278 60279 60280 60281 60282 60283 60284 60285 60286 60287 60288 60289 60290 60291 60292 60293 60294 60295 60296 60297 60298 60299 60300 60301 60302 60303 60304 60305 60306 60307 60308 60309 60310 60311 60312 60313 60314 60315 60316 60317 60318 60319 60320 60321 60322 60323 60324 60325 60326 60327 60328 60329 60330 60331 60332 60333 60334 60335 60336 60337 60338 60339 60340 60341 60342 60343 60344 60345 60346 60347 60348 60349 60350 60351 60352 60353 60354 60355 60356 60357 60358 60359 60360 60361 60362 60363 60364 60365 60366 60367 60368 60369 60370 60371 60372 60373 60374 60375 60376 60377 60378 60379 60380 60381 60382 60383 60384 60385 60386 60387 60388 60389 60390 60391 60392 60393 60394 60395 60396 60397 60398 60399 60400 60401 60402 60403 60404 60405 60406 60407 60408 60409 60410 60411 60412 60413 60414 60415 60416 60417 60418 60419 60420 60421 60422 60423 60424 60425 60426 60427 60428 60429 60430 60431 60432 60433 60434 60435 60436 60437 60438 60439 60440 60441 60442 60443 60444 60445 60446 60447 60448 60449 60450 60451 60452 60453 60454 60455 60456 60457 60458 60459 60460 60461 60462 60463 60464 60465 60466 60467 60468 60469 60470 60471 60472 60473 60474 60475 60476 60477 60478 60479 60480 60481 60482 60483 60484 60485 60486 60487 60488 60489 60490 60491 60492 60493 60494 60495 60496 60497 60498 60499 60500 60501 60502 60503 60504 60505 60506 60507 60508 60509 60510 60511 60512 60513 60514 60515 60516 60517 60518 60519 60520 60521 60522 60523 60524 60525 60526 60527 60528 60529 60530 60531 60532 60533 60534 60535 60536 60537 60538 60539 60540 60541 60542 60543 60544 60545 60546 60547 60548 60549 60550 60551 60552 60553 60554 60555 60556 60557 60558 60559 60560 60561 60562 60563 60564 60565 60566 60567 60568 60569 60570 60571 60572 60573 60574 60575 60576 60577 60578 60579 60580 60581 60582 60583 60584 60585 60586 60587 60588 60589 60590 60591 60592 60593 60594 60595 60596 60597 60598 60599 60600 60601 60602 60603 60604 60605 60606 60607 60608 60609 60610 60611 60612 60613 60614 60615 60616 60617 60618 60619 60620 60621 60622 60623 60624 60625 60626 60627 60628 60629 60630 60631 60632 60633 60634 60635 60636 60637 60638 60639 60640 60641 60642 60643 60644 60645 60646 60647 60648 60649 60650 60651 60652 60653 60654 60655 60656 60657 60658 60659 60660 60661 60662 60663 60664 60665 60666 60667 60668 60669 60670 60671 60672 60673 60674 60675 60676 60677 60678 60679 60680 60681 60682 60683 60684 60685 60686 60687 60688 60689 60690 60691 60692 60693 60694 60695 60696 60697 60698 60699 60700 60701 60702 60703 60704 60705 60706 60707 60708 60709 60710 60711 60712 60713 60714 60715 60716 60717 60718 60719 60720 60721 60722 60723 60724 60725 60726 60727 60728 60729 60730 60731 60732 60733 60734 60735 60736 60737 60738 60739 60740 60741 60742 60743 60744 60745 60746 60747 60748 60749 60750 60751 60752 60753 60754 60755 60756 60757 60758 60759 60760 60761 60762 60763 60764 60765 60766 60767 60768 60769 60770 60771 60772 60773 60774 60775 60776 60777 60778 60779 60780 60781 60782 60783 60784 60785 60786 60787 60788 60789 60790 60791 60792 60793 60794 60795 60796 60797 60798 60799 60800 60801 60802 60803 60804 60805 60806 60807 60808 60809 60810 60811 60812 60813 60814 60815 60816 60817 60818 60819 60820 60821 60822 60823 60824 60825 60826 60827 60828 60829 60830 60831 60832 60833 60834 60835 60836 60837 60838 60839 60840 60841 60842 60843 60844 60845 60846 60847 60848 60849 60850 60851 60852 60853 60854 60855 60856 60857 60858 60859 60860 60861 60862 60863 60864 60865 60866 60867 60868 60869 60870 60871 60872 60873 60874 60875 60876 60877 60878 60879 60880 60881 60882 60883 60884 60885 60886 60887 60888 60889 60890 60891 60892 60893 60894 60895 60896 60897 60898 60899 60900 60901 60902 60903 60904 60905 60906 60907 60908 60909 60910 60911 60912 60913 60914 60915 60916 60917 60918 60919 60920 60921 60922 60923 60924 60925 60926 60927 60928 60929 60930 60931 60932 60933 60934 60935 60936 60937 60938 60939 60940 60941 60942 60943 60944 60945 60946 60947 60948 60949 60950 60951 60952 60953 60954 60955 60956 60957 60958 60959 60960 60961 60962 60963 60964 60965 60966 60967 60968 60969 60970 60971 60972 60973 60974 60975 60976 60977 60978 60979 60980 60981 60982 60983 60984 60985 60986 60987 60988 60989 60990 60991 60992 60993 60994 60995 60996 60997 60998 60999 61000 61001 61002 61003 61004 61005 61006 61007 61008 61009 61010 61011 61012 61013 61014 61015 61016 61017 61018 61019 61020 61021 61022 61023 61024 61025 61026 61027 61028 61029 61030 61031 61032 61033 61034 61035 61036 61037 61038 61039 61040 61041 61042 61043 61044 61045 61046 61047 61048 61049 61050 61051 61052 61053 61054 61055 61056 61057 61058 61059 61060 61061 61062 61063 61064 61065 61066 61067 61068 61069 61070 61071 61072 61073 61074 61075 61076 61077 61078 61079 61080 61081 61082 61083 61084 61085 61086 61087 61088 61089 61090 61091 61092 61093 61094 61095 61096 61097 61098 61099 61100 61101 61102 61103 61104 61105 61106 61107 61108 61109 61110 61111 61112 61113 61114 61115 61116 61117 61118 61119 61120 61121 61122 61123 61124 61125 61126 61127 61128 61129 61130 61131 61132 61133 61134 61135 61136 61137 61138 61139 61140 61141 61142 61143 61144 61145 61146 61147 61148 61149 61150 61151 61152 61153 61154 61155 61156 61157 61158 61159 61160 61161 61162 61163 61164 61165 61166 61167 61168 61169 61170 61171 61172 61173 61174 61175 61176 61177 61178 61179 61180 61181 61182 61183 61184 61185 61186 61187 61188 61189 61190 61191 61192 61193 61194 61195 61196 61197 61198 61199 61200 61201 61202 61203 61204 61205 61206 61207 61208 61209 61210 61211 61212 61213 61214 61215 61216 61217 61218 61219 61220 61221 61222 61223 61224 61225 61226 61227 61228 61229 61230 61231 61232 61233 61234 61235 61236 61237 61238 61239 61240 61241 61242 61243 61244 61245 61246 61247 61248 61249 61250 61251 61252 61253 61254 61255 61256 61257 61258 61259 61260 61261 61262 61263 61264 61265 61266 61267 61268 61269 61270 61271 61272 61273 61274 61275 61276 61277 61278 61279 61280 61281 61282 61283 61284 61285 61286 61287 61288 61289 61290 61291 61292 61293 61294 61295 61296 61297 61298 61299 61300 61301 61302 61303 61304 61305 61306 61307 61308 61309 61310 61311 61312 61313 61314 61315 61316 61317 61318 61319 61320 61321 61322 61323 61324 61325 61326 61327 61328 61329 61330 61331 61332 61333 61334 61335 61336 61337 61338 61339 61340 61341 61342 61343 61344 61345 61346 61347 61348 61349 61350 61351 61352 61353 61354 61355 61356 61357 61358 61359 61360 61361 61362 61363 61364 61365 61366 61367 61368 61369 61370 61371 61372 61373 61374 61375 61376 61377 61378 61379 61380 61381 61382 61383 61384 61385 61386 61387 61388 61389 61390 61391 61392 61393 61394 61395 61396 61397 61398 61399 61400 61401 61402 61403 61404 61405 61406 61407 61408 61409 61410 61411 61412 61413 61414 61415 61416 61417 61418 61419 61420 61421 61422 61423 61424 61425 61426 61427 61428 61429 61430 61431 61432 61433 61434 61435 61436 61437 61438 61439 61440 61441 61442 61443 61444 61445 61446 61447 61448 61449 61450 61451 61452 61453 61454 61455 61456 61457 61458 61459 61460 61461 61462 61463 61464 61465 61466 61467 61468 61469 61470 61471 61472 61473 61474 61475 61476 61477 61478 61479 61480 61481 61482 61483 61484 61485 61486 61487 61488 61489 61490 61491 61492 61493 61494 61495 61496 61497 61498 61499 61500 61501 61502 61503 61504 61505 61506 61507 61508 61509 61510 61511 61512 61513 61514 61515 61516 61517 61518 61519 61520 61521 61522 61523 61524 61525 61526 61527 61528 61529 61530 61531 61532 61533 61534 61535 61536 61537 61538 61539 61540 61541 61542 61543 61544 61545 61546 61547 61548 61549 61550 61551 61552 61553 61554 61555 61556 61557 61558 61559 61560 61561 61562 61563 61564 61565 61566 61567 61568 61569 61570 61571 61572 61573 61574 61575 61576 61577 61578 61579 61580 61581 61582 61583 61584 61585 61586 61587 61588 61589 61590 61591 61592 61593 61594 61595 61596 61597 61598 61599 61600 61601 61602 61603 61604 61605 61606 61607 61608 61609 61610 61611 61612 61613 61614 61615 61616 61617 61618 61619 61620 61621 61622 61623 61624 61625 61626 61627 61628 61629 61630 61631 61632 61633 61634 61635 61636 61637 61638 61639 61640 61641 61642 61643 61644 61645 61646 61647 61648 61649 61650 61651 61652 61653 61654 61655 61656 61657 61658 61659 61660 61661 61662 61663 61664 61665 61666 61667 61668 61669 61670 61671 61672 61673 61674 61675 61676 61677 61678 61679 61680 61681 61682 61683 61684 61685 61686 61687 61688 61689 61690 61691 61692 61693 61694 61695 61696 61697 61698 61699 61700 61701 61702 61703 61704 61705 61706 61707 61708 61709 61710 61711 61712 61713 61714 61715 61716 61717 61718 61719 61720 61721 61722 61723 61724 61725 61726 61727 61728 61729 61730 61731 61732 61733 61734 61735 61736 61737 61738 61739 61740 61741 61742 61743 61744 61745 61746 61747 61748 61749 61750 61751 61752 61753 61754 61755 61756 61757 61758 61759 61760 61761 61762 61763 61764 61765 61766 61767 61768 61769 61770 61771 61772 61773 61774 61775 61776 61777 61778 61779 61780 61781 61782 61783 61784 61785 61786 61787 61788 61789 61790 61791 61792 61793 61794 61795 61796 61797 61798 61799 61800 61801 61802 61803 61804 61805 61806 61807 61808 61809 61810 61811 61812 61813 61814 61815 61816 61817 61818 61819 61820 61821 61822 61823 61824 61825 61826 61827 61828 61829 61830 61831 61832 61833 61834 61835 61836 61837 61838 61839 61840 61841 61842 61843 61844 61845 61846 61847 61848 61849 61850 61851 61852 61853 61854 61855 61856 61857 61858 61859 61860 61861 61862 61863 61864 61865 61866 61867 61868 61869 61870 61871 61872 61873 61874 61875 61876 61877 61878 61879 61880 61881 61882 61883 61884 61885 61886 61887 61888 61889 61890 61891 61892 61893 61894 61895 61896 61897 61898 61899 61900 61901 61902 61903 61904 61905 61906 61907 61908 61909 61910 61911 61912 61913 61914 61915 61916 61917 61918 61919 61920 61921 61922 61923 61924 61925 61926 61927 61928 61929 61930 61931 61932 61933 61934 61935 61936 61937 61938 61939 61940 61941 61942 61943 61944 61945 61946 61947 61948 61949 61950 61951 61952 61953 61954 61955 61956 61957 61958 61959 61960 61961 61962 61963 61964 61965 61966 61967 61968 61969 61970 61971 61972 61973 61974 61975 61976 61977 61978 61979 61980 61981 61982 61983 61984 61985 61986 61987 61988 61989 61990 61991 61992 61993 61994 61995 61996 61997 61998 61999 62000 62001 62002 62003 62004 62005 62006 62007 62008 62009 62010 62011 62012 62013 62014 62015 62016 62017 62018 62019 62020 62021 62022 62023 62024 62025 62026 62027 62028 62029 62030 62031 62032 62033 62034 62035 62036 62037 62038 62039 62040 62041 62042 62043 62044 62045 62046 62047 62048 62049 62050 62051 62052 62053 62054 62055 62056 62057 62058 62059 62060 62061 62062 62063 62064 62065 62066 62067 62068 62069 62070 62071 62072 62073 62074 62075 62076 62077 62078 62079 62080 62081 62082 62083 62084 62085 62086 62087 62088 62089 62090 62091 62092 62093 62094 62095 62096 62097 62098 62099 62100 62101 62102 62103 62104 62105 62106 62107 62108 62109 62110 62111 62112 62113 62114 62115 62116 62117 62118 62119 62120 62121 62122 62123 62124 62125 62126 62127 62128 62129 62130 62131 62132 62133 62134 62135 62136 62137 62138 62139 62140 62141 62142 62143 62144 62145 62146 62147 62148 62149 62150 62151 62152 62153 62154 62155 62156 62157 62158 62159 62160 62161 62162 62163 62164 62165 62166 62167 62168 62169 62170 62171 62172 62173 62174 62175 62176 62177 62178 62179 62180 62181 62182 62183 62184 62185 62186 62187 62188 62189 62190 62191 62192 62193 62194 62195 62196 62197 62198 62199 62200 62201 62202 62203 62204 62205 62206 62207 62208 62209 62210 62211 62212 62213 62214 62215 62216 62217 62218 62219 62220 62221 62222 62223 62224 62225 62226 62227 62228 62229 62230 62231 62232 62233 62234 62235 62236 62237 62238 62239 62240 62241 62242 62243 62244 62245 62246 62247 62248 62249 62250 62251 62252 62253 62254 62255 62256 62257 62258 62259 62260 62261 62262 62263 62264 62265 62266 62267 62268 62269 62270 62271 62272 62273 62274 62275 62276 62277 62278 62279 62280 62281 62282 62283 62284 62285 62286 62287 62288 62289 62290 62291 62292 62293 62294 62295 62296 62297 62298 62299 62300 62301 62302 62303 62304 62305 62306 62307 62308 62309 62310 62311 62312 62313 62314 62315 62316 62317 62318 62319 62320 62321 62322 62323 62324 62325 62326 62327 62328 62329 62330 62331 62332 62333 62334 62335 62336 62337 62338 62339 62340 62341 62342 62343 62344 62345 62346 62347 62348 62349 62350 62351 62352 62353 62354 62355 62356 62357 62358 62359 62360 62361 62362 62363 62364 62365 62366 62367 62368 62369 62370 62371 62372 62373 62374 62375 62376 62377 62378 62379 62380 62381 62382 62383 62384 62385 62386 62387 62388 62389 62390 62391 62392 62393 62394 62395 62396 62397 62398 62399 62400 62401 62402 62403 62404 62405 62406 62407 62408 62409 62410 62411 62412 62413 62414 62415 62416 62417 62418 62419 62420 62421 62422 62423 62424 62425 62426 62427 62428 62429 62430 62431 62432 62433 62434 62435 62436 62437 62438 62439 62440 62441 62442 62443 62444 62445 62446 62447 62448 62449 62450 62451 62452 62453 62454 62455 62456 62457 62458 62459 62460 62461 62462 62463 62464 62465 62466 62467 62468 62469 62470 62471 62472 62473 62474 62475 62476 62477 62478 62479 62480 62481 62482 62483 62484 62485 62486 62487 62488 62489 62490 62491 62492 62493 62494 62495 62496 62497 62498 62499 62500 62501 62502 62503 62504 62505 62506 62507 62508 62509 62510 62511 62512 62513 62514 62515 62516 62517 62518 62519 62520 62521 62522 62523 62524 62525 62526 62527 62528 62529 62530 62531 62532 62533 62534 62535 62536 62537 62538 62539 62540 62541 62542 62543 62544 62545 62546 62547 62548 62549 62550 62551 62552 62553 62554 62555 62556 62557 62558 62559 62560 62561 62562 62563 62564 62565 62566 62567 62568 62569 62570 62571 62572 62573 62574 62575 62576 62577 62578 62579 62580 62581 62582 62583 62584 62585 62586 62587 62588 62589 62590 62591 62592 62593 62594 62595 62596 62597 62598 62599 62600 62601 62602 62603 62604 62605 62606 62607 62608 62609 62610 62611 62612 62613 62614 62615 62616 62617 62618 62619 62620 62621 62622 62623 62624 62625 62626 62627 62628 62629 62630 62631 62632 62633 62634 62635 62636 62637 62638 62639 62640 62641 62642 62643 62644 62645 62646 62647 62648 62649 62650 62651 62652 62653 62654 62655 62656 62657 62658 62659 62660 62661 62662 62663 62664 62665 62666 62667 62668 62669 62670 62671 62672 62673 62674 62675 62676 62677 62678 62679 62680 62681 62682 62683 62684 62685 62686 62687 62688 62689 62690 62691 62692 62693 62694 62695 62696 62697 62698 62699 62700 62701 62702 62703 62704 62705 62706 62707 62708 62709 62710 62711 62712 62713 62714 62715 62716 62717 62718 62719 62720 62721 62722 62723 62724 62725 62726 62727 62728 62729 62730 62731 62732 62733 62734 62735 62736 62737 62738 62739 62740 62741 62742 62743 62744 62745 62746 62747 62748 62749 62750 62751 62752 62753 62754 62755 62756 62757 62758 62759 62760 62761 62762 62763 62764 62765 62766 62767 62768 62769 62770 62771 62772 62773 62774 62775 62776 62777 62778 62779 62780 62781 62782 62783 62784 62785 62786 62787 62788 62789 62790 62791 62792 62793 62794 62795 62796 62797 62798 62799 62800 62801 62802 62803 62804 62805 62806 62807 62808 62809 62810 62811 62812 62813 62814 62815 62816 62817 62818 62819 62820 62821 62822 62823 62824 62825 62826 62827 62828 62829 62830 62831 62832 62833 62834 62835 62836 62837 62838 62839 62840 62841 62842 62843 62844 62845 62846 62847 62848 62849 62850 62851 62852 62853 62854 62855 62856 62857 62858 62859 62860 62861 62862 62863 62864 62865 62866 62867 62868 62869 62870 62871 62872 62873 62874 62875 62876 62877 62878 62879 62880 62881 62882 62883 62884 62885 62886 62887 62888 62889 62890 62891 62892 62893 62894 62895 62896 62897 62898 62899 62900 62901 62902 62903 62904 62905 62906 62907 62908 62909 62910 62911 62912 62913 62914 62915 62916 62917 62918 62919 62920 62921 62922 62923 62924 62925 62926 62927 62928 62929 62930 62931 62932 62933 62934 62935 62936 62937 62938 62939 62940 62941 62942 62943 62944 62945 62946 62947 62948 62949 62950 62951 62952 62953 62954 62955 62956 62957 62958 62959 62960 62961 62962 62963 62964 62965 62966 62967 62968 62969 62970 62971 62972 62973 62974 62975 62976 62977 62978 62979 62980 62981 62982 62983 62984 62985 62986 62987 62988 62989 62990 62991 62992 62993 62994 62995 62996 62997 62998 62999 63000 63001 63002 63003 63004 63005 63006 63007 63008 63009 63010 63011 63012 63013 63014 63015 63016 63017 63018 63019 63020 63021 63022 63023 63024 63025 63026 63027 63028 63029 63030 63031 63032 63033 63034 63035 63036 63037 63038 63039 63040 63041 63042 63043 63044 63045 63046 63047 63048 63049 63050 63051 63052 63053 63054 63055 63056 63057 63058 63059 63060 63061 63062 63063 63064 63065 63066 63067 63068 63069 63070 63071 63072 63073 63074 63075 63076 63077 63078 63079 63080 63081 63082 63083 63084 63085 63086 63087 63088 63089 63090 63091 63092 63093 63094 63095 63096 63097 63098 63099 63100 63101 63102 63103 63104 63105 63106 63107 63108 63109 63110 63111 63112 63113 63114 63115 63116 63117 63118 63119 63120 63121 63122 63123 63124 63125 63126 63127 63128 63129 63130 63131 63132 63133 63134 63135 63136 63137 63138 63139 63140 63141 63142 63143 63144 63145 63146 63147 63148 63149 63150 63151 63152 63153 63154 63155 63156 63157 63158 63159 63160 63161 63162 63163 63164 63165 63166 63167 63168 63169 63170 63171 63172 63173 63174 63175 63176 63177 63178 63179 63180 63181 63182 63183 63184 63185 63186 63187 63188 63189 63190 63191 63192 63193 63194 63195 63196 63197 63198 63199 63200 63201 63202 63203 63204 63205 63206 63207 63208 63209 63210 63211 63212 63213 63214 63215 63216 63217 63218 63219 63220 63221 63222 63223 63224 63225 63226 63227 63228 63229 63230 63231 63232 63233 63234 63235 63236 63237 63238 63239 63240 63241 63242 63243 63244 63245 63246 63247 63248 63249 63250 63251 63252 63253 63254 63255 63256 63257 63258 63259 63260 63261 63262 63263 63264 63265 63266 63267 63268 63269 63270 63271 63272 63273 63274 63275 63276 63277 63278 63279 63280 63281 63282 63283 63284 63285 63286 63287 63288 63289 63290 63291 63292 63293 63294 63295 63296 63297 63298 63299 63300 63301 63302 63303 63304 63305 63306 63307 63308 63309 63310 63311 63312 63313 63314 63315 63316 63317 63318 63319 63320 63321 63322 63323 63324 63325 63326 63327 63328 63329 63330 63331 63332 63333 63334 63335 63336 63337 63338 63339 63340 63341 63342 63343 63344 63345 63346 63347 63348 63349 63350 63351 63352 63353 63354 63355 63356 63357 63358 63359 63360 63361 63362 63363 63364 63365 63366 63367 63368 63369 63370 63371 63372 63373 63374 63375 63376 63377 63378 63379 63380 63381 63382 63383 63384 63385 63386 63387 63388 63389 63390 63391 63392 63393 63394 63395 63396 63397 63398 63399 63400 63401 63402 63403 63404 63405 63406 63407 63408 63409 63410 63411 63412 63413 63414 63415 63416 63417 63418 63419 63420 63421 63422 63423 63424 63425 63426 63427 63428 63429 63430 63431 63432 63433 63434 63435 63436 63437 63438 63439 63440 63441 63442 63443 63444 63445 63446 63447 63448 63449 63450 63451 63452 63453 63454 63455 63456 63457 63458 63459 63460 63461 63462 63463 63464 63465 63466 63467 63468 63469 63470 63471 63472 63473 63474 63475 63476 63477 63478 63479 63480 63481 63482 63483 63484 63485 63486 63487 63488 63489 63490 63491 63492 63493 63494 63495 63496 63497 63498 63499 63500 63501 63502 63503 63504 63505 63506 63507 63508 63509 63510 63511 63512 63513 63514 63515 63516 63517 63518 63519 63520 63521 63522 63523 63524 63525 63526 63527 63528 63529 63530 63531 63532 63533 63534 63535 63536 63537 63538 63539 63540 63541 63542 63543 63544 63545 63546 63547 63548 63549 63550 63551 63552 63553 63554 63555 63556 63557 63558 63559 63560 63561 63562 63563 63564 63565 63566 63567 63568 63569 63570 63571 63572 63573 63574 63575 63576 63577 63578 63579 63580 63581 63582 63583 63584 63585 63586 63587 63588 63589 63590 63591 63592 63593 63594 63595 63596 63597 63598 63599 63600 63601 63602 63603 63604 63605 63606 63607 63608 63609 63610 63611 63612 63613 63614 63615 63616 63617 63618 63619 63620 63621 63622 63623 63624 63625 63626 63627 63628 63629 63630 63631 63632 63633 63634 63635 63636 63637 63638 63639 63640 63641 63642 63643 63644 63645 63646 63647 63648 63649 63650 63651 63652 63653 63654 63655 63656 63657 63658 63659 63660 63661 63662 63663 63664 63665 63666 63667 63668 63669 63670 63671 63672 63673 63674 63675 63676 63677 63678 63679 63680 63681 63682 63683 63684 63685 63686 63687 63688 63689 63690 63691 63692 63693 63694 63695 63696 63697 63698 63699 63700 63701 63702 63703 63704 63705 63706 63707 63708 63709 63710 63711 63712 63713 63714 63715 63716 63717 63718 63719 63720 63721 63722 63723 63724 63725 63726 63727 63728 63729 63730 63731 63732 63733 63734 63735 63736 63737 63738 63739 63740 63741 63742 63743 63744 63745 63746 63747 63748 63749 63750 63751 63752 63753 63754 63755 63756 63757 63758 63759 63760 63761 63762 63763 63764 63765 63766 63767 63768 63769 63770 63771 63772 63773 63774 63775 63776 63777 63778 63779 63780 63781 63782 63783 63784 63785 63786 63787 63788 63789 63790 63791 63792 63793 63794 63795 63796 63797 63798 63799 63800 63801 63802 63803 63804 63805 63806 63807 63808 63809 63810 63811 63812 63813 63814 63815 63816 63817 63818 63819 63820 63821 63822 63823 63824 63825 63826 63827 63828 63829 63830 63831 63832 63833 63834 63835 63836 63837 63838 63839 63840 63841 63842 63843 63844 63845 63846 63847 63848 63849 63850 63851 63852 63853 63854 63855 63856 63857 63858 63859 63860 63861 63862 63863 63864 63865 63866 63867 63868 63869 63870 63871 63872 63873 63874 63875 63876 63877 63878 63879 63880 63881 63882 63883 63884 63885 63886 63887 63888 63889 63890 63891 63892 63893 63894 63895 63896 63897 63898 63899 63900 63901 63902 63903 63904 63905 63906 63907 63908 63909 63910 63911 63912 63913 63914 63915 63916 63917 63918 63919 63920 63921 63922 63923 63924 63925 63926 63927 63928 63929 63930 63931 63932 63933 63934 63935 63936 63937 63938 63939 63940 63941 63942 63943 63944 63945 63946 63947 63948 63949 63950 63951 63952 63953 63954 63955 63956 63957 63958 63959 63960 63961 63962 63963 63964 63965 63966 63967 63968 63969 63970 63971 63972 63973 63974 63975 63976 63977 63978 63979 63980 63981 63982 63983 63984 63985 63986 63987 63988 63989 63990 63991 63992 63993 63994 63995 63996 63997 63998 63999 64000 64001 64002 64003 64004 64005 64006 64007 64008 64009 64010 64011 64012 64013 64014 64015 64016 64017 64018 64019 64020 64021 64022 64023 64024 64025 64026 64027 64028 64029 64030 64031 64032 64033 64034 64035 64036 64037 64038 64039 64040 64041 64042 64043 64044 64045 64046 64047 64048 64049 64050 64051 64052 64053 64054 64055 64056 64057 64058 64059 64060 64061 64062 64063 64064 64065 64066 64067 64068 64069 64070 64071 64072 64073 64074 64075 64076 64077 64078 64079 64080 64081 64082 64083 64084 64085 64086 64087 64088 64089 64090 64091 64092 64093 64094 64095 64096 64097 64098 64099 64100 64101 64102 64103 64104 64105 64106 64107 64108 64109 64110 64111 64112 64113 64114 64115 64116 64117 64118 64119 64120 64121 64122 64123 64124 64125 64126 64127 64128 64129 64130 64131 64132 64133 64134 64135 64136 64137 64138 64139 64140 64141 64142 64143 64144 64145 64146 64147 64148 64149 64150 64151 64152 64153 64154 64155 64156 64157 64158 64159 64160 64161 64162 64163 64164 64165 64166 64167 64168 64169 64170 64171 64172 64173 64174 64175 64176 64177 64178 64179 64180 64181 64182 64183 64184 64185 64186 64187 64188 64189 64190 64191 64192 64193 64194 64195 64196 64197 64198 64199 64200 64201 64202 64203 64204 64205 64206 64207 64208 64209 64210 64211 64212 64213 64214 64215 64216 64217 64218 64219 64220 64221 64222 64223 64224 64225 64226 64227 64228 64229 64230 64231 64232 64233 64234 64235 64236 64237 64238 64239 64240 64241 64242 64243 64244 64245 64246 64247 64248 64249 64250 64251 64252 64253 64254 64255 64256 64257 64258 64259 64260 64261 64262 64263 64264 64265 64266 64267 64268 64269 64270 64271 64272 64273 64274 64275 64276 64277 64278 64279 64280 64281 64282 64283 64284 64285 64286 64287 64288 64289 64290 64291 64292 64293 64294 64295 64296 64297 64298 64299 64300 64301 64302 64303 64304 64305 64306 64307 64308 64309 64310 64311 64312 64313 64314 64315 64316 64317 64318 64319 64320 64321 64322 64323 64324 64325 64326 64327 64328 64329 64330 64331 64332 64333 64334 64335 64336 64337 64338 64339 64340 64341 64342 64343 64344 64345 64346 64347 64348 64349 64350 64351 64352 64353 64354 64355 64356 64357 64358 64359 64360 64361 64362 64363 64364 64365 64366 64367 64368 64369 64370 64371 64372 64373 64374 64375 64376 64377 64378 64379 64380 64381 64382 64383 64384 64385 64386 64387 64388 64389 64390 64391 64392 64393 64394 64395 64396 64397 64398 64399 64400 64401 64402 64403 64404 64405 64406 64407 64408 64409 64410 64411 64412 64413 64414 64415 64416 64417 64418 64419 64420 64421 64422 64423 64424 64425 64426 64427 64428 64429 64430 64431 64432 64433 64434 64435 64436 64437 64438 64439 64440 64441 64442 64443 64444 64445 64446 64447 64448 64449 64450 64451 64452 64453 64454 64455 64456 64457 64458 64459 64460 64461 64462 64463 64464 64465 64466 64467 64468 64469 64470 64471 64472 64473 64474 64475 64476 64477 64478 64479 64480 64481 64482 64483 64484 64485 64486 64487 64488 64489 64490 64491 64492 64493 64494 64495 64496 64497 64498 64499 64500 64501 64502 64503 64504 64505 64506 64507 64508 64509 64510 64511 64512 64513 64514 64515 64516 64517 64518 64519 64520 64521 64522 64523 64524 64525 64526 64527 64528 64529 64530 64531 64532 64533 64534 64535 64536 64537 64538 64539 64540 64541 64542 64543 64544 64545 64546 64547 64548 64549 64550 64551 64552 64553 64554 64555 64556 64557 64558 64559 64560 64561 64562 64563 64564 64565 64566 64567 64568 64569 64570 64571 64572 64573 64574 64575 64576 64577 64578 64579 64580 64581 64582 64583 64584 64585 64586 64587 64588 64589 64590 64591 64592 64593 64594 64595 64596 64597 64598 64599 64600 64601 64602 64603 64604 64605 64606 64607 64608 64609 64610 64611 64612 64613 64614 64615 64616 64617 64618 64619 64620 64621 64622 64623 64624 64625 64626 64627 64628 64629 64630 64631 64632 64633 64634 64635 64636 64637 64638 64639 64640 64641 64642 64643 64644 64645 64646 64647 64648 64649 64650 64651 64652 64653 64654 64655 64656 64657 64658 64659 64660 64661 64662 64663 64664 64665 64666 64667 64668 64669 64670 64671 64672 64673 64674 64675 64676 64677 64678 64679 64680 64681 64682 64683 64684 64685 64686 64687 64688 64689 64690 64691 64692 64693 64694 64695 64696 64697 64698 64699 64700 64701 64702 64703 64704 64705 64706 64707 64708 64709 64710 64711 64712 64713 64714 64715 64716 64717 64718 64719 64720 64721 64722 64723 64724 64725 64726 64727 64728 64729 64730 64731 64732 64733 64734 64735 64736 64737 64738 64739 64740 64741 64742 64743 64744 64745 64746 64747 64748 64749 64750 64751 64752 64753 64754 64755 64756 64757 64758 64759 64760 64761 64762 64763 64764 64765 64766 64767 64768 64769 64770 64771 64772 64773 64774 64775 64776 64777 64778 64779 64780 64781 64782 64783 64784 64785 64786 64787 64788 64789 64790 64791 64792 64793 64794 64795 64796 64797 64798 64799 64800 64801 64802 64803 64804 64805 64806 64807 64808 64809 64810 64811 64812 64813 64814 64815 64816 64817 64818 64819 64820 64821 64822 64823 64824 64825 64826 64827 64828 64829 64830 64831 64832 64833 64834 64835 64836 64837 64838 64839 64840 64841 64842 64843 64844 64845 64846 64847 64848 64849 64850 64851 64852 64853 64854 64855 64856 64857 64858 64859 64860 64861 64862 64863 64864 64865 64866 64867 64868 64869 64870 64871 64872 64873 64874 64875 64876 64877 64878 64879 64880 64881 64882 64883 64884 64885 64886 64887 64888 64889 64890 64891 64892 64893 64894 64895 64896 64897 64898 64899 64900 64901 64902 64903 64904 64905 64906 64907 64908 64909 64910 64911 64912 64913 64914 64915 64916 64917 64918 64919 64920 64921 64922 64923 64924 64925 64926 64927 64928 64929 64930 64931 64932 64933 64934 64935 64936 64937 64938 64939 64940 64941 64942 64943 64944 64945 64946 64947 64948 64949 64950 64951 64952 64953 64954 64955 64956 64957 64958 64959 64960 64961 64962 64963 64964 64965 64966 64967 64968 64969 64970 64971 64972 64973 64974 64975 64976 64977 64978 64979 64980 64981 64982 64983 64984 64985 64986 64987 64988 64989 64990 64991 64992 64993 64994 64995 64996 64997 64998 64999 65000 65001 65002 65003 65004 65005 65006 65007 65008 65009 65010 65011 65012 65013 65014 65015 65016 65017 65018 65019 65020 65021 65022 65023 65024 65025 65026 65027 65028 65029 65030 65031 65032 65033 65034 65035 65036 65037 65038 65039 65040 65041 65042 65043 65044 65045 65046 65047 65048 65049 65050 65051 65052 65053 65054 65055 65056 65057 65058 65059 65060 65061 65062 65063 65064 65065 65066 65067 65068 65069 65070 65071 65072 65073 65074 65075 65076 65077 65078 65079 65080 65081 65082 65083 65084 65085 65086 65087 65088 65089 65090 65091 65092 65093 65094 65095 65096 65097 65098 65099 65100 65101 65102 65103 65104 65105 65106 65107 65108 65109 65110 65111 65112 65113 65114 65115 65116 65117 65118 65119 65120 65121 65122 65123 65124 65125 65126 65127 65128 65129 65130 65131 65132 65133 65134 65135 65136 65137 65138 65139 65140 65141 65142 65143 65144 65145 65146 65147 65148 65149 65150 65151 65152 65153 65154 65155 65156 65157 65158 65159 65160 65161 65162 65163 65164 65165 65166 65167 65168 65169 65170 65171 65172 65173 65174 65175 65176 65177 65178 65179 65180 65181 65182 65183 65184 65185 65186 65187 65188 65189 65190 65191 65192 65193 65194 65195 65196 65197 65198 65199 65200 65201 65202 65203 65204 65205 65206 65207 65208 65209 65210 65211 65212 65213 65214 65215 65216 65217 65218 65219 65220 65221 65222 65223 65224 65225 65226 65227 65228 65229 65230 65231 65232 65233 65234 65235 65236 65237 65238 65239 65240 65241 65242 65243 65244 65245 65246 65247 65248 65249 65250 65251 65252 65253 65254 65255 65256 65257 65258 65259 65260 65261 65262 65263 65264 65265 65266 65267 65268 65269 65270 65271 65272 65273 65274 65275 65276 65277 65278 65279 65280 65281 65282 65283 65284 65285 65286 65287 65288 65289 65290 65291 65292 65293 65294 65295 65296 65297 65298 65299 65300 65301 65302 65303 65304 65305 65306 65307 65308 65309 65310 65311 65312 65313 65314 65315 65316 65317 65318 65319 65320 65321 65322 65323 65324 65325 65326 65327 65328 65329 65330 65331 65332 65333 65334 65335 65336 65337 65338 65339 65340 65341 65342 65343 65344 65345 65346 65347 65348 65349 65350 65351 65352 65353 65354 65355 65356 65357 65358 65359 65360 65361 65362 65363 65364 65365 65366 65367 65368 65369 65370 65371 65372 65373 65374 65375 65376 65377 65378 65379 65380 65381 65382 65383 65384 65385 65386 65387 65388 65389 65390 65391 65392 65393 65394 65395 65396 65397 65398 65399 65400 65401 65402 65403 65404 65405 65406 65407 65408 65409 65410 65411 65412 65413 65414 65415 65416 65417 65418 65419 65420 65421 65422 65423 65424 65425 65426 65427 65428 65429 65430 65431 65432 65433 65434 65435 65436 65437 65438 65439 65440 65441 65442 65443 65444 65445 65446 65447 65448 65449 65450 65451 65452 65453 65454 65455 65456 65457 65458 65459 65460 65461 65462 65463 65464 65465 65466 65467 65468 65469 65470 65471 65472 65473 65474 65475 65476 65477 65478 65479 65480 65481 65482 65483 65484 65485 65486 65487 65488 65489 65490 65491 65492 65493 65494 65495 65496 65497 65498 65499 65500 65501 65502 65503 65504 65505 65506 65507 65508 65509 65510 65511 65512 65513 65514 65515 65516 65517 65518 65519 65520 65521 65522 65523 65524 65525 65526 65527 65528 65529 65530 65531 65532 65533 65534 65535 65536 65537 65538 65539 65540 65541 65542 65543 65544 65545 65546 65547 65548 65549 65550 65551 65552 65553 65554 65555 65556 65557 65558 65559 65560 65561 65562 65563 65564 65565 65566 65567 65568 65569 65570 65571 65572 65573 65574 65575 65576 65577 65578 65579 65580 65581 65582 65583 65584 65585 65586 65587 65588 65589 65590 65591 65592 65593 65594 65595 65596 65597 65598 65599 65600 65601 65602 65603 65604 65605 65606 65607 65608 65609 65610 65611 65612 65613 65614 65615 65616 65617 65618 65619 65620 65621 65622 65623 65624 65625 65626 65627 65628 65629 65630 65631 65632 65633 65634 65635 65636 65637 65638 65639 65640 65641 65642 65643 65644 65645 65646 65647 65648 65649 65650 65651 65652 65653 65654 65655 65656 65657 65658 65659 65660 65661 65662 65663 65664 65665 65666 65667 65668 65669 65670 65671 65672 65673 65674 65675 65676 65677 65678 65679 65680 65681 65682 65683 65684 65685 65686 65687 65688 65689 65690 65691 65692 65693 65694 65695 65696 65697 65698 65699 65700 65701 65702 65703 65704 65705 65706 65707 65708 65709 65710 65711 65712 65713 65714 65715 65716 65717 65718 65719 65720 65721 65722 65723 65724 65725 65726 65727 65728 65729 65730 65731 65732 65733 65734 65735 65736 65737 65738 65739 65740 65741 65742 65743 65744 65745 65746 65747 65748 65749 65750 65751 65752 65753 65754 65755 65756 65757 65758 65759 65760 65761 65762 65763 65764 65765 65766 65767 65768 65769 65770 65771 65772 65773 65774 65775 65776 65777 65778 65779 65780 65781 65782 65783 65784 65785 65786 65787 65788 65789 65790 65791 65792 65793 65794 65795 65796 65797 65798 65799 65800 65801 65802 65803 65804 65805 65806 65807 65808 65809 65810 65811 65812 65813 65814 65815 65816 65817 65818 65819 65820 65821 65822 65823 65824 65825 65826 65827 65828 65829 65830 65831 65832 65833 65834 65835 65836 65837 65838 65839 65840 65841 65842 65843 65844 65845 65846 65847 65848 65849 65850 65851 65852 65853 65854 65855 65856 65857 65858 65859 65860 65861 65862 65863 65864 65865 65866 65867 65868 65869 65870 65871 65872 65873 65874 65875 65876 65877 65878 65879 65880 65881 65882 65883 65884 65885 65886 65887 65888 65889 65890 65891 65892 65893 65894 65895 65896 65897 65898 65899 65900 65901 65902 65903 65904 65905 65906 65907 65908 65909 65910 65911 65912 65913 65914 65915 65916 65917 65918 65919 65920 65921 65922 65923 65924 65925 65926 65927 65928 65929 65930 65931 65932 65933 65934 65935 65936 65937 65938 65939 65940 65941 65942 65943 65944 65945 65946 65947 65948 65949 65950 65951 65952 65953 65954 65955 65956 65957 65958 65959 65960 65961 65962 65963 65964 65965 65966 65967 65968 65969 65970 65971 65972 65973 65974 65975 65976 65977 65978 65979 65980 65981 65982 65983 65984 65985 65986 65987 65988 65989 65990 65991 65992 65993 65994 65995 65996 65997 65998 65999 66000 66001 66002 66003 66004 66005 66006 66007 66008 66009 66010 66011 66012 66013 66014 66015 66016 66017 66018 66019 66020 66021 66022 66023 66024 66025 66026 66027 66028 66029 66030 66031 66032 66033 66034 66035 66036 66037 66038 66039 66040 66041 66042 66043 66044 66045 66046 66047 66048 66049 66050 66051 66052 66053 66054 66055 66056 66057 66058 66059 66060 66061 66062 66063 66064 66065 66066 66067 66068 66069 66070 66071 66072 66073 66074 66075 66076 66077 66078 66079 66080 66081 66082 66083 66084 66085 66086 66087 66088 66089 66090 66091 66092 66093 66094 66095 66096 66097 66098 66099 66100 66101 66102 66103 66104 66105 66106 66107 66108 66109 66110 66111 66112 66113 66114 66115 66116 66117 66118 66119 66120 66121 66122 66123 66124 66125 66126 66127 66128 66129 66130 66131 66132 66133 66134 66135 66136 66137 66138 66139 66140 66141 66142 66143 66144 66145 66146 66147 66148 66149 66150 66151 66152 66153 66154 66155 66156 66157 66158 66159 66160 66161 66162 66163 66164 66165 66166 66167 66168 66169 66170 66171 66172 66173 66174 66175 66176 66177 66178 66179 66180 66181 66182 66183 66184 66185 66186 66187 66188 66189 66190 66191 66192 66193 66194 66195 66196 66197 66198 66199 66200 66201 66202 66203 66204 66205 66206 66207 66208 66209 66210 66211 66212 66213 66214 66215 66216 66217 66218 66219 66220 66221 66222 66223 66224 66225 66226 66227 66228 66229 66230 66231 66232 66233 66234 66235 66236 66237 66238 66239 66240 66241 66242 66243 66244 66245 66246 66247 66248 66249 66250 66251 66252 66253 66254 66255 66256 66257 66258 66259 66260 66261 66262 66263 66264 66265 66266 66267 66268 66269 66270 66271 66272 66273 66274 66275 66276 66277 66278 66279 66280 66281 66282 66283 66284 66285 66286 66287 66288 66289 66290 66291 66292 66293 66294 66295 66296 66297 66298 66299 66300 66301 66302 66303 66304 66305 66306 66307 66308 66309 66310 66311 66312 66313 66314 66315 66316 66317 66318 66319 66320 66321 66322 66323 66324 66325 66326 66327 66328 66329 66330 66331 66332 66333 66334 66335 66336 66337 66338 66339 66340 66341 66342 66343 66344 66345 66346 66347 66348 66349 66350 66351 66352 66353 66354 66355 66356 66357 66358 66359 66360 66361 66362 66363 66364 66365 66366 66367 66368 66369 66370 66371 66372 66373 66374 66375 66376 66377 66378 66379 66380 66381 66382 66383 66384 66385 66386 66387 66388 66389 66390 66391 66392 66393 66394 66395 66396 66397 66398 66399 66400 66401 66402 66403 66404 66405 66406 66407 66408 66409 66410 66411 66412 66413 66414 66415 66416 66417 66418 66419 66420 66421 66422 66423 66424 66425 66426 66427 66428 66429 66430 66431 66432 66433 66434 66435 66436 66437 66438 66439 66440 66441 66442 66443 66444 66445 66446 66447 66448 66449 66450 66451 66452 66453 66454 66455 66456 66457 66458 66459 66460 66461 66462 66463 66464 66465 66466 66467 66468 66469 66470 66471 66472 66473 66474 66475 66476 66477 66478 66479 66480 66481 66482 66483 66484 66485 66486 66487 66488 66489 66490 66491 66492 66493 66494 66495 66496 66497 66498 66499 66500 66501 66502 66503 66504 66505 66506 66507 66508 66509 66510 66511 66512 66513 66514 66515 66516 66517 66518 66519 66520 66521 66522 66523 66524 66525 66526 66527 66528 66529 66530 66531 66532 66533 66534 66535 66536 66537 66538 66539 66540 66541 66542 66543 66544 66545 66546 66547 66548 66549 66550 66551 66552 66553 66554 66555 66556 66557 66558 66559 66560 66561 66562 66563 66564 66565 66566 66567 66568 66569 66570 66571 66572 66573 66574 66575 66576 66577 66578 66579 66580 66581 66582 66583 66584 66585 66586 66587 66588 66589 66590 66591 66592 66593 66594 66595 66596 66597 66598 66599 66600 66601 66602 66603 66604 66605 66606 66607 66608 66609 66610 66611 66612 66613 66614 66615 66616 66617 66618 66619 66620 66621 66622 66623 66624 66625 66626 66627 66628 66629 66630 66631 66632 66633 66634 66635 66636 66637 66638 66639 66640 66641 66642 66643 66644 66645 66646 66647 66648 66649 66650 66651 66652 66653 66654 66655 66656 66657 66658 66659 66660 66661 66662 66663 66664 66665 66666 66667 66668 66669 66670 66671 66672 66673 66674 66675 66676 66677 66678 66679 66680 66681 66682 66683 66684 66685 66686 66687 66688 66689 66690 66691 66692 66693 66694 66695 66696 66697 66698 66699 66700 66701 66702 66703 66704 66705 66706 66707 66708 66709 66710 66711 66712 66713 66714 66715 66716 66717 66718 66719 66720 66721 66722 66723 66724 66725 66726 66727 66728 66729 66730 66731 66732 66733 66734 66735 66736 66737 66738 66739 66740 66741 66742 66743 66744 66745 66746 66747 66748 66749 66750 66751 66752 66753 66754 66755 66756 66757 66758 66759 66760 66761 66762 66763 66764 66765 66766 66767 66768 66769 66770 66771 66772 66773 66774 66775 66776 66777 66778 66779 66780 66781 66782 66783 66784 66785 66786 66787 66788 66789 66790 66791 66792 66793 66794 66795 66796 66797 66798 66799 66800 66801 66802 66803 66804 66805 66806 66807 66808 66809 66810 66811 66812 66813 66814 66815 66816 66817 66818 66819 66820 66821 66822 66823 66824 66825 66826 66827 66828 66829 66830 66831 66832 66833 66834 66835 66836 66837 66838 66839 66840 66841 66842 66843 66844 66845 66846 66847 66848 66849 66850 66851 66852 66853 66854 66855 66856 66857 66858 66859 66860 66861 66862 66863 66864 66865 66866 66867 66868 66869 66870 66871 66872 66873 66874 66875 66876 66877 66878 66879 66880 66881 66882 66883 66884 66885 66886 66887 66888 66889 66890 66891 66892 66893 66894 66895 66896 66897 66898 66899 66900 66901 66902 66903 66904 66905 66906 66907 66908 66909 66910 66911 66912 66913 66914 66915 66916 66917 66918 66919 66920 66921 66922 66923 66924 66925 66926 66927 66928 66929 66930 66931 66932 66933 66934 66935 66936 66937 66938 66939 66940 66941 66942 66943 66944 66945 66946 66947 66948 66949 66950 66951 66952 66953 66954 66955 66956 66957 66958 66959 66960 66961 66962 66963 66964 66965 66966 66967 66968 66969 66970 66971 66972 66973 66974 66975 66976 66977 66978 66979 66980 66981 66982 66983 66984 66985 66986 66987 66988 66989 66990 66991 66992 66993 66994 66995 66996 66997 66998 66999 67000 67001 67002 67003 67004 67005 67006 67007 67008 67009 67010 67011 67012 67013 67014 67015 67016 67017 67018 67019 67020 67021 67022 67023 67024 67025 67026 67027 67028 67029 67030 67031 67032 67033 67034 67035 67036 67037 67038 67039 67040 67041 67042 67043 67044 67045 67046 67047 67048 67049 67050 67051 67052 67053 67054 67055 67056 67057 67058 67059 67060 67061 67062 67063 67064 67065 67066 67067 67068 67069 67070 67071 67072 67073 67074 67075 67076 67077 67078 67079 67080 67081 67082 67083 67084 67085 67086 67087 67088 67089 67090 67091 67092 67093 67094 67095 67096 67097 67098 67099 67100 67101 67102 67103 67104 67105 67106 67107 67108 67109 67110 67111 67112 67113 67114 67115 67116 67117 67118 67119 67120 67121 67122 67123 67124 67125 67126 67127 67128 67129 67130 67131 67132 67133 67134 67135 67136 67137 67138 67139 67140 67141 67142 67143 67144 67145 67146 67147 67148 67149 67150 67151 67152 67153 67154 67155 67156 67157 67158 67159 67160 67161 67162 67163 67164 67165 67166 67167 67168 67169 67170 67171 67172 67173 67174 67175 67176 67177 67178 67179 67180 67181 67182 67183 67184 67185 67186 67187 67188 67189 67190 67191 67192 67193 67194 67195 67196 67197 67198 67199 67200 67201 67202 67203 67204 67205 67206 67207 67208 67209 67210 67211 67212 67213 67214 67215 67216 67217 67218 67219 67220 67221 67222 67223 67224 67225 67226 67227 67228 67229 67230 67231 67232 67233 67234 67235 67236 67237 67238 67239 67240 67241 67242 67243 67244 67245 67246 67247 67248 67249 67250 67251 67252 67253 67254 67255 67256 67257 67258 67259 67260 67261 67262 67263 67264 67265 67266 67267 67268 67269 67270 67271 67272 67273 67274 67275 67276 67277 67278 67279 67280 67281 67282 67283 67284 67285 67286 67287 67288 67289 67290 67291 67292 67293 67294 67295 67296 67297 67298 67299 67300 67301 67302 67303 67304 67305 67306 67307 67308 67309 67310 67311 67312 67313 67314 67315 67316 67317 67318 67319 67320 67321 67322 67323 67324 67325 67326 67327 67328 67329 67330 67331 67332 67333 67334 67335 67336 67337 67338 67339 67340 67341 67342 67343 67344 67345 67346 67347 67348 67349 67350 67351 67352 67353 67354 67355 67356 67357 67358 67359 67360 67361 67362 67363 67364 67365 67366 67367 67368 67369 67370 67371 67372 67373 67374 67375 67376 67377 67378 67379 67380 67381 67382 67383 67384 67385 67386 67387 67388 67389 67390 67391 67392 67393 67394 67395 67396 67397 67398 67399 67400 67401 67402 67403 67404 67405 67406 67407 67408 67409 67410 67411 67412 67413 67414 67415 67416 67417 67418 67419 67420 67421 67422 67423 67424 67425 67426 67427 67428 67429 67430 67431 67432 67433 67434 67435 67436 67437 67438 67439 67440 67441 67442 67443 67444 67445 67446 67447 67448 67449 67450 67451 67452 67453 67454 67455 67456 67457 67458 67459 67460 67461 67462 67463 67464 67465 67466 67467 67468 67469 67470 67471 67472 67473 67474 67475 67476 67477 67478 67479 67480 67481 67482 67483 67484 67485 67486 67487 67488 67489 67490 67491 67492 67493 67494 67495 67496 67497 67498 67499 67500 67501 67502 67503 67504 67505 67506 67507 67508 67509 67510 67511 67512 67513 67514 67515 67516 67517 67518 67519 67520 67521 67522 67523 67524 67525 67526 67527 67528 67529 67530 67531 67532 67533 67534 67535 67536 67537 67538 67539 67540 67541 67542 67543 67544 67545 67546 67547 67548 67549 67550 67551 67552 67553 67554 67555 67556 67557 67558 67559 67560 67561 67562 67563 67564 67565 67566 67567 67568 67569 67570 67571 67572 67573 67574 67575 67576 67577 67578 67579 67580 67581 67582 67583 67584 67585 67586 67587 67588 67589 67590 67591 67592 67593 67594 67595 67596 67597 67598 67599 67600 67601 67602 67603 67604 67605 67606 67607 67608 67609 67610 67611 67612 67613 67614 67615 67616 67617 67618 67619 67620 67621 67622 67623 67624 67625 67626 67627 67628 67629 67630 67631 67632 67633 67634 67635 67636 67637 67638 67639 67640 67641 67642 67643 67644 67645 67646 67647 67648 67649 67650 67651 67652 67653 67654 67655 67656 67657 67658 67659 67660 67661 67662 67663 67664 67665 67666 67667 67668 67669 67670 67671 67672 67673 67674 67675 67676 67677 67678 67679 67680 67681 67682 67683 67684 67685 67686 67687 67688 67689 67690 67691 67692 67693 67694 67695 67696 67697 67698 67699 67700 67701 67702 67703 67704 67705 67706 67707 67708 67709 67710 67711 67712 67713 67714 67715 67716 67717 67718 67719 67720 67721 67722 67723 67724 67725 67726 67727 67728 67729 67730 67731 67732 67733 67734 67735 67736 67737 67738 67739 67740 67741 67742 67743 67744 67745 67746 67747 67748 67749 67750 67751 67752 67753 67754 67755 67756 67757 67758 67759 67760 67761 67762 67763 67764 67765 67766 67767 67768 67769 67770 67771 67772 67773 67774 67775 67776 67777 67778 67779 67780 67781 67782 67783 67784 67785 67786 67787 67788 67789 67790 67791 67792 67793 67794 67795 67796 67797 67798 67799 67800 67801 67802 67803 67804 67805 67806 67807 67808 67809 67810 67811 67812 67813 67814 67815 67816 67817 67818 67819 67820 67821 67822 67823 67824 67825 67826 67827 67828 67829 67830 67831 67832 67833 67834 67835 67836 67837 67838 67839 67840 67841 67842 67843 67844 67845 67846 67847 67848 67849 67850 67851 67852 67853 67854 67855 67856 67857 67858 67859 67860 67861 67862 67863 67864 67865 67866 67867 67868 67869 67870 67871 67872 67873 67874 67875 67876 67877 67878 67879 67880 67881 67882 67883 67884 67885 67886 67887 67888 67889 67890 67891 67892 67893 67894 67895 67896 67897 67898 67899 67900 67901 67902 67903 67904 67905 67906 67907 67908 67909 67910 67911 67912 67913 67914 67915 67916 67917 67918 67919 67920 67921 67922 67923 67924 67925 67926 67927 67928 67929 67930 67931 67932 67933 67934 67935 67936 67937 67938 67939 67940 67941 67942 67943 67944 67945 67946 67947 67948 67949 67950 67951 67952 67953 67954 67955 67956 67957 67958 67959 67960 67961 67962 67963 67964 67965 67966 67967 67968 67969 67970 67971 67972 67973 67974 67975 67976 67977 67978 67979 67980 67981 67982 67983 67984 67985 67986 67987 67988 67989 67990 67991 67992 67993 67994 67995 67996 67997 67998 67999 68000 68001 68002 68003 68004 68005 68006 68007 68008 68009 68010 68011 68012 68013 68014 68015 68016 68017 68018 68019 68020 68021 68022 68023 68024 68025 68026 68027 68028 68029 68030 68031 68032 68033 68034 68035 68036 68037 68038 68039 68040 68041 68042 68043 68044 68045 68046 68047 68048 68049 68050 68051 68052 68053 68054 68055 68056 68057 68058 68059 68060 68061 68062 68063 68064 68065 68066 68067 68068 68069 68070 68071 68072 68073 68074 68075 68076 68077 68078 68079 68080 68081 68082 68083 68084 68085 68086 68087 68088 68089 68090 68091 68092 68093 68094 68095 68096 68097 68098 68099 68100 68101 68102 68103 68104 68105 68106 68107 68108 68109 68110 68111 68112 68113 68114 68115 68116 68117 68118 68119 68120 68121 68122 68123 68124 68125 68126 68127 68128 68129 68130 68131 68132 68133 68134 68135 68136 68137 68138 68139 68140 68141 68142 68143 68144 68145 68146 68147 68148 68149 68150 68151 68152 68153 68154 68155 68156 68157 68158 68159 68160 68161 68162 68163 68164 68165 68166 68167 68168 68169 68170 68171 68172 68173 68174 68175 68176 68177 68178 68179 68180 68181 68182 68183 68184 68185 68186 68187 68188 68189 68190 68191 68192 68193 68194 68195 68196 68197 68198 68199 68200 68201 68202 68203 68204 68205 68206 68207 68208 68209 68210 68211 68212 68213 68214 68215 68216 68217 68218 68219 68220 68221 68222 68223 68224 68225 68226 68227 68228 68229 68230 68231 68232 68233 68234 68235 68236 68237 68238 68239 68240 68241 68242 68243 68244 68245 68246 68247 68248 68249 68250 68251 68252 68253 68254 68255 68256 68257 68258 68259 68260 68261 68262 68263 68264 68265 68266 68267 68268 68269 68270 68271 68272 68273 68274 68275 68276 68277 68278 68279 68280 68281 68282 68283 68284 68285 68286 68287 68288 68289 68290 68291 68292 68293 68294 68295 68296 68297 68298 68299 68300 68301 68302 68303 68304 68305 68306 68307 68308 68309 68310 68311 68312 68313 68314 68315 68316 68317 68318 68319 68320 68321 68322 68323 68324 68325 68326 68327 68328 68329 68330 68331 68332 68333 68334 68335 68336 68337 68338 68339 68340 68341 68342 68343 68344 68345 68346 68347 68348 68349 68350 68351 68352 68353 68354 68355 68356 68357 68358 68359 68360 68361 68362 68363 68364 68365 68366 68367 68368 68369 68370 68371 68372 68373 68374 68375 68376 68377 68378 68379 68380 68381 68382 68383 68384 68385 68386 68387 68388 68389 68390 68391 68392 68393 68394 68395 68396 68397 68398 68399 68400 68401 68402 68403 68404 68405 68406 68407 68408 68409 68410 68411 68412 68413 68414 68415 68416 68417 68418 68419 68420 68421 68422 68423 68424 68425 68426 68427 68428 68429 68430 68431 68432 68433 68434 68435 68436 68437 68438 68439 68440 68441 68442 68443 68444 68445 68446 68447 68448 68449 68450 68451 68452 68453 68454 68455 68456 68457 68458 68459 68460 68461 68462 68463 68464 68465 68466 68467 68468 68469 68470 68471 68472 68473 68474 68475 68476 68477 68478 68479 68480 68481 68482 68483 68484 68485 68486 68487 68488 68489 68490 68491 68492 68493 68494 68495 68496 68497 68498 68499 68500 68501 68502 68503 68504 68505 68506 68507 68508 68509 68510 68511 68512 68513 68514 68515 68516 68517 68518 68519 68520 68521 68522 68523 68524 68525 68526 68527 68528 68529 68530 68531 68532 68533 68534 68535 68536 68537 68538 68539 68540 68541 68542 68543 68544 68545 68546 68547 68548 68549 68550 68551 68552 68553 68554 68555 68556 68557 68558 68559 68560 68561 68562 68563 68564 68565 68566 68567 68568 68569 68570 68571 68572 68573 68574 68575 68576 68577 68578 68579 68580 68581 68582 68583 68584 68585 68586 68587 68588 68589 68590 68591 68592 68593 68594 68595 68596 68597 68598 68599 68600 68601 68602 68603 68604 68605 68606 68607 68608 68609 68610 68611 68612 68613 68614 68615 68616 68617 68618 68619 68620 68621 68622 68623 68624 68625 68626 68627 68628 68629 68630 68631 68632 68633 68634 68635 68636 68637 68638 68639 68640 68641 68642 68643 68644 68645 68646 68647 68648 68649 68650 68651 68652 68653 68654 68655 68656 68657 68658 68659 68660 68661 68662 68663 68664 68665 68666 68667 68668 68669 68670 68671 68672 68673 68674 68675 68676 68677 68678 68679 68680 68681 68682 68683 68684 68685 68686 68687 68688 68689 68690 68691 68692 68693 68694 68695 68696 68697 68698 68699 68700 68701 68702 68703 68704 68705 68706 68707 68708 68709 68710 68711 68712 68713 68714 68715 68716 68717 68718 68719 68720 68721 68722 68723 68724 68725 68726 68727 68728 68729 68730 68731 68732 68733 68734 68735 68736 68737 68738 68739 68740 68741 68742 68743 68744 68745 68746 68747 68748 68749 68750 68751 68752 68753 68754 68755 68756 68757 68758 68759 68760 68761 68762 68763 68764 68765 68766 68767 68768 68769 68770 68771 68772 68773 68774 68775 68776 68777 68778 68779 68780 68781 68782 68783 68784 68785 68786 68787 68788 68789 68790 68791 68792 68793 68794 68795 68796 68797 68798 68799 68800 68801 68802 68803 68804 68805 68806 68807 68808 68809 68810 68811 68812 68813 68814 68815 68816 68817 68818 68819 68820 68821 68822 68823 68824 68825 68826 68827 68828 68829 68830 68831 68832 68833 68834 68835 68836 68837 68838 68839 68840 68841 68842 68843 68844 68845 68846 68847 68848 68849 68850 68851 68852 68853 68854 68855 68856 68857 68858 68859 68860 68861 68862 68863 68864 68865 68866 68867 68868 68869 68870 68871 68872 68873 68874 68875 68876 68877 68878 68879 68880 68881 68882 68883 68884 68885 68886 68887 68888 68889 68890 68891 68892 68893 68894 68895 68896 68897 68898 68899 68900 68901 68902 68903 68904 68905 68906 68907 68908 68909 68910 68911 68912 68913 68914 68915 68916 68917 68918 68919 68920 68921 68922 68923 68924 68925 68926 68927 68928 68929 68930 68931 68932 68933 68934 68935 68936 68937 68938 68939 68940 68941 68942 68943 68944 68945 68946 68947 68948 68949 68950 68951 68952 68953 68954 68955 68956 68957 68958 68959 68960 68961 68962 68963 68964 68965 68966 68967 68968 68969 68970 68971 68972 68973 68974 68975 68976 68977 68978 68979 68980 68981 68982 68983 68984 68985 68986 68987 68988 68989 68990 68991 68992 68993 68994 68995 68996 68997 68998 68999 69000 69001 69002 69003 69004 69005 69006 69007 69008 69009 69010 69011 69012 69013 69014 69015 69016 69017 69018 69019 69020 69021 69022 69023 69024 69025 69026 69027 69028 69029 69030 69031 69032 69033 69034 69035 69036 69037 69038 69039 69040 69041 69042 69043 69044 69045 69046 69047 69048 69049 69050 69051 69052 69053 69054 69055 69056 69057 69058 69059 69060 69061 69062 69063 69064 69065 69066 69067 69068 69069 69070 69071 69072 69073 69074 69075 69076 69077 69078 69079 69080 69081 69082 69083 69084 69085 69086 69087 69088 69089 69090 69091 69092 69093 69094 69095 69096 69097 69098 69099 69100 69101 69102 69103 69104 69105 69106 69107 69108 69109 69110 69111 69112 69113 69114 69115 69116 69117 69118 69119 69120 69121 69122 69123 69124 69125 69126 69127 69128 69129 69130 69131 69132 69133 69134 69135 69136 69137 69138 69139 69140 69141 69142 69143 69144 69145 69146 69147 69148 69149 69150 69151 69152 69153 69154 69155 69156 69157 69158 69159 69160 69161 69162 69163 69164 69165 69166 69167 69168 69169 69170 69171 69172 69173 69174 69175 69176 69177 69178 69179 69180 69181 69182 69183 69184 69185 69186 69187 69188 69189 69190 69191 69192 69193 69194 69195 69196 69197 69198 69199 69200 69201 69202 69203 69204 69205 69206 69207 69208 69209 69210 69211 69212 69213 69214 69215 69216 69217 69218 69219 69220 69221 69222 69223 69224 69225 69226 69227 69228 69229 69230 69231 69232 69233 69234 69235 69236 69237 69238 69239 69240 69241 69242 69243 69244 69245 69246 69247 69248 69249 69250 69251 69252 69253 69254 69255 69256 69257 69258 69259 69260 69261 69262 69263 69264 69265 69266 69267 69268 69269 69270 69271 69272 69273 69274 69275 69276 69277 69278 69279 69280 69281 69282 69283 69284 69285 69286 69287 69288 69289 69290 69291 69292 69293 69294 69295 69296 69297 69298 69299 69300 69301 69302 69303 69304 69305 69306 69307 69308 69309 69310 69311 69312 69313 69314 69315 69316 69317 69318 69319 69320 69321 69322 69323 69324 69325 69326 69327 69328 69329 69330 69331 69332 69333 69334 69335 69336 69337 69338 69339 69340 69341 69342 69343 69344 69345 69346 69347 69348 69349 69350 69351 69352 69353 69354 69355 69356 69357 69358 69359 69360 69361 69362 69363 69364 69365 69366 69367 69368 69369 69370 69371 69372 69373 69374 69375 69376 69377 69378 69379 69380 69381 69382 69383 69384 69385 69386 69387 69388 69389 69390 69391 69392 69393 69394 69395 69396 69397 69398 69399 69400 69401 69402 69403 69404 69405 69406 69407 69408 69409 69410 69411 69412 69413 69414 69415 69416 69417 69418 69419 69420 69421 69422 69423 69424 69425 69426 69427 69428 69429 69430 69431 69432 69433 69434 69435 69436 69437 69438 69439 69440 69441 69442 69443 69444 69445 69446 69447 69448 69449 69450 69451 69452 69453 69454 69455 69456 69457 69458 69459 69460 69461 69462 69463 69464 69465 69466 69467 69468 69469 69470 69471 69472 69473 69474 69475 69476 69477 69478 69479 69480 69481 69482 69483 69484 69485 69486 69487 69488 69489 69490 69491 69492 69493 69494 69495 69496 69497 69498 69499 69500 69501 69502 69503 69504 69505 69506 69507 69508 69509 69510 69511 69512 69513 69514 69515 69516 69517 69518 69519 69520 69521 69522 69523 69524 69525 69526 69527 69528 69529 69530 69531 69532 69533 69534 69535 69536 69537 69538 69539 69540 69541 69542 69543 69544 69545 69546 69547 69548 69549 69550 69551 69552 69553 69554 69555 69556 69557 69558 69559 69560 69561 69562 69563 69564 69565 69566 69567 69568 69569 69570 69571 69572 69573 69574 69575 69576 69577 69578 69579 69580 69581 69582 69583 69584 69585 69586 69587 69588 69589 69590 69591 69592 69593 69594 69595 69596 69597 69598 69599 69600 69601 69602 69603 69604 69605 69606 69607 69608 69609 69610 69611 69612 69613 69614 69615 69616 69617 69618 69619 69620 69621 69622 69623 69624 69625 69626 69627 69628 69629 69630 69631 69632 69633 69634 69635 69636 69637 69638 69639 69640 69641 69642 69643 69644 69645 69646 69647 69648 69649 69650 69651 69652 69653 69654 69655 69656 69657 69658 69659 69660 69661 69662 69663 69664 69665 69666 69667 69668 69669 69670 69671 69672 69673 69674 69675 69676 69677 69678 69679 69680 69681 69682 69683 69684 69685 69686 69687 69688 69689 69690 69691 69692 69693 69694 69695 69696 69697 69698 69699 69700 69701 69702 69703 69704 69705 69706 69707 69708 69709 69710 69711 69712 69713 69714 69715 69716 69717 69718 69719 69720 69721 69722 69723 69724 69725 69726 69727 69728 69729 69730 69731 69732 69733 69734 69735 69736 69737 69738 69739 69740 69741 69742 69743 69744 69745 69746 69747 69748 69749 69750 69751 69752 69753 69754 69755 69756 69757 69758 69759 69760 69761 69762 69763 69764 69765 69766 69767 69768 69769 69770 69771 69772 69773 69774 69775 69776 69777 69778 69779 69780 69781 69782 69783 69784 69785 69786 69787 69788 69789 69790 69791 69792 69793 69794 69795 69796 69797 69798 69799 69800 69801 69802 69803 69804 69805 69806 69807 69808 69809 69810 69811 69812 69813 69814 69815 69816 69817 69818 69819 69820 69821 69822 69823 69824 69825 69826 69827 69828 69829 69830 69831 69832 69833 69834 69835 69836 69837 69838 69839 69840 69841 69842 69843 69844 69845 69846 69847 69848 69849 69850 69851 69852 69853 69854 69855 69856 69857 69858 69859 69860 69861 69862 69863 69864 69865 69866 69867 69868 69869 69870 69871 69872 69873 69874 69875 69876 69877 69878 69879 69880 69881 69882 69883 69884 69885 69886 69887 69888 69889 69890 69891 69892 69893 69894 69895 69896 69897 69898 69899 69900 69901 69902 69903 69904 69905 69906 69907 69908 69909 69910 69911 69912 69913 69914 69915 69916 69917 69918 69919 69920 69921 69922 69923 69924 69925 69926 69927 69928 69929 69930 69931 69932 69933 69934 69935 69936 69937 69938 69939 69940 69941 69942 69943 69944 69945 69946 69947 69948 69949 69950 69951 69952 69953 69954 69955 69956 69957 69958 69959 69960 69961 69962 69963 69964 69965 69966 69967 69968 69969 69970 69971 69972 69973 69974 69975 69976 69977 69978 69979 69980 69981 69982 69983 69984 69985 69986 69987 69988 69989 69990 69991 69992 69993 69994 69995 69996 69997 69998 69999 70000 70001 70002 70003 70004 70005 70006 70007 70008 70009 70010 70011 70012 70013 70014 70015 70016 70017 70018 70019 70020 70021 70022 70023 70024 70025 70026 70027 70028 70029 70030 70031 70032 70033 70034 70035 70036 70037 70038 70039 70040 70041 70042 70043 70044 70045 70046 70047 70048 70049 70050 70051 70052 70053 70054 70055 70056 70057 70058 70059 70060 70061 70062 70063 70064 70065 70066 70067 70068 70069 70070 70071 70072 70073 70074 70075 70076 70077 70078 70079 70080 70081 70082 70083 70084 70085 70086 70087 70088 70089 70090 70091 70092 70093 70094 70095 70096 70097 70098 70099 70100 70101 70102 70103 70104 70105 70106 70107 70108 70109 70110 70111 70112 70113 70114 70115 70116 70117 70118 70119 70120 70121 70122 70123 70124 70125 70126 70127 70128 70129 70130 70131 70132 70133 70134 70135 70136 70137 70138 70139 70140 70141 70142 70143 70144 70145 70146 70147 70148 70149 70150 70151 70152 70153 70154 70155 70156 70157 70158 70159 70160 70161 70162 70163 70164 70165 70166 70167 70168 70169 70170 70171 70172 70173 70174 70175 70176 70177 70178 70179 70180 70181 70182 70183 70184 70185 70186 70187 70188 70189 70190 70191 70192 70193 70194 70195 70196 70197 70198 70199 70200 70201 70202 70203 70204 70205 70206 70207 70208 70209 70210 70211 70212 70213 70214 70215 70216 70217 70218 70219 70220 70221 70222 70223 70224 70225 70226 70227 70228 70229 70230 70231 70232 70233 70234 70235 70236 70237 70238 70239 70240 70241 70242 70243 70244 70245 70246 70247 70248 70249 70250 70251 70252 70253 70254 70255 70256 70257 70258 70259 70260 70261 70262 70263 70264 70265 70266 70267 70268 70269 70270 70271 70272 70273 70274 70275 70276 70277 70278 70279 70280 70281 70282 70283 70284 70285 70286 70287 70288 70289 70290 70291 70292 70293 70294 70295 70296 70297 70298 70299 70300 70301 70302 70303 70304 70305 70306 70307 70308 70309 70310 70311 70312 70313 70314 70315 70316 70317 70318 70319 70320 70321 70322 70323 70324 70325 70326 70327 70328 70329 70330 70331 70332 70333 70334 70335 70336 70337 70338 70339 70340 70341 70342 70343 70344 70345 70346 70347 70348 70349 70350 70351 70352 70353 70354 70355 70356 70357 70358 70359 70360 70361 70362 70363 70364 70365 70366 70367 70368 70369 70370 70371 70372 70373 70374 70375 70376 70377 70378 70379 70380 70381 70382 70383 70384 70385 70386 70387 70388 70389 70390 70391 70392 70393 70394 70395 70396 70397 70398 70399 70400 70401 70402 70403 70404 70405 70406 70407 70408 70409 70410 70411 70412 70413 70414 70415 70416 70417 70418 70419 70420 70421 70422 70423 70424 70425 70426 70427 70428 70429 70430 70431 70432 70433 70434 70435 70436 70437 70438 70439 70440 70441 70442 70443 70444 70445 70446 70447 70448 70449 70450 70451 70452 70453 70454 70455 70456 70457 70458 70459 70460 70461 70462 70463 70464 70465 70466 70467 70468 70469 70470 70471 70472 70473 70474 70475 70476 70477 70478 70479 70480 70481 70482 70483 70484 70485 70486 70487 70488 70489 70490 70491 70492 70493 70494 70495 70496 70497 70498 70499 70500 70501 70502 70503 70504 70505 70506 70507 70508 70509 70510 70511 70512 70513 70514 70515 70516 70517 70518 70519 70520 70521 70522 70523 70524 70525 70526 70527 70528 70529 70530 70531 70532 70533 70534 70535 70536 70537 70538 70539 70540 70541 70542 70543 70544 70545 70546 70547 70548 70549 70550 70551 70552 70553 70554 70555 70556 70557 70558 70559 70560 70561 70562 70563 70564 70565 70566 70567 70568 70569 70570 70571 70572 70573 70574 70575 70576 70577 70578 70579 70580 70581 70582 70583 70584 70585 70586 70587 70588 70589 70590 70591 70592 70593 70594 70595 70596 70597 70598 70599 70600 70601 70602 70603 70604 70605 70606 70607 70608 70609 70610 70611 70612 70613 70614 70615 70616 70617 70618 70619 70620 70621 70622 70623 70624 70625 70626 70627 70628 70629 70630 70631 70632 70633 70634 70635 70636 70637 70638 70639 70640 70641 70642 70643 70644 70645 70646 70647 70648 70649 70650 70651 70652 70653 70654 70655 70656 70657 70658 70659 70660 70661 70662 70663 70664 70665 70666 70667 70668 70669 70670 70671 70672 70673 70674 70675 70676 70677 70678 70679 70680 70681 70682 70683 70684 70685 70686 70687 70688 70689 70690 70691 70692 70693 70694 70695 70696 70697 70698 70699 70700 70701 70702 70703 70704 70705 70706 70707 70708 70709 70710 70711 70712 70713 70714 70715 70716 70717 70718 70719 70720 70721 70722 70723 70724 70725 70726 70727 70728 70729 70730 70731 70732 70733 70734 70735 70736 70737 70738 70739 70740 70741 70742 70743 70744 70745 70746 70747 70748 70749 70750 70751 70752 70753 70754 70755 70756 70757 70758 70759 70760 70761 70762 70763 70764 70765 70766 70767 70768 70769 70770 70771 70772 70773 70774 70775 70776 70777 70778 70779 70780 70781 70782 70783 70784 70785 70786 70787 70788 70789 70790 70791 70792 70793 70794 70795 70796 70797 70798 70799 70800 70801 70802 70803 70804 70805 70806 70807 70808 70809 70810 70811 70812 70813 70814 70815 70816 70817 70818 70819 70820 70821 70822 70823 70824 70825 70826 70827 70828 70829 70830 70831 70832 70833 70834 70835 70836 70837 70838 70839 70840 70841 70842 70843 70844 70845 70846 70847 70848 70849 70850 70851 70852 70853 70854 70855 70856 70857 70858 70859 70860 70861 70862 70863 70864 70865 70866 70867 70868 70869 70870 70871 70872 70873 70874 70875 70876 70877 70878 70879 70880 70881 70882 70883 70884 70885 70886 70887 70888 70889 70890 70891 70892 70893 70894 70895 70896 70897 70898 70899 70900 70901 70902 70903 70904 70905 70906 70907 70908 70909 70910 70911 70912 70913 70914 70915 70916 70917 70918 70919 70920 70921 70922 70923 70924 70925 70926 70927 70928 70929 70930 70931 70932 70933 70934 70935 70936 70937 70938 70939 70940 70941 70942 70943 70944 70945 70946 70947 70948 70949 70950 70951 70952 70953 70954 70955 70956 70957 70958 70959 70960 70961 70962 70963 70964 70965 70966 70967 70968 70969 70970 70971 70972 70973 70974 70975 70976 70977 70978 70979 70980 70981 70982 70983 70984 70985 70986 70987 70988 70989 70990 70991 70992 70993 70994 70995 70996 70997 70998 70999 71000 71001 71002 71003 71004 71005 71006 71007 71008 71009 71010 71011 71012 71013 71014 71015 71016 71017 71018 71019 71020 71021 71022 71023 71024 71025 71026 71027 71028 71029 71030 71031 71032 71033 71034 71035 71036 71037 71038 71039 71040 71041 71042 71043 71044 71045 71046 71047 71048 71049 71050 71051 71052 71053 71054 71055 71056 71057 71058 71059 71060 71061 71062 71063 71064 71065 71066 71067 71068 71069 71070 71071 71072 71073 71074 71075 71076 71077 71078 71079 71080 71081 71082 71083 71084 71085 71086 71087 71088 71089 71090 71091 71092 71093 71094 71095 71096 71097 71098 71099 71100 71101 71102 71103 71104 71105 71106 71107 71108 71109 71110 71111 71112 71113 71114 71115 71116 71117 71118 71119 71120 71121 71122 71123 71124 71125 71126 71127 71128 71129 71130 71131 71132 71133 71134 71135 71136 71137 71138 71139 71140 71141 71142 71143 71144 71145 71146 71147 71148 71149 71150 71151 71152 71153 71154 71155 71156 71157 71158 71159 71160 71161 71162 71163 71164 71165 71166 71167 71168 71169 71170 71171 71172 71173 71174 71175 71176 71177 71178 71179 71180 71181 71182 71183 71184 71185 71186 71187 71188 71189 71190 71191 71192 71193 71194 71195 71196 71197 71198 71199 71200 71201 71202 71203 71204 71205 71206 71207 71208 71209 71210 71211 71212 71213 71214 71215 71216 71217 71218 71219 71220 71221 71222 71223 71224 71225 71226 71227 71228 71229 71230 71231 71232 71233 71234 71235 71236 71237 71238 71239 71240 71241 71242 71243 71244 71245 71246 71247 71248 71249 71250 71251 71252 71253 71254 71255 71256 71257 71258 71259 71260 71261 71262 71263 71264 71265 71266 71267 71268 71269 71270 71271 71272 71273 71274 71275 71276 71277 71278 71279 71280 71281 71282 71283 71284 71285 71286 71287 71288 71289 71290 71291 71292 71293 71294 71295 71296 71297 71298 71299 71300 71301 71302 71303 71304 71305 71306 71307 71308 71309 71310 71311 71312 71313 71314 71315 71316 71317 71318 71319 71320 71321 71322 71323 71324 71325 71326 71327 71328 71329 71330 71331 71332 71333 71334 71335 71336 71337 71338 71339 71340 71341 71342 71343 71344 71345 71346 71347 71348 71349 71350 71351 71352 71353 71354 71355 71356 71357 71358 71359 71360 71361 71362 71363 71364 71365 71366 71367 71368 71369 71370 71371 71372 71373 71374 71375 71376 71377 71378 71379 71380 71381 71382 71383 71384 71385 71386 71387 71388 71389 71390 71391 71392 71393 71394 71395 71396 71397 71398 71399 71400 71401 71402 71403 71404 71405 71406 71407 71408 71409 71410 71411 71412 71413 71414 71415 71416 71417 71418 71419 71420 71421 71422 71423 71424 71425 71426 71427 71428 71429 71430 71431 71432 71433 71434 71435 71436 71437 71438 71439 71440 71441 71442 71443 71444 71445 71446 71447 71448 71449 71450 71451 71452 71453 71454 71455 71456 71457 71458 71459 71460 71461 71462 71463 71464 71465 71466 71467 71468 71469 71470 71471 71472 71473 71474 71475 71476 71477 71478 71479 71480 71481 71482 71483 71484 71485 71486 71487 71488 71489 71490 71491 71492 71493 71494 71495 71496 71497 71498 71499 71500 71501 71502 71503 71504 71505 71506 71507 71508 71509 71510 71511 71512 71513 71514 71515 71516 71517 71518 71519 71520 71521 71522 71523 71524 71525 71526 71527 71528 71529 71530 71531 71532 71533 71534 71535 71536 71537 71538 71539 71540 71541 71542 71543 71544 71545 71546 71547 71548 71549 71550 71551 71552 71553 71554 71555 71556 71557 71558 71559 71560 71561 71562 71563 71564 71565 71566 71567 71568 71569 71570 71571 71572 71573 71574 71575 71576 71577 71578 71579 71580 71581 71582 71583 71584 71585 71586 71587 71588 71589 71590 71591 71592 71593 71594 71595 71596 71597 71598 71599 71600 71601 71602 71603 71604 71605 71606 71607 71608 71609 71610 71611 71612 71613 71614 71615 71616 71617 71618 71619 71620 71621 71622 71623 71624 71625 71626 71627 71628 71629 71630 71631 71632 71633 71634 71635 71636 71637 71638 71639 71640 71641 71642 71643 71644 71645 71646 71647 71648 71649 71650 71651 71652 71653 71654 71655 71656 71657 71658 71659 71660 71661 71662 71663 71664 71665 71666 71667 71668 71669 71670 71671 71672 71673 71674 71675 71676 71677 71678 71679 71680 71681 71682 71683 71684 71685 71686 71687 71688 71689 71690 71691 71692 71693 71694 71695 71696 71697 71698 71699 71700 71701 71702 71703 71704 71705 71706 71707 71708 71709 71710 71711 71712 71713 71714 71715 71716 71717 71718 71719 71720 71721 71722 71723 71724 71725 71726 71727 71728 71729 71730 71731 71732 71733 71734 71735 71736 71737 71738 71739 71740 71741 71742 71743 71744 71745 71746 71747 71748 71749 71750 71751 71752 71753 71754 71755 71756 71757 71758 71759 71760 71761 71762 71763 71764 71765 71766 71767 71768 71769 71770 71771 71772 71773 71774 71775 71776 71777 71778 71779 71780 71781 71782 71783 71784 71785 71786 71787 71788 71789 71790 71791 71792 71793 71794 71795 71796 71797 71798 71799 71800 71801 71802 71803 71804 71805 71806 71807 71808 71809 71810 71811 71812 71813 71814 71815 71816 71817 71818 71819 71820 71821 71822 71823 71824 71825 71826 71827 71828 71829 71830 71831 71832 71833 71834 71835 71836 71837 71838 71839 71840 71841 71842 71843 71844 71845 71846 71847 71848 71849 71850 71851 71852 71853 71854 71855 71856 71857 71858 71859 71860 71861 71862 71863 71864 71865 71866 71867 71868 71869 71870 71871 71872 71873 71874 71875 71876 71877 71878 71879 71880 71881 71882 71883 71884 71885 71886 71887 71888 71889 71890 71891 71892 71893 71894 71895 71896 71897 71898 71899 71900 71901 71902 71903 71904 71905 71906 71907 71908 71909 71910 71911 71912 71913 71914 71915 71916 71917 71918 71919 71920 71921 71922 71923 71924 71925 71926 71927 71928 71929 71930 71931 71932 71933 71934 71935 71936 71937 71938 71939 71940 71941 71942 71943 71944 71945 71946 71947 71948 71949 71950 71951 71952 71953 71954 71955 71956 71957 71958 71959 71960 71961 71962 71963 71964 71965 71966 71967 71968 71969 71970 71971 71972 71973 71974 71975 71976 71977 71978 71979 71980 71981 71982 71983 71984 71985 71986 71987 71988 71989 71990 71991 71992 71993 71994 71995 71996 71997 71998 71999 72000 72001 72002 72003 72004 72005 72006 72007 72008 72009 72010 72011 72012 72013 72014 72015 72016 72017 72018 72019 72020 72021 72022 72023 72024 72025 72026 72027 72028 72029 72030 72031 72032 72033 72034 72035 72036 72037 72038 72039 72040 72041 72042 72043 72044 72045 72046 72047 72048 72049 72050 72051 72052 72053 72054 72055 72056 72057 72058 72059 72060 72061 72062 72063 72064 72065 72066 72067 72068 72069 72070 72071 72072 72073 72074 72075 72076 72077 72078 72079 72080 72081 72082 72083 72084 72085 72086 72087 72088 72089 72090 72091 72092 72093 72094 72095 72096 72097 72098 72099 72100 72101 72102 72103 72104 72105 72106 72107 72108 72109 72110 72111 72112 72113 72114 72115 72116 72117 72118 72119 72120 72121 72122 72123 72124 72125 72126 72127 72128 72129 72130 72131 72132 72133 72134 72135 72136 72137 72138 72139 72140 72141 72142 72143 72144 72145 72146 72147 72148 72149 72150 72151 72152 72153 72154 72155 72156 72157 72158 72159 72160 72161 72162 72163 72164 72165 72166 72167 72168 72169 72170 72171 72172 72173 72174 72175 72176 72177 72178 72179 72180 72181 72182 72183 72184 72185 72186 72187 72188 72189 72190 72191 72192 72193 72194 72195 72196 72197 72198 72199 72200 72201 72202 72203 72204 72205 72206 72207 72208 72209 72210 72211 72212 72213 72214 72215 72216 72217 72218 72219 72220 72221 72222 72223 72224 72225 72226 72227 72228 72229 72230 72231 72232 72233 72234 72235 72236 72237 72238 72239 72240 72241 72242 72243 72244 72245 72246 72247 72248 72249 72250 72251 72252 72253 72254 72255 72256 72257 72258 72259 72260 72261 72262 72263 72264 72265 72266 72267 72268 72269 72270 72271 72272 72273 72274 72275 72276 72277 72278 72279 72280 72281 72282 72283 72284 72285 72286 72287 72288 72289 72290 72291 72292 72293 72294 72295 72296 72297 72298 72299 72300 72301 72302 72303 72304 72305 72306 72307 72308 72309 72310 72311 72312 72313 72314 72315 72316 72317 72318 72319 72320 72321 72322 72323 72324 72325 72326 72327 72328 72329 72330 72331 72332 72333 72334 72335 72336 72337 72338 72339 72340 72341 72342 72343 72344 72345 72346 72347 72348 72349 72350 72351 72352 72353 72354 72355 72356 72357 72358 72359 72360 72361 72362 72363 72364 72365 72366 72367 72368 72369 72370 72371 72372 72373 72374 72375 72376 72377 72378 72379 72380 72381 72382 72383 72384 72385 72386 72387 72388 72389 72390 72391 72392 72393 72394 72395 72396 72397 72398 72399 72400 72401 72402 72403 72404 72405 72406 72407 72408 72409 72410 72411 72412 72413 72414 72415 72416 72417 72418 72419 72420 72421 72422 72423 72424 72425 72426 72427 72428 72429 72430 72431 72432 72433 72434 72435 72436 72437 72438 72439 72440 72441 72442 72443 72444 72445 72446 72447 72448 72449 72450 72451 72452 72453 72454 72455 72456 72457 72458 72459 72460 72461 72462 72463 72464 72465 72466 72467 72468 72469 72470 72471 72472 72473 72474 72475 72476 72477 72478 72479 72480 72481 72482 72483 72484 72485 72486 72487 72488 72489 72490 72491 72492 72493 72494 72495 72496 72497 72498 72499 72500 72501 72502 72503 72504 72505 72506 72507 72508 72509 72510 72511 72512 72513 72514 72515 72516 72517 72518 72519 72520 72521 72522 72523 72524 72525 72526 72527 72528 72529 72530 72531 72532 72533 72534 72535 72536 72537 72538 72539 72540 72541 72542 72543 72544 72545 72546 72547 72548 72549 72550 72551 72552 72553 72554 72555 72556 72557 72558 72559 72560 72561 72562 72563 72564 72565 72566 72567 72568 72569 72570 72571 72572 72573 72574 72575 72576 72577 72578 72579 72580 72581 72582 72583 72584 72585 72586 72587 72588 72589 72590 72591 72592 72593 72594 72595 72596 72597 72598 72599 72600 72601 72602 72603 72604 72605 72606 72607 72608 72609 72610 72611 72612 72613 72614 72615 72616 72617 72618 72619 72620 72621 72622 72623 72624 72625 72626 72627 72628 72629 72630 72631 72632 72633 72634 72635 72636 72637 72638 72639 72640 72641 72642 72643 72644 72645 72646 72647 72648 72649 72650 72651 72652 72653 72654 72655 72656 72657 72658 72659 72660 72661 72662 72663 72664 72665 72666 72667 72668 72669 72670 72671 72672 72673 72674 72675 72676 72677 72678 72679 72680 72681 72682 72683 72684 72685 72686 72687 72688 72689 72690 72691 72692 72693 72694 72695 72696 72697 72698 72699 72700 72701 72702 72703 72704 72705 72706 72707 72708 72709 72710 72711 72712 72713 72714 72715 72716 72717 72718 72719 72720 72721 72722 72723 72724 72725 72726 72727 72728 72729 72730 72731 72732 72733 72734 72735 72736 72737 72738 72739 72740 72741 72742 72743 72744 72745 72746 72747 72748 72749 72750 72751 72752 72753 72754 72755 72756 72757 72758 72759 72760 72761 72762 72763 72764 72765 72766 72767 72768 72769 72770 72771 72772 72773 72774 72775 72776 72777 72778 72779 72780 72781 72782 72783 72784 72785 72786 72787 72788 72789 72790 72791 72792 72793 72794 72795 72796 72797 72798 72799 72800 72801 72802 72803 72804 72805 72806 72807 72808 72809 72810 72811 72812 72813 72814 72815 72816 72817 72818 72819 72820 72821 72822 72823 72824 72825 72826 72827 72828 72829 72830 72831 72832 72833 72834 72835 72836 72837 72838 72839 72840 72841 72842 72843 72844 72845 72846 72847 72848 72849 72850 72851 72852 72853 72854 72855 72856 72857 72858 72859 72860 72861 72862 72863 72864 72865 72866 72867 72868 72869 72870 72871 72872 72873 72874 72875 72876 72877 72878 72879 72880 72881 72882 72883 72884 72885 72886 72887 72888 72889 72890 72891 72892 72893 72894 72895 72896 72897 72898 72899 72900 72901 72902 72903 72904 72905 72906 72907 72908 72909 72910 72911 72912 72913 72914 72915 72916 72917 72918 72919 72920 72921 72922 72923 72924 72925 72926 72927 72928 72929 72930 72931 72932 72933 72934 72935 72936 72937 72938 72939 72940 72941 72942 72943 72944 72945 72946 72947 72948 72949 72950 72951 72952 72953 72954 72955 72956 72957 72958 72959 72960 72961 72962 72963 72964 72965 72966 72967 72968 72969 72970 72971 72972 72973 72974 72975 72976 72977 72978 72979 72980 72981 72982 72983 72984 72985 72986 72987 72988 72989 72990 72991 72992 72993 72994 72995 72996 72997 72998 72999 73000 73001 73002 73003 73004 73005 73006 73007 73008 73009 73010 73011 73012 73013 73014 73015 73016 73017 73018 73019 73020 73021 73022 73023 73024 73025 73026 73027 73028 73029 73030 73031 73032 73033 73034 73035 73036 73037 73038 73039 73040 73041 73042 73043 73044 73045 73046 73047 73048 73049 73050 73051 73052 73053 73054 73055 73056 73057 73058 73059 73060 73061 73062 73063 73064 73065 73066 73067 73068 73069 73070 73071 73072 73073 73074 73075 73076 73077 73078 73079 73080 73081 73082 73083 73084 73085 73086 73087 73088 73089 73090 73091 73092 73093 73094 73095 73096 73097 73098 73099 73100 73101 73102 73103 73104 73105 73106 73107 73108 73109 73110 73111 73112 73113 73114 73115 73116 73117 73118 73119 73120 73121 73122 73123 73124 73125 73126 73127 73128 73129 73130 73131 73132 73133 73134 73135 73136 73137 73138 73139 73140 73141 73142 73143 73144 73145 73146 73147 73148 73149 73150 73151 73152 73153 73154 73155 73156 73157 73158 73159 73160 73161 73162 73163 73164 73165 73166 73167 73168 73169 73170 73171 73172 73173 73174 73175 73176 73177 73178 73179 73180 73181 73182 73183 73184 73185 73186 73187 73188 73189 73190 73191 73192 73193 73194 73195 73196 73197 73198 73199 73200 73201 73202 73203 73204 73205 73206 73207 73208 73209 73210 73211 73212 73213 73214 73215 73216 73217 73218 73219 73220 73221 73222 73223 73224 73225 73226 73227 73228 73229 73230 73231 73232 73233 73234 73235 73236 73237 73238 73239 73240 73241 73242 73243 73244 73245 73246 73247 73248 73249 73250 73251 73252 73253 73254 73255 73256 73257 73258 73259 73260 73261 73262 73263 73264 73265 73266 73267 73268 73269 73270 73271 73272 73273 73274 73275 73276 73277 73278 73279 73280 73281 73282 73283 73284 73285 73286 73287 73288 73289 73290 73291 73292 73293 73294 73295 73296 73297 73298 73299 73300 73301 73302 73303 73304 73305 73306 73307 73308 73309 73310 73311 73312 73313 73314 73315 73316 73317 73318 73319 73320 73321 73322 73323 73324 73325 73326 73327 73328 73329 73330 73331 73332 73333 73334 73335 73336 73337 73338 73339 73340 73341 73342 73343 73344 73345 73346 73347 73348 73349 73350 73351 73352 73353 73354 73355 73356 73357 73358 73359 73360 73361 73362 73363 73364 73365 73366 73367 73368 73369 73370 73371 73372 73373 73374 73375 73376 73377 73378 73379 73380 73381 73382 73383 73384 73385 73386 73387 73388 73389 73390 73391 73392 73393 73394 73395 73396 73397 73398 73399 73400 73401 73402 73403 73404 73405 73406 73407 73408 73409 73410 73411 73412 73413 73414 73415 73416 73417 73418 73419 73420 73421 73422 73423 73424 73425 73426 73427 73428 73429 73430 73431 73432 73433 73434 73435 73436 73437 73438 73439 73440 73441 73442 73443 73444 73445 73446 73447 73448 73449 73450 73451 73452 73453 73454 73455 73456 73457 73458 73459 73460 73461 73462 73463 73464 73465 73466 73467 73468 73469 73470 73471 73472 73473 73474 73475 73476 73477 73478 73479 73480 73481 73482 73483 73484 73485 73486 73487 73488 73489 73490 73491 73492 73493 73494 73495 73496 73497 73498 73499 73500 73501 73502 73503 73504 73505 73506 73507 73508 73509 73510 73511 73512 73513 73514 73515 73516 73517 73518 73519 73520 73521 73522 73523 73524 73525 73526 73527 73528 73529 73530 73531 73532 73533 73534 73535 73536 73537 73538 73539 73540 73541 73542 73543 73544 73545 73546 73547 73548 73549 73550 73551 73552 73553 73554 73555 73556 73557 73558 73559 73560 73561 73562 73563 73564 73565 73566 73567 73568 73569 73570 73571 73572 73573 73574 73575 73576 73577 73578 73579 73580 73581 73582 73583 73584 73585 73586 73587 73588 73589 73590 73591 73592 73593 73594 73595 73596 73597 73598 73599 73600 73601 73602 73603 73604 73605 73606 73607 73608 73609 73610 73611 73612 73613 73614 73615 73616 73617 73618 73619 73620 73621 73622 73623 73624 73625 73626 73627 73628 73629 73630 73631 73632 73633 73634 73635 73636 73637 73638 73639 73640 73641 73642 73643 73644 73645 73646 73647 73648 73649 73650 73651 73652 73653 73654 73655 73656 73657 73658 73659 73660 73661 73662 73663 73664 73665 73666 73667 73668 73669 73670 73671 73672 73673 73674 73675 73676 73677 73678 73679 73680 73681 73682 73683 73684 73685 73686 73687 73688 73689 73690 73691 73692 73693 73694 73695 73696 73697 73698 73699 73700 73701 73702 73703 73704 73705 73706 73707 73708 73709 73710 73711 73712 73713 73714 73715 73716 73717 73718 73719 73720 73721 73722 73723 73724 73725 73726 73727 73728 73729 73730 73731 73732 73733 73734 73735 73736 73737 73738 73739 73740 73741 73742 73743 73744 73745 73746 73747 73748 73749 73750 73751 73752 73753 73754 73755 73756 73757 73758 73759 73760 73761 73762 73763 73764 73765 73766 73767 73768 73769 73770 73771 73772 73773 73774 73775 73776 73777 73778 73779 73780 73781 73782 73783 73784 73785 73786 73787 73788 73789 73790 73791 73792 73793 73794 73795 73796 73797 73798 73799 73800 73801 73802 73803 73804 73805 73806 73807 73808 73809 73810 73811 73812 73813 73814 73815 73816 73817 73818 73819 73820 73821 73822 73823 73824 73825 73826 73827 73828 73829 73830 73831 73832 73833 73834 73835 73836 73837 73838 73839 73840 73841 73842 73843 73844 73845 73846 73847 73848 73849 73850 73851 73852 73853 73854 73855 73856 73857 73858 73859 73860 73861 73862 73863 73864 73865 73866 73867 73868 73869 73870 73871 73872 73873 73874 73875 73876 73877 73878 73879 73880 73881 73882 73883 73884 73885 73886 73887 73888 73889 73890 73891 73892 73893 73894 73895 73896 73897 73898 73899 73900 73901 73902 73903 73904 73905 73906 73907 73908 73909 73910 73911 73912 73913 73914 73915 73916 73917 73918 73919 73920 73921 73922 73923 73924 73925 73926 73927 73928 73929 73930 73931 73932 73933 73934 73935 73936 73937 73938 73939 73940 73941 73942 73943 73944 73945 73946 73947 73948 73949 73950 73951 73952 73953 73954 73955 73956 73957 73958 73959 73960 73961 73962 73963 73964 73965 73966 73967 73968 73969 73970 73971 73972 73973 73974 73975 73976 73977 73978 73979 73980 73981 73982 73983 73984 73985 73986 73987 73988 73989 73990 73991 73992 73993 73994 73995 73996 73997 73998 73999 74000 74001 74002 74003 74004 74005 74006 74007 74008 74009 74010 74011 74012 74013 74014 74015 74016 74017 74018 74019 74020 74021 74022 74023 74024 74025 74026 74027 74028 74029 74030 74031 74032 74033 74034 74035 74036 74037 74038 74039 74040 74041 74042 74043 74044 74045 74046 74047 74048 74049 74050 74051 74052 74053 74054 74055 74056 74057 74058 74059 74060 74061 74062 74063 74064 74065 74066 74067 74068 74069 74070 74071 74072 74073 74074 74075 74076 74077 74078 74079 74080 74081 74082 74083 74084 74085 74086 74087 74088 74089 74090 74091 74092 74093 74094 74095 74096 74097 74098 74099 74100 74101 74102 74103 74104 74105 74106 74107 74108 74109 74110 74111 74112 74113 74114 74115 74116 74117 74118 74119 74120 74121 74122 74123 74124 74125 74126 74127 74128 74129 74130 74131 74132 74133 74134 74135 74136 74137 74138 74139 74140 74141 74142 74143 74144 74145 74146 74147 74148 74149 74150 74151 74152 74153 74154 74155 74156 74157 74158 74159 74160 74161 74162 74163 74164 74165 74166 74167 74168 74169 74170 74171 74172 74173 74174 74175 74176 74177 74178 74179 74180 74181 74182 74183 74184 74185 74186 74187 74188 74189 74190 74191 74192 74193 74194 74195 74196 74197 74198 74199 74200 74201 74202 74203 74204 74205 74206 74207 74208 74209 74210 74211 74212 74213 74214 74215 74216 74217 74218 74219 74220 74221 74222 74223 74224 74225 74226 74227 74228 74229 74230 74231 74232 74233 74234 74235 74236 74237 74238 74239 74240 74241 74242 74243 74244 74245 74246 74247 74248 74249 74250 74251 74252 74253 74254 74255 74256 74257 74258 74259 74260 74261 74262 74263 74264 74265 74266 74267 74268 74269 74270 74271 74272 74273 74274 74275 74276 74277 74278 74279 74280 74281 74282 74283 74284 74285 74286 74287 74288 74289 74290 74291 74292 74293 74294 74295 74296 74297 74298 74299 74300 74301 74302 74303 74304 74305 74306 74307 74308 74309 74310 74311 74312 74313 74314 74315 74316 74317 74318 74319 74320 74321 74322 74323 74324 74325 74326 74327 74328 74329 74330 74331 74332 74333 74334 74335 74336 74337 74338 74339 74340 74341 74342 74343 74344 74345 74346 74347 74348 74349 74350 74351 74352 74353 74354 74355 74356 74357 74358 74359 74360 74361 74362 74363 74364 74365 74366 74367 74368 74369 74370 74371 74372 74373 74374 74375 74376 74377 74378 74379 74380 74381 74382 74383 74384 74385 74386 74387 74388 74389 74390 74391 74392 74393 74394 74395 74396 74397 74398 74399 74400 74401 74402 74403 74404 74405 74406 74407 74408 74409 74410 74411 74412 74413 74414 74415 74416 74417 74418 74419 74420 74421 74422 74423 74424 74425 74426 74427 74428 74429 74430 74431 74432 74433 74434 74435 74436 74437 74438 74439 74440 74441 74442 74443 74444 74445 74446 74447 74448 74449 74450 74451 74452 74453 74454 74455 74456 74457 74458 74459 74460 74461 74462 74463 74464 74465 74466 74467 74468 74469 74470 74471 74472 74473 74474 74475 74476 74477 74478 74479 74480 74481 74482 74483 74484 74485 74486 74487 74488 74489 74490 74491 74492 74493 74494 74495 74496 74497 74498 74499 74500 74501 74502 74503 74504 74505 74506 74507 74508 74509 74510 74511 74512 74513 74514 74515 74516 74517 74518 74519 74520 74521 74522 74523 74524 74525 74526 74527 74528 74529 74530 74531 74532 74533 74534 74535 74536 74537 74538 74539 74540 74541 74542 74543 74544 74545 74546 74547 74548 74549 74550 74551 74552 74553 74554 74555 74556 74557 74558 74559 74560 74561 74562 74563 74564 74565 74566 74567 74568 74569 74570 74571 74572 74573 74574 74575 74576 74577 74578 74579 74580 74581 74582 74583 74584 74585 74586 74587 74588 74589 74590 74591 74592 74593 74594 74595 74596 74597 74598 74599 74600 74601 74602 74603 74604 74605 74606 74607 74608 74609 74610 74611 74612 74613 74614 74615 74616 74617 74618 74619 74620 74621 74622 74623 74624 74625 74626 74627 74628 74629 74630 74631 74632 74633 74634 74635 74636 74637 74638 74639 74640 74641 74642 74643 74644 74645 74646 74647 74648 74649 74650 74651 74652 74653 74654 74655 74656 74657 74658 74659 74660 74661 74662 74663 74664 74665 74666 74667 74668 74669 74670 74671 74672 74673 74674 74675 74676 74677 74678 74679 74680 74681 74682 74683 74684 74685 74686 74687 74688 74689 74690 74691 74692 74693 74694 74695 74696 74697 74698 74699 74700 74701 74702 74703 74704 74705 74706 74707 74708 74709 74710 74711 74712 74713 74714 74715 74716 74717 74718 74719 74720 74721 74722 74723 74724 74725 74726 74727 74728 74729 74730 74731 74732 74733 74734 74735 74736 74737 74738 74739 74740 74741 74742 74743 74744 74745 74746 74747 74748 74749 74750 74751 74752 74753 74754 74755 74756 74757 74758 74759 74760 74761 74762 74763 74764 74765 74766 74767 74768 74769 74770 74771 74772 74773 74774 74775 74776 74777 74778 74779 74780 74781 74782 74783 74784 74785 74786 74787 74788 74789 74790 74791 74792 74793 74794 74795 74796 74797 74798 74799 74800 74801 74802 74803 74804 74805 74806 74807 74808 74809 74810 74811 74812 74813 74814 74815 74816 74817 74818 74819 74820 74821 74822 74823 74824 74825 74826 74827 74828 74829 74830 74831 74832 74833 74834 74835 74836 74837 74838 74839 74840 74841 74842 74843 74844 74845 74846 74847 74848 74849 74850 74851 74852 74853 74854 74855 74856 74857 74858 74859 74860 74861 74862 74863 74864 74865 74866 74867 74868 74869 74870 74871 74872 74873 74874 74875 74876 74877 74878 74879 74880 74881 74882 74883 74884 74885 74886 74887 74888 74889 74890 74891 74892 74893 74894 74895 74896 74897 74898 74899 74900 74901 74902 74903 74904 74905 74906 74907 74908 74909 74910 74911 74912 74913 74914 74915 74916 74917 74918 74919 74920 74921 74922 74923 74924 74925 74926 74927 74928 74929 74930 74931 74932 74933 74934 74935 74936 74937 74938 74939 74940 74941 74942 74943 74944 74945 74946 74947 74948 74949 74950 74951 74952 74953 74954 74955 74956 74957 74958 74959 74960 74961 74962 74963 74964 74965 74966 74967 74968 74969 74970 74971 74972 74973 74974 74975 74976 74977 74978 74979 74980 74981 74982 74983 74984 74985 74986 74987 74988 74989 74990 74991 74992 74993 74994 74995 74996 74997 74998 74999 75000 75001 75002 75003 75004 75005 75006 75007 75008 75009 75010 75011 75012 75013 75014 75015 75016 75017 75018 75019 75020 75021 75022 75023 75024 75025 75026 75027 75028 75029 75030 75031 75032 75033 75034 75035 75036 75037 75038 75039 75040 75041 75042 75043 75044 75045 75046 75047 75048 75049 75050 75051 75052 75053 75054 75055 75056 75057 75058 75059 75060 75061 75062 75063 75064 75065 75066 75067 75068 75069 75070 75071 75072 75073 75074 75075 75076 75077 75078 75079 75080 75081 75082 75083 75084 75085 75086 75087 75088 75089 75090 75091 75092 75093 75094 75095 75096 75097 75098 75099 75100 75101 75102 75103 75104 75105 75106 75107 75108 75109 75110 75111 75112 75113 75114 75115 75116 75117 75118 75119 75120 75121 75122 75123 75124 75125 75126 75127 75128 75129 75130 75131 75132 75133 75134 75135 75136 75137 75138 75139 75140 75141 75142 75143 75144 75145 75146 75147 75148 75149 75150 75151 75152 75153 75154 75155 75156 75157 75158 75159 75160 75161 75162 75163 75164 75165 75166 75167 75168 75169 75170 75171 75172 75173 75174 75175 75176 75177 75178 75179 75180 75181 75182 75183 75184 75185 75186 75187 75188 75189 75190 75191 75192 75193 75194 75195 75196 75197 75198 75199 75200 75201 75202 75203 75204 75205 75206 75207 75208 75209 75210 75211 75212 75213 75214 75215 75216 75217 75218 75219 75220 75221 75222 75223 75224 75225 75226 75227 75228 75229 75230 75231 75232 75233 75234 75235 75236 75237 75238 75239 75240 75241 75242 75243 75244 75245 75246 75247 75248 75249 75250 75251 75252 75253 75254 75255 75256 75257 75258 75259 75260 75261 75262 75263 75264 75265 75266 75267 75268 75269 75270 75271 75272 75273 75274 75275 75276 75277 75278 75279 75280 75281 75282 75283 75284 75285 75286 75287 75288 75289 75290 75291 75292 75293 75294 75295 75296 75297 75298 75299 75300 75301 75302 75303 75304 75305 75306 75307 75308 75309 75310 75311 75312 75313 75314 75315 75316 75317 75318 75319 75320 75321 75322 75323 75324 75325 75326 75327 75328 75329 75330 75331 75332 75333 75334 75335 75336 75337 75338 75339 75340 75341 75342 75343 75344 75345 75346 75347 75348 75349 75350 75351 75352 75353 75354 75355 75356 75357 75358 75359 75360 75361 75362 75363 75364 75365 75366 75367 75368 75369 75370 75371 75372 75373 75374 75375 75376 75377 75378 75379 75380 75381 75382 75383 75384 75385 75386 75387 75388 75389 75390 75391 75392 75393 75394 75395 75396 75397 75398 75399 75400 75401 75402 75403 75404 75405 75406 75407 75408 75409 75410 75411 75412 75413 75414 75415 75416 75417 75418 75419 75420 75421 75422 75423 75424 75425 75426 75427 75428 75429 75430 75431 75432 75433 75434 75435 75436 75437 75438 75439 75440 75441 75442 75443 75444 75445 75446 75447 75448 75449 75450 75451 75452 75453 75454 75455 75456 75457 75458 75459 75460 75461 75462 75463 75464 75465 75466 75467 75468 75469 75470 75471 75472 75473 75474 75475 75476 75477 75478 75479 75480 75481 75482 75483 75484 75485 75486 75487 75488 75489 75490 75491 75492 75493 75494 75495 75496 75497 75498 75499 75500 75501 75502 75503 75504 75505 75506 75507 75508 75509 75510 75511 75512 75513 75514 75515 75516 75517 75518 75519 75520 75521 75522 75523 75524 75525 75526 75527 75528 75529 75530 75531 75532 75533 75534 75535 75536 75537 75538 75539 75540 75541 75542 75543 75544 75545 75546 75547 75548 75549 75550 75551 75552 75553 75554 75555 75556 75557 75558 75559 75560 75561 75562 75563 75564 75565 75566 75567 75568 75569 75570 75571 75572 75573 75574 75575 75576 75577 75578 75579 75580 75581 75582 75583 75584 75585 75586 75587 75588 75589 75590 75591 75592 75593 75594 75595 75596 75597 75598 75599 75600 75601 75602 75603 75604 75605 75606 75607 75608 75609 75610 75611 75612 75613 75614 75615 75616 75617 75618 75619 75620 75621 75622 75623 75624 75625 75626 75627 75628 75629 75630 75631 75632 75633 75634 75635 75636 75637 75638 75639 75640 75641 75642 75643 75644 75645 75646 75647 75648 75649 75650 75651 75652 75653 75654 75655 75656 75657 75658 75659 75660 75661 75662 75663 75664 75665 75666 75667 75668 75669 75670 75671 75672 75673 75674 75675 75676 75677 75678 75679 75680 75681 75682 75683 75684 75685 75686 75687 75688 75689 75690 75691 75692 75693 75694 75695 75696 75697 75698 75699 75700 75701 75702 75703 75704 75705 75706 75707 75708 75709 75710 75711 75712 75713 75714 75715 75716 75717 75718 75719 75720 75721 75722 75723 75724 75725 75726 75727 75728 75729 75730 75731 75732 75733 75734 75735 75736 75737 75738 75739 75740 75741 75742 75743 75744 75745 75746 75747 75748 75749 75750 75751 75752 75753 75754 75755 75756 75757 75758 75759 75760 75761 75762 75763 75764 75765 75766 75767 75768 75769 75770 75771 75772 75773 75774 75775 75776 75777 75778 75779 75780 75781 75782 75783 75784 75785 75786 75787 75788 75789 75790 75791 75792 75793 75794 75795 75796 75797 75798 75799 75800 75801 75802 75803 75804 75805 75806 75807 75808 75809 75810 75811 75812 75813 75814 75815 75816 75817 75818 75819 75820 75821 75822 75823 75824 75825 75826 75827 75828 75829 75830 75831 75832 75833 75834 75835 75836 75837 75838 75839 75840 75841 75842 75843 75844 75845 75846 75847 75848 75849 75850 75851 75852 75853 75854 75855 75856 75857 75858 75859 75860 75861 75862 75863 75864 75865 75866 75867 75868 75869 75870 75871 75872 75873 75874 75875 75876 75877 75878 75879 75880 75881 75882 75883 75884 75885 75886 75887 75888 75889 75890 75891 75892 75893 75894 75895 75896 75897 75898 75899 75900 75901 75902 75903 75904 75905 75906 75907 75908 75909 75910 75911 75912 75913 75914 75915 75916 75917 75918 75919 75920 75921 75922 75923 75924 75925 75926 75927 75928 75929 75930 75931 75932 75933 75934 75935 75936 75937 75938 75939 75940 75941 75942 75943 75944 75945 75946 75947 75948 75949 75950 75951 75952 75953 75954 75955 75956 75957 75958 75959 75960 75961 75962 75963 75964 75965 75966 75967 75968 75969 75970 75971 75972 75973 75974 75975 75976 75977 75978 75979 75980 75981 75982 75983 75984 75985 75986 75987 75988 75989 75990 75991 75992 75993 75994 75995 75996 75997 75998 75999 76000 76001 76002 76003 76004 76005 76006 76007 76008 76009 76010 76011 76012 76013 76014 76015 76016 76017 76018 76019 76020 76021 76022 76023 76024 76025 76026 76027 76028 76029 76030 76031 76032 76033 76034 76035 76036 76037 76038 76039 76040 76041 76042 76043 76044 76045 76046 76047 76048 76049 76050 76051 76052 76053 76054 76055 76056 76057 76058 76059 76060 76061 76062 76063 76064 76065 76066 76067 76068 76069 76070 76071 76072 76073 76074 76075 76076 76077 76078 76079 76080 76081 76082 76083 76084 76085 76086 76087 76088 76089 76090 76091 76092 76093 76094 76095 76096 76097 76098 76099 76100 76101 76102 76103 76104 76105 76106 76107 76108 76109 76110 76111 76112 76113 76114 76115 76116 76117 76118 76119 76120 76121 76122 76123 76124 76125 76126 76127 76128 76129 76130 76131 76132 76133 76134 76135 76136 76137 76138 76139 76140 76141 76142 76143 76144 76145 76146 76147 76148 76149 76150 76151 76152 76153 76154 76155 76156 76157 76158 76159 76160 76161 76162 76163 76164 76165 76166 76167 76168 76169 76170 76171 76172 76173 76174 76175 76176 76177 76178 76179 76180 76181 76182 76183 76184 76185 76186 76187 76188 76189 76190 76191 76192 76193 76194 76195 76196 76197 76198 76199 76200 76201 76202 76203 76204 76205 76206 76207 76208 76209 76210 76211 76212 76213 76214 76215 76216 76217 76218 76219 76220 76221 76222 76223 76224 76225 76226 76227 76228 76229 76230 76231 76232 76233 76234 76235 76236 76237 76238 76239 76240 76241 76242 76243 76244 76245 76246 76247 76248 76249 76250 76251 76252 76253 76254 76255 76256 76257 76258 76259 76260 76261 76262 76263 76264 76265 76266 76267 76268 76269 76270 76271 76272 76273 76274 76275 76276 76277 76278 76279 76280 76281 76282 76283 76284 76285 76286 76287 76288 76289 76290 76291 76292 76293 76294 76295 76296 76297 76298 76299 76300 76301 76302 76303 76304 76305 76306 76307 76308 76309 76310 76311 76312 76313 76314 76315 76316 76317 76318 76319 76320 76321 76322 76323 76324 76325 76326 76327 76328 76329 76330 76331 76332 76333 76334 76335 76336 76337 76338 76339 76340 76341 76342 76343 76344 76345 76346 76347 76348 76349 76350 76351 76352 76353 76354 76355 76356 76357 76358 76359 76360 76361 76362 76363 76364 76365 76366 76367 76368 76369 76370 76371 76372 76373 76374 76375 76376 76377 76378 76379 76380 76381 76382 76383 76384 76385 76386 76387 76388 76389 76390 76391 76392 76393 76394 76395 76396 76397 76398 76399 76400 76401 76402 76403 76404 76405 76406 76407 76408 76409 76410 76411 76412 76413 76414 76415 76416 76417 76418 76419 76420 76421 76422 76423 76424 76425 76426 76427 76428 76429 76430 76431 76432 76433 76434 76435 76436 76437 76438 76439 76440 76441 76442 76443 76444 76445 76446 76447 76448 76449 76450 76451 76452 76453 76454 76455 76456 76457 76458 76459 76460 76461 76462 76463 76464 76465 76466 76467 76468 76469 76470 76471 76472 76473 76474 76475 76476 76477 76478 76479 76480 76481 76482 76483 76484 76485 76486 76487 76488 76489 76490 76491 76492 76493 76494 76495 76496 76497 76498 76499 76500 76501 76502 76503 76504 76505 76506 76507 76508 76509 76510 76511 76512 76513 76514 76515 76516 76517 76518 76519 76520 76521 76522 76523 76524 76525 76526 76527 76528 76529 76530 76531 76532 76533 76534 76535 76536 76537 76538 76539 76540 76541 76542 76543 76544 76545 76546 76547 76548 76549 76550 76551 76552 76553 76554 76555 76556 76557 76558 76559 76560 76561 76562 76563 76564 76565 76566 76567 76568 76569 76570 76571 76572 76573 76574 76575 76576 76577 76578 76579 76580 76581 76582 76583 76584 76585 76586 76587 76588 76589 76590 76591 76592 76593 76594 76595 76596 76597 76598 76599 76600 76601 76602 76603 76604 76605 76606 76607 76608 76609 76610 76611 76612 76613 76614 76615 76616 76617 76618 76619 76620 76621 76622 76623 76624 76625 76626 76627 76628 76629 76630 76631 76632 76633 76634 76635 76636 76637 76638 76639 76640 76641 76642 76643 76644 76645 76646 76647 76648 76649 76650 76651 76652 76653 76654 76655 76656 76657 76658 76659 76660 76661 76662 76663 76664 76665 76666 76667 76668 76669 76670 76671 76672 76673 76674 76675 76676 76677 76678 76679 76680 76681 76682 76683 76684 76685 76686 76687 76688 76689 76690 76691 76692 76693 76694 76695 76696 76697 76698 76699 76700 76701 76702 76703 76704 76705 76706 76707 76708 76709 76710 76711 76712 76713 76714 76715 76716 76717 76718 76719 76720 76721 76722 76723 76724 76725 76726 76727 76728 76729 76730 76731 76732 76733 76734 76735 76736 76737 76738 76739 76740 76741 76742 76743 76744 76745 76746 76747 76748 76749 76750 76751 76752 76753 76754 76755 76756 76757 76758 76759 76760 76761 76762 76763 76764 76765 76766 76767 76768 76769 76770 76771 76772 76773 76774 76775 76776 76777 76778 76779 76780 76781 76782 76783 76784 76785 76786 76787 76788 76789 76790 76791 76792 76793 76794 76795 76796 76797 76798 76799 76800 76801 76802 76803 76804 76805 76806 76807 76808 76809 76810 76811 76812 76813 76814 76815 76816 76817 76818 76819 76820 76821 76822 76823 76824 76825 76826 76827 76828 76829 76830 76831 76832 76833 76834 76835 76836 76837 76838 76839 76840 76841 76842 76843 76844 76845 76846 76847 76848 76849 76850 76851 76852 76853 76854 76855 76856 76857 76858 76859 76860 76861 76862 76863 76864 76865 76866 76867 76868 76869 76870 76871 76872 76873 76874 76875 76876 76877 76878 76879 76880 76881 76882 76883 76884 76885 76886 76887 76888 76889 76890 76891 76892 76893 76894 76895 76896 76897 76898 76899 76900 76901 76902 76903 76904 76905 76906 76907 76908 76909 76910 76911 76912 76913 76914 76915 76916 76917 76918 76919 76920 76921 76922 76923 76924 76925 76926 76927 76928 76929 76930 76931 76932 76933 76934 76935 76936 76937 76938 76939 76940 76941 76942 76943 76944 76945 76946 76947 76948 76949 76950 76951 76952 76953 76954 76955 76956 76957 76958 76959 76960 76961 76962 76963 76964 76965 76966 76967 76968 76969 76970 76971 76972 76973 76974 76975 76976 76977 76978 76979 76980 76981 76982 76983 76984 76985 76986 76987 76988 76989 76990 76991 76992 76993 76994 76995 76996 76997 76998 76999 77000 77001 77002 77003 77004 77005 77006 77007 77008 77009 77010 77011 77012 77013 77014 77015 77016 77017 77018 77019 77020 77021 77022 77023 77024 77025 77026 77027 77028 77029 77030 77031 77032 77033 77034 77035 77036 77037 77038 77039 77040 77041 77042 77043 77044 77045 77046 77047 77048 77049 77050 77051 77052 77053 77054 77055 77056 77057 77058 77059 77060 77061 77062 77063 77064 77065 77066 77067 77068 77069 77070 77071 77072 77073 77074 77075 77076 77077 77078 77079 77080 77081 77082 77083 77084 77085 77086 77087 77088 77089 77090 77091 77092 77093 77094 77095 77096 77097 77098 77099 77100 77101 77102 77103 77104 77105 77106 77107 77108 77109 77110 77111 77112 77113 77114 77115 77116 77117 77118 77119 77120 77121 77122 77123 77124 77125 77126 77127 77128 77129 77130 77131 77132 77133 77134 77135 77136 77137 77138 77139 77140 77141 77142 77143 77144 77145 77146 77147 77148 77149 77150 77151 77152 77153 77154 77155 77156 77157 77158 77159 77160 77161 77162 77163 77164 77165 77166 77167 77168 77169 77170 77171 77172 77173 77174 77175 77176 77177 77178 77179 77180 77181 77182 77183 77184 77185 77186 77187 77188 77189 77190 77191 77192 77193 77194 77195 77196 77197 77198 77199 77200 77201 77202 77203 77204 77205 77206 77207 77208 77209 77210 77211 77212 77213 77214 77215 77216 77217 77218 77219 77220 77221 77222 77223 77224 77225 77226 77227 77228 77229 77230 77231 77232 77233 77234 77235 77236 77237 77238 77239 77240 77241 77242 77243 77244 77245 77246 77247 77248 77249 77250 77251 77252 77253 77254 77255 77256 77257 77258 77259 77260 77261 77262 77263 77264 77265 77266 77267 77268 77269 77270 77271 77272 77273 77274 77275 77276 77277 77278 77279 77280 77281 77282 77283 77284 77285 77286 77287 77288 77289 77290 77291 77292 77293 77294 77295 77296 77297 77298 77299 77300 77301 77302 77303 77304 77305 77306 77307 77308 77309 77310 77311 77312 77313 77314 77315 77316 77317 77318 77319 77320 77321 77322 77323 77324 77325 77326 77327 77328 77329 77330 77331 77332 77333 77334 77335 77336 77337 77338 77339 77340 77341 77342 77343 77344 77345 77346 77347 77348 77349 77350 77351 77352 77353 77354 77355 77356 77357 77358 77359 77360 77361 77362 77363 77364 77365 77366 77367 77368 77369 77370 77371 77372 77373 77374 77375 77376 77377 77378 77379 77380 77381 77382 77383 77384 77385 77386 77387 77388 77389 77390 77391 77392 77393 77394 77395 77396 77397 77398 77399 77400 77401 77402 77403 77404 77405 77406 77407 77408 77409 77410 77411 77412 77413 77414 77415 77416 77417 77418 77419 77420 77421 77422 77423 77424 77425 77426 77427 77428 77429 77430 77431 77432 77433 77434 77435 77436 77437 77438 77439 77440 77441 77442 77443 77444 77445 77446 77447 77448 77449 77450 77451 77452 77453 77454 77455 77456 77457 77458 77459 77460 77461 77462 77463 77464 77465 77466 77467 77468 77469 77470 77471 77472 77473 77474 77475 77476 77477 77478 77479 77480 77481 77482 77483 77484 77485 77486 77487 77488 77489 77490 77491 77492 77493 77494 77495 77496 77497 77498 77499 77500 77501 77502 77503 77504 77505 77506 77507 77508 77509 77510 77511 77512 77513 77514 77515 77516 77517 77518 77519 77520 77521 77522 77523 77524 77525 77526 77527 77528 77529 77530 77531 77532 77533 77534 77535 77536 77537 77538 77539 77540 77541 77542 77543 77544 77545 77546 77547 77548 77549 77550 77551 77552 77553 77554 77555 77556 77557 77558 77559 77560 77561 77562 77563 77564 77565 77566 77567 77568 77569 77570 77571 77572 77573 77574 77575 77576 77577 77578 77579 77580 77581 77582 77583 77584 77585 77586 77587 77588 77589 77590 77591 77592 77593 77594 77595 77596 77597 77598 77599 77600 77601 77602 77603 77604 77605 77606 77607 77608 77609 77610 77611 77612 77613 77614 77615 77616 77617 77618 77619 77620 77621 77622 77623 77624 77625 77626 77627 77628 77629 77630 77631 77632 77633 77634 77635 77636 77637 77638 77639 77640 77641 77642 77643 77644 77645 77646 77647 77648 77649 77650 77651 77652 77653 77654 77655 77656 77657 77658 77659 77660 77661 77662 77663 77664 77665 77666 77667 77668 77669 77670 77671 77672 77673 77674 77675 77676 77677 77678 77679 77680 77681 77682 77683 77684 77685 77686 77687 77688 77689 77690 77691 77692 77693 77694 77695 77696 77697 77698 77699 77700 77701 77702 77703 77704 77705 77706 77707 77708 77709 77710 77711 77712 77713 77714 77715 77716 77717 77718 77719 77720 77721 77722 77723 77724 77725 77726 77727 77728 77729 77730 77731 77732 77733 77734 77735 77736 77737 77738 77739 77740 77741 77742 77743 77744 77745 77746 77747 77748 77749 77750 77751 77752 77753 77754 77755 77756 77757 77758 77759 77760 77761 77762 77763 77764 77765 77766 77767 77768 77769 77770 77771 77772 77773 77774 77775 77776 77777 77778 77779 77780 77781 77782 77783 77784 77785 77786 77787 77788 77789 77790 77791 77792 77793 77794 77795 77796 77797 77798 77799 77800 77801 77802 77803 77804 77805 77806 77807 77808 77809 77810 77811 77812 77813 77814 77815 77816 77817 77818 77819 77820 77821 77822 77823 77824 77825 77826 77827 77828 77829 77830 77831 77832 77833 77834 77835 77836 77837 77838 77839 77840 77841 77842 77843 77844 77845 77846 77847 77848 77849 77850 77851 77852 77853 77854 77855 77856 77857 77858 77859 77860 77861 77862 77863 77864 77865 77866 77867 77868 77869 77870 77871 77872 77873 77874 77875 77876 77877 77878 77879 77880 77881 77882 77883 77884 77885 77886 77887 77888 77889 77890 77891 77892 77893 77894 77895 77896 77897 77898 77899 77900 77901 77902 77903 77904 77905 77906 77907 77908 77909 77910 77911 77912 77913 77914 77915 77916 77917 77918 77919 77920 77921 77922 77923 77924 77925 77926 77927 77928 77929 77930 77931 77932 77933 77934 77935 77936 77937 77938 77939 77940 77941 77942 77943 77944 77945 77946 77947 77948 77949 77950 77951 77952 77953 77954 77955 77956 77957 77958 77959 77960 77961 77962 77963 77964 77965 77966 77967 77968 77969 77970 77971 77972 77973 77974 77975 77976 77977 77978 77979 77980 77981 77982 77983 77984 77985 77986 77987 77988 77989 77990 77991 77992 77993 77994 77995 77996 77997 77998 77999 78000 78001 78002 78003 78004 78005 78006 78007 78008 78009 78010 78011 78012 78013 78014 78015 78016 78017 78018 78019 78020 78021 78022 78023 78024 78025 78026 78027 78028 78029 78030 78031 78032 78033 78034 78035 78036 78037 78038 78039 78040 78041 78042 78043 78044 78045 78046 78047 78048 78049 78050 78051 78052 78053 78054 78055 78056 78057 78058 78059 78060 78061 78062 78063 78064 78065 78066 78067 78068 78069 78070 78071 78072 78073 78074 78075 78076 78077 78078 78079 78080 78081 78082 78083 78084 78085 78086 78087 78088 78089 78090 78091 78092 78093 78094 78095 78096 78097 78098 78099 78100 78101 78102 78103 78104 78105 78106 78107 78108 78109 78110 78111 78112 78113 78114 78115 78116 78117 78118 78119 78120 78121 78122 78123 78124 78125 78126 78127 78128 78129 78130 78131 78132 78133 78134 78135 78136 78137 78138 78139 78140 78141 78142 78143 78144 78145 78146 78147 78148 78149 78150 78151 78152 78153 78154 78155 78156 78157 78158 78159 78160 78161 78162 78163 78164 78165 78166 78167 78168 78169 78170 78171 78172 78173 78174 78175 78176 78177 78178 78179 78180 78181 78182 78183 78184 78185 78186 78187 78188 78189 78190 78191 78192 78193 78194 78195 78196 78197 78198 78199 78200 78201 78202 78203 78204 78205 78206 78207 78208 78209 78210 78211 78212 78213 78214 78215 78216 78217 78218 78219 78220 78221 78222 78223 78224 78225 78226 78227 78228 78229 78230 78231 78232 78233 78234 78235 78236 78237 78238 78239 78240 78241 78242 78243 78244 78245 78246 78247 78248 78249 78250 78251 78252 78253 78254 78255 78256 78257 78258 78259 78260 78261 78262 78263 78264 78265 78266 78267 78268 78269 78270 78271 78272 78273 78274 78275 78276 78277 78278 78279 78280 78281 78282 78283 78284 78285 78286 78287 78288 78289 78290 78291 78292 78293 78294 78295 78296 78297 78298 78299 78300 78301 78302 78303 78304 78305 78306 78307 78308 78309 78310 78311 78312 78313 78314 78315 78316 78317 78318 78319 78320 78321 78322 78323 78324 78325 78326 78327 78328 78329 78330 78331 78332 78333 78334 78335 78336 78337 78338 78339 78340 78341 78342 78343 78344 78345 78346 78347 78348 78349 78350 78351 78352 78353 78354 78355 78356 78357 78358 78359 78360 78361 78362 78363 78364 78365 78366 78367 78368 78369 78370 78371 78372 78373 78374 78375 78376 78377 78378 78379 78380 78381 78382 78383 78384 78385 78386 78387 78388 78389 78390 78391 78392 78393 78394 78395 78396 78397 78398 78399 78400 78401 78402 78403 78404 78405 78406 78407 78408 78409 78410 78411 78412 78413 78414 78415 78416 78417 78418 78419 78420 78421 78422 78423 78424 78425 78426 78427 78428 78429 78430 78431 78432 78433 78434 78435 78436 78437 78438 78439 78440 78441 78442 78443 78444 78445 78446 78447 78448 78449 78450 78451 78452 78453 78454 78455 78456 78457 78458 78459 78460 78461 78462 78463 78464 78465 78466 78467 78468 78469 78470 78471 78472 78473 78474 78475 78476 78477 78478 78479 78480 78481 78482 78483 78484 78485 78486 78487 78488 78489 78490 78491 78492 78493 78494 78495 78496 78497 78498 78499 78500 78501 78502 78503 78504 78505 78506 78507 78508 78509 78510 78511 78512 78513 78514 78515 78516 78517 78518 78519 78520 78521 78522 78523 78524 78525 78526 78527 78528 78529 78530 78531 78532 78533 78534 78535 78536 78537 78538 78539 78540 78541 78542 78543 78544 78545 78546 78547 78548 78549 78550 78551 78552 78553 78554 78555 78556 78557 78558 78559 78560 78561 78562 78563 78564 78565 78566 78567 78568 78569 78570 78571 78572 78573 78574 78575 78576 78577 78578 78579 78580 78581 78582 78583 78584 78585 78586 78587 78588 78589 78590 78591 78592 78593 78594 78595 78596 78597 78598 78599 78600 78601 78602 78603 78604 78605 78606 78607 78608 78609 78610 78611 78612 78613 78614 78615 78616 78617 78618 78619 78620 78621 78622 78623 78624 78625 78626 78627 78628 78629 78630 78631 78632 78633 78634 78635 78636 78637 78638 78639 78640 78641 78642 78643 78644 78645 78646 78647 78648 78649 78650 78651 78652 78653 78654 78655 78656 78657 78658 78659 78660 78661 78662 78663 78664 78665 78666 78667 78668 78669 78670 78671 78672 78673 78674 78675 78676 78677 78678 78679 78680 78681 78682 78683 78684 78685 78686 78687 78688 78689 78690 78691 78692 78693 78694 78695 78696 78697 78698 78699 78700 78701 78702 78703 78704 78705 78706 78707 78708 78709 78710 78711 78712 78713 78714 78715 78716 78717 78718 78719 78720 78721 78722 78723 78724 78725 78726 78727 78728 78729 78730 78731 78732 78733 78734 78735 78736 78737 78738 78739 78740 78741 78742 78743 78744 78745 78746 78747 78748 78749 78750 78751 78752 78753 78754 78755 78756 78757 78758 78759 78760 78761 78762 78763 78764 78765 78766 78767 78768 78769 78770 78771 78772 78773 78774 78775 78776 78777 78778 78779 78780 78781 78782 78783 78784 78785 78786 78787 78788 78789 78790 78791 78792 78793 78794 78795 78796 78797 78798 78799 78800 78801 78802 78803 78804 78805 78806 78807 78808 78809 78810 78811 78812 78813 78814 78815 78816 78817 78818 78819 78820 78821 78822 78823 78824 78825 78826 78827 78828 78829 78830 78831 78832 78833 78834 78835 78836 78837 78838 78839 78840 78841 78842 78843 78844 78845 78846 78847 78848 78849 78850 78851 78852 78853 78854 78855 78856 78857 78858 78859 78860 78861 78862 78863 78864 78865 78866 78867 78868 78869 78870 78871 78872 78873 78874 78875 78876 78877 78878 78879 78880 78881 78882 78883 78884 78885 78886 78887 78888 78889 78890 78891 78892 78893 78894 78895 78896 78897 78898 78899 78900 78901 78902 78903 78904 78905 78906 78907 78908 78909 78910 78911 78912 78913 78914 78915 78916 78917 78918 78919 78920 78921 78922 78923 78924 78925 78926 78927 78928 78929 78930 78931 78932 78933 78934 78935 78936 78937 78938 78939 78940 78941 78942 78943 78944 78945 78946 78947 78948 78949 78950 78951 78952 78953 78954 78955 78956 78957 78958 78959 78960 78961 78962 78963 78964 78965 78966 78967 78968 78969 78970 78971 78972 78973 78974 78975 78976 78977 78978 78979 78980 78981 78982 78983 78984 78985 78986 78987 78988 78989 78990 78991 78992 78993 78994 78995 78996 78997 78998 78999 79000 79001 79002 79003 79004 79005 79006 79007 79008 79009 79010 79011 79012 79013 79014 79015 79016 79017 79018 79019 79020 79021 79022 79023 79024 79025 79026 79027 79028 79029 79030 79031 79032 79033 79034 79035 79036 79037 79038 79039 79040 79041 79042 79043 79044 79045 79046 79047 79048 79049 79050 79051 79052 79053 79054 79055 79056 79057 79058 79059 79060 79061 79062 79063 79064 79065 79066 79067 79068 79069 79070 79071 79072 79073 79074 79075 79076 79077 79078 79079 79080 79081 79082 79083 79084 79085 79086 79087 79088 79089 79090 79091 79092 79093 79094 79095 79096 79097 79098 79099 79100 79101 79102 79103 79104 79105 79106 79107 79108 79109 79110 79111 79112 79113 79114 79115 79116 79117 79118 79119 79120 79121 79122 79123 79124 79125 79126 79127 79128 79129 79130 79131 79132 79133 79134 79135 79136 79137 79138 79139 79140 79141 79142 79143 79144 79145 79146 79147 79148 79149 79150 79151 79152 79153 79154 79155 79156 79157 79158 79159 79160 79161 79162 79163 79164 79165 79166 79167 79168 79169 79170 79171 79172 79173 79174 79175 79176 79177 79178 79179 79180 79181 79182 79183 79184 79185 79186 79187 79188 79189 79190 79191 79192 79193 79194 79195 79196 79197 79198 79199 79200 79201 79202 79203 79204 79205 79206 79207 79208 79209 79210 79211 79212 79213 79214 79215 79216 79217 79218 79219 79220 79221 79222 79223 79224 79225 79226 79227 79228 79229 79230 79231 79232 79233 79234 79235 79236 79237 79238 79239 79240 79241 79242 79243 79244 79245 79246 79247 79248 79249 79250 79251 79252 79253 79254 79255 79256 79257 79258 79259 79260 79261 79262 79263 79264 79265 79266 79267 79268 79269 79270 79271 79272 79273 79274 79275 79276 79277 79278 79279 79280 79281 79282 79283 79284 79285 79286 79287 79288 79289 79290 79291 79292 79293 79294 79295 79296 79297 79298 79299 79300 79301 79302 79303 79304 79305 79306 79307 79308 79309 79310 79311 79312 79313 79314 79315 79316 79317 79318 79319 79320 79321 79322 79323 79324 79325 79326 79327 79328 79329 79330 79331 79332 79333 79334 79335 79336 79337 79338 79339 79340 79341 79342 79343 79344 79345 79346 79347 79348 79349 79350 79351 79352 79353 79354 79355 79356 79357 79358 79359 79360 79361 79362 79363 79364 79365 79366 79367 79368 79369 79370 79371 79372 79373 79374 79375 79376 79377 79378 79379 79380 79381 79382 79383 79384 79385 79386 79387 79388 79389 79390 79391 79392 79393 79394 79395 79396 79397 79398 79399 79400 79401 79402 79403 79404 79405 79406 79407 79408 79409 79410 79411 79412 79413 79414 79415 79416 79417 79418 79419 79420 79421 79422 79423 79424 79425 79426 79427 79428 79429 79430 79431 79432 79433 79434 79435 79436 79437 79438 79439 79440 79441 79442 79443 79444 79445 79446 79447 79448 79449 79450 79451 79452 79453 79454 79455 79456 79457 79458 79459 79460 79461 79462 79463 79464 79465 79466 79467 79468 79469 79470 79471 79472 79473 79474 79475 79476 79477 79478 79479 79480 79481 79482 79483 79484 79485 79486 79487 79488 79489 79490 79491 79492 79493 79494 79495 79496 79497 79498 79499 79500 79501 79502 79503 79504 79505 79506 79507 79508 79509 79510 79511 79512 79513 79514 79515 79516 79517 79518 79519 79520 79521 79522 79523 79524 79525 79526 79527 79528 79529 79530 79531 79532 79533 79534 79535 79536 79537 79538 79539 79540 79541 79542 79543 79544 79545 79546 79547 79548 79549 79550 79551 79552 79553 79554 79555 79556 79557 79558 79559 79560 79561 79562 79563 79564 79565 79566 79567 79568 79569 79570 79571 79572 79573 79574 79575 79576 79577 79578 79579 79580 79581 79582 79583 79584 79585 79586 79587 79588 79589 79590 79591 79592 79593 79594 79595 79596 79597 79598 79599 79600 79601 79602 79603 79604 79605 79606 79607 79608 79609 79610 79611 79612 79613 79614 79615 79616 79617 79618 79619 79620 79621 79622 79623 79624 79625 79626 79627 79628 79629 79630 79631 79632 79633 79634 79635 79636 79637 79638 79639 79640 79641 79642 79643 79644 79645 79646 79647 79648 79649 79650 79651 79652 79653 79654 79655 79656 79657 79658 79659 79660 79661 79662 79663 79664 79665 79666 79667 79668 79669 79670 79671 79672 79673 79674 79675 79676 79677 79678 79679 79680 79681 79682 79683 79684 79685 79686 79687 79688 79689 79690 79691 79692 79693 79694 79695 79696 79697 79698 79699 79700 79701 79702 79703 79704 79705 79706 79707 79708 79709 79710 79711 79712 79713 79714 79715 79716 79717 79718 79719 79720 79721 79722 79723 79724 79725 79726 79727 79728 79729 79730 79731 79732 79733 79734 79735 79736 79737 79738 79739 79740 79741 79742 79743 79744 79745 79746 79747 79748 79749 79750 79751 79752 79753 79754 79755 79756 79757 79758 79759 79760 79761 79762 79763 79764 79765 79766 79767 79768 79769 79770 79771 79772 79773 79774 79775 79776 79777 79778 79779 79780 79781 79782 79783 79784 79785 79786 79787 79788 79789 79790 79791 79792 79793 79794 79795 79796 79797 79798 79799 79800 79801 79802 79803 79804 79805 79806 79807 79808 79809 79810 79811 79812 79813 79814 79815 79816 79817 79818 79819 79820 79821 79822 79823 79824 79825 79826 79827 79828 79829 79830 79831 79832 79833 79834 79835 79836 79837 79838 79839 79840 79841 79842 79843 79844 79845 79846 79847 79848 79849 79850 79851 79852 79853 79854 79855 79856 79857 79858 79859 79860 79861 79862 79863 79864 79865 79866 79867 79868 79869 79870 79871 79872 79873 79874 79875 79876 79877 79878 79879 79880 79881 79882 79883 79884 79885 79886 79887 79888 79889 79890 79891 79892 79893 79894 79895 79896 79897 79898 79899 79900 79901 79902 79903 79904 79905 79906 79907 79908 79909 79910 79911 79912 79913 79914 79915 79916 79917 79918 79919 79920 79921 79922 79923 79924 79925 79926 79927 79928 79929 79930 79931 79932 79933 79934 79935 79936 79937 79938 79939 79940 79941 79942 79943 79944 79945 79946 79947 79948 79949 79950 79951 79952 79953 79954 79955 79956 79957 79958 79959 79960 79961 79962 79963 79964 79965 79966 79967 79968 79969 79970 79971 79972 79973 79974 79975 79976 79977 79978 79979 79980 79981 79982 79983 79984 79985 79986 79987 79988 79989 79990 79991 79992 79993 79994 79995 79996 79997 79998 79999 80000 80001 80002 80003 80004 80005 80006 80007 80008 80009 80010 80011 80012 80013 80014 80015 80016 80017 80018 80019 80020 80021 80022 80023 80024 80025 80026 80027 80028 80029 80030 80031 80032 80033 80034 80035 80036 80037 80038 80039 80040 80041 80042 80043 80044 80045 80046 80047 80048 80049 80050 80051 80052 80053 80054 80055 80056 80057 80058 80059 80060 80061 80062 80063 80064 80065 80066 80067 80068 80069 80070 80071 80072 80073 80074 80075 80076 80077 80078 80079 80080 80081 80082 80083 80084 80085 80086 80087 80088 80089 80090 80091 80092 80093 80094 80095 80096 80097 80098 80099 80100 80101 80102 80103 80104 80105 80106 80107 80108 80109 80110 80111 80112 80113 80114 80115 80116 80117 80118 80119 80120 80121 80122 80123 80124 80125 80126 80127 80128 80129 80130 80131 80132 80133 80134 80135 80136 80137 80138 80139 80140 80141 80142 80143 80144 80145 80146 80147 80148 80149 80150 80151 80152 80153 80154 80155 80156 80157 80158 80159 80160 80161 80162 80163 80164 80165 80166 80167 80168 80169 80170 80171 80172 80173 80174 80175 80176 80177 80178 80179 80180 80181 80182 80183 80184 80185 80186 80187 80188 80189 80190 80191 80192 80193 80194 80195 80196 80197 80198 80199 80200 80201 80202 80203 80204 80205 80206 80207 80208 80209 80210 80211 80212 80213 80214 80215 80216 80217 80218 80219 80220 80221 80222 80223 80224 80225 80226 80227 80228 80229 80230 80231 80232 80233 80234 80235 80236 80237 80238 80239 80240 80241 80242 80243 80244 80245 80246 80247 80248 80249 80250 80251 80252 80253 80254 80255 80256 80257 80258 80259 80260 80261 80262 80263 80264 80265 80266 80267 80268 80269 80270 80271 80272 80273 80274 80275 80276 80277 80278 80279 80280 80281 80282 80283 80284 80285 80286 80287 80288 80289 80290 80291 80292 80293 80294 80295 80296 80297 80298 80299 80300 80301 80302 80303 80304 80305 80306 80307 80308 80309 80310 80311 80312 80313 80314 80315 80316 80317 80318 80319 80320 80321 80322 80323 80324 80325 80326 80327 80328 80329 80330 80331 80332 80333 80334 80335 80336 80337 80338 80339 80340 80341 80342 80343 80344 80345 80346 80347 80348 80349 80350 80351 80352 80353 80354 80355 80356 80357 80358 80359 80360 80361 80362 80363 80364 80365 80366 80367 80368 80369 80370 80371 80372 80373 80374 80375 80376 80377 80378 80379 80380 80381 80382 80383 80384 80385 80386 80387 80388 80389 80390 80391 80392 80393 80394 80395 80396 80397 80398 80399 80400 80401 80402 80403 80404 80405 80406 80407 80408 80409 80410 80411 80412 80413 80414 80415 80416 80417 80418 80419 80420 80421 80422 80423 80424 80425 80426 80427 80428 80429 80430 80431 80432 80433 80434 80435 80436 80437 80438 80439 80440 80441 80442 80443 80444 80445 80446 80447 80448 80449 80450 80451 80452 80453 80454 80455 80456 80457 80458 80459 80460 80461 80462 80463 80464 80465 80466 80467 80468 80469 80470 80471 80472 80473 80474 80475 80476 80477 80478 80479 80480 80481 80482 80483 80484 80485 80486 80487 80488 80489 80490 80491 80492 80493 80494 80495 80496 80497 80498 80499 80500 80501 80502 80503 80504 80505 80506 80507 80508 80509 80510 80511 80512 80513 80514 80515 80516 80517 80518 80519 80520 80521 80522 80523 80524 80525 80526 80527 80528 80529 80530 80531 80532 80533 80534 80535 80536 80537 80538 80539 80540 80541 80542 80543 80544 80545 80546 80547 80548 80549 80550 80551 80552 80553 80554 80555 80556 80557 80558 80559 80560 80561 80562 80563 80564 80565 80566 80567 80568 80569 80570 80571 80572 80573 80574 80575 80576 80577 80578 80579 80580 80581 80582 80583 80584 80585 80586 80587 80588 80589 80590 80591 80592 80593 80594 80595 80596 80597 80598 80599 80600 80601 80602 80603 80604 80605 80606 80607 80608 80609 80610 80611 80612 80613 80614 80615 80616 80617 80618 80619 80620 80621 80622 80623 80624 80625 80626 80627 80628 80629 80630 80631 80632 80633 80634 80635 80636 80637 80638 80639 80640 80641 80642 80643 80644 80645 80646 80647 80648 80649 80650 80651 80652 80653 80654 80655 80656 80657 80658 80659 80660 80661 80662 80663 80664 80665 80666 80667 80668 80669 80670 80671 80672 80673 80674 80675 80676 80677 80678 80679 80680 80681 80682 80683 80684 80685 80686 80687 80688 80689 80690 80691 80692 80693 80694 80695 80696 80697 80698 80699 80700 80701 80702 80703 80704 80705 80706 80707 80708 80709 80710 80711 80712 80713 80714 80715 80716 80717 80718 80719 80720 80721 80722 80723 80724 80725 80726 80727 80728 80729 80730 80731 80732 80733 80734 80735 80736 80737 80738 80739 80740 80741 80742 80743 80744 80745 80746 80747 80748 80749 80750 80751 80752 80753 80754 80755 80756 80757 80758 80759 80760 80761 80762 80763 80764 80765 80766 80767 80768 80769 80770 80771 80772 80773 80774 80775 80776 80777 80778 80779 80780 80781 80782 80783 80784 80785 80786 80787 80788 80789 80790 80791 80792 80793 80794 80795 80796 80797 80798 80799 80800 80801 80802 80803 80804 80805 80806 80807 80808 80809 80810 80811 80812 80813 80814 80815 80816 80817 80818 80819 80820 80821 80822 80823 80824 80825 80826 80827 80828 80829 80830 80831 80832 80833 80834 80835 80836 80837 80838 80839 80840 80841 80842 80843 80844 80845 80846 80847 80848 80849 80850 80851 80852 80853 80854 80855 80856 80857 80858 80859 80860 80861 80862 80863 80864 80865 80866 80867 80868 80869 80870 80871 80872 80873 80874 80875 80876 80877 80878 80879 80880 80881 80882 80883 80884 80885 80886 80887 80888 80889 80890 80891 80892 80893 80894 80895 80896 80897 80898 80899 80900 80901 80902 80903 80904 80905 80906 80907 80908 80909 80910 80911 80912 80913 80914 80915 80916 80917 80918 80919 80920 80921 80922 80923 80924 80925 80926 80927 80928 80929 80930 80931 80932 80933 80934 80935 80936 80937 80938 80939 80940 80941 80942 80943 80944 80945 80946 80947 80948 80949 80950 80951 80952 80953 80954 80955 80956 80957 80958 80959 80960 80961 80962 80963 80964 80965 80966 80967 80968 80969 80970 80971 80972 80973 80974 80975 80976 80977 80978 80979 80980 80981 80982 80983 80984 80985 80986 80987 80988 80989 80990 80991 80992 80993 80994 80995 80996 80997 80998 80999 81000 81001 81002 81003 81004 81005 81006 81007 81008 81009 81010 81011 81012 81013 81014 81015 81016 81017 81018 81019 81020 81021 81022 81023 81024 81025 81026 81027 81028 81029 81030 81031 81032 81033 81034 81035 81036 81037 81038 81039 81040 81041 81042 81043 81044 81045 81046 81047 81048 81049 81050 81051 81052 81053 81054 81055 81056 81057 81058 81059 81060 81061 81062 81063 81064 81065 81066 81067 81068 81069 81070 81071 81072 81073 81074 81075 81076 81077 81078 81079 81080 81081 81082 81083 81084 81085 81086 81087 81088 81089 81090 81091 81092 81093 81094 81095 81096 81097 81098 81099 81100 81101 81102 81103 81104 81105 81106 81107 81108 81109 81110 81111 81112 81113 81114 81115 81116 81117 81118 81119 81120 81121 81122 81123 81124 81125 81126 81127 81128 81129 81130 81131 81132 81133 81134 81135 81136 81137 81138 81139 81140 81141 81142 81143 81144 81145 81146 81147 81148 81149 81150 81151 81152 81153 81154 81155 81156 81157 81158 81159 81160 81161 81162 81163 81164 81165 81166 81167 81168 81169 81170 81171 81172 81173 81174 81175 81176 81177 81178 81179 81180 81181 81182 81183 81184 81185 81186 81187 81188 81189 81190 81191 81192 81193 81194 81195 81196 81197 81198 81199 81200 81201 81202 81203 81204 81205 81206 81207 81208 81209 81210 81211 81212 81213 81214 81215 81216 81217 81218 81219 81220 81221 81222 81223 81224 81225 81226 81227 81228 81229 81230 81231 81232 81233 81234 81235 81236 81237 81238 81239 81240 81241 81242 81243 81244 81245 81246 81247 81248 81249 81250 81251 81252 81253 81254 81255 81256 81257 81258 81259 81260 81261 81262 81263 81264 81265 81266 81267 81268 81269 81270 81271 81272 81273 81274 81275 81276 81277 81278 81279 81280 81281 81282 81283 81284 81285 81286 81287 81288 81289 81290 81291 81292 81293 81294 81295 81296 81297 81298 81299 81300 81301 81302 81303 81304 81305 81306 81307 81308 81309 81310 81311 81312 81313 81314 81315 81316 81317 81318 81319 81320 81321 81322 81323 81324 81325 81326 81327 81328 81329 81330 81331 81332 81333 81334 81335 81336 81337 81338 81339 81340 81341 81342 81343 81344 81345 81346 81347 81348 81349 81350 81351 81352 81353 81354 81355 81356 81357 81358 81359 81360 81361 81362 81363 81364 81365 81366 81367 81368 81369 81370 81371 81372 81373 81374 81375 81376 81377 81378 81379 81380 81381 81382 81383 81384 81385 81386 81387 81388 81389 81390 81391 81392 81393 81394 81395 81396 81397 81398 81399 81400 81401 81402 81403 81404 81405 81406 81407 81408 81409 81410 81411 81412 81413 81414 81415 81416 81417 81418 81419 81420 81421 81422 81423 81424 81425 81426 81427 81428 81429 81430 81431 81432 81433 81434 81435 81436 81437 81438 81439 81440 81441 81442 81443 81444 81445 81446 81447 81448 81449 81450 81451 81452 81453 81454 81455 81456 81457 81458 81459 81460 81461 81462 81463 81464 81465 81466 81467 81468 81469 81470 81471 81472 81473 81474 81475 81476 81477 81478 81479 81480 81481 81482 81483 81484 81485 81486 81487 81488 81489 81490 81491 81492 81493 81494 81495 81496 81497 81498 81499 81500 81501 81502 81503 81504 81505 81506 81507 81508 81509 81510 81511 81512 81513 81514 81515 81516 81517 81518 81519 81520 81521 81522 81523 81524 81525 81526 81527 81528 81529 81530 81531 81532 81533 81534 81535 81536 81537 81538 81539 81540 81541 81542 81543 81544 81545 81546 81547 81548 81549 81550 81551 81552 81553 81554 81555 81556 81557 81558 81559 81560 81561 81562 81563 81564 81565 81566 81567 81568 81569 81570 81571 81572 81573 81574 81575 81576 81577 81578 81579 81580 81581 81582 81583 81584 81585 81586 81587 81588 81589 81590 81591 81592 81593 81594 81595 81596 81597 81598 81599 81600 81601 81602 81603 81604 81605 81606 81607 81608 81609 81610 81611 81612 81613 81614 81615 81616 81617 81618 81619 81620 81621 81622 81623 81624 81625 81626 81627 81628 81629 81630 81631 81632 81633 81634 81635 81636 81637 81638 81639 81640 81641 81642 81643 81644 81645 81646 81647 81648 81649 81650 81651 81652 81653 81654 81655 81656 81657 81658 81659 81660 81661 81662 81663 81664 81665 81666 81667 81668 81669 81670 81671 81672 81673 81674 81675 81676 81677 81678 81679 81680 81681 81682 81683 81684 81685 81686 81687 81688 81689 81690 81691 81692 81693 81694 81695 81696 81697 81698 81699 81700 81701 81702 81703 81704 81705 81706 81707 81708 81709 81710 81711 81712 81713 81714 81715 81716 81717 81718 81719 81720 81721 81722 81723 81724 81725 81726 81727 81728 81729 81730 81731 81732 81733 81734 81735 81736 81737 81738 81739 81740 81741 81742 81743 81744 81745 81746 81747 81748 81749 81750 81751 81752 81753 81754 81755 81756 81757 81758 81759 81760 81761 81762 81763 81764 81765 81766 81767 81768 81769 81770 81771 81772 81773 81774 81775 81776 81777 81778 81779 81780 81781 81782 81783 81784 81785 81786 81787 81788 81789 81790 81791 81792 81793 81794 81795 81796 81797 81798 81799 81800 81801 81802 81803 81804 81805 81806 81807 81808 81809 81810 81811 81812 81813 81814 81815 81816 81817 81818 81819 81820 81821 81822 81823 81824 81825 81826 81827 81828 81829 81830 81831 81832 81833 81834 81835 81836 81837 81838 81839 81840 81841 81842 81843 81844 81845 81846 81847 81848 81849 81850 81851 81852 81853 81854 81855 81856 81857 81858 81859 81860 81861 81862 81863 81864 81865 81866 81867 81868 81869 81870 81871 81872 81873 81874 81875 81876 81877 81878 81879 81880 81881 81882 81883 81884 81885 81886 81887 81888 81889 81890 81891 81892 81893 81894 81895 81896 81897 81898 81899 81900 81901 81902 81903 81904 81905 81906 81907 81908 81909 81910 81911 81912 81913 81914 81915 81916 81917 81918 81919 81920 81921 81922 81923 81924 81925 81926 81927 81928 81929 81930 81931 81932 81933 81934 81935 81936 81937 81938 81939 81940 81941 81942 81943 81944 81945 81946 81947 81948 81949 81950 81951 81952 81953 81954 81955 81956 81957 81958 81959 81960 81961 81962 81963 81964 81965 81966 81967 81968 81969 81970 81971 81972 81973 81974 81975 81976 81977 81978 81979 81980 81981 81982 81983 81984 81985 81986 81987 81988 81989 81990 81991 81992 81993 81994 81995 81996 81997 81998 81999 82000 82001 82002 82003 82004 82005 82006 82007 82008 82009 82010 82011 82012 82013 82014 82015 82016 82017 82018 82019 82020 82021 82022 82023 82024 82025 82026 82027 82028 82029 82030 82031 82032 82033 82034 82035 82036 82037 82038 82039 82040 82041 82042 82043 82044 82045 82046 82047 82048 82049 82050 82051 82052 82053 82054 82055 82056 82057 82058 82059 82060 82061 82062 82063 82064 82065 82066 82067 82068 82069 82070 82071 82072 82073 82074 82075 82076 82077 82078 82079 82080 82081 82082 82083 82084 82085 82086 82087 82088 82089 82090 82091 82092 82093 82094 82095 82096 82097 82098 82099 82100 82101 82102 82103 82104 82105 82106 82107 82108 82109 82110 82111 82112 82113 82114 82115 82116 82117 82118 82119 82120 82121 82122 82123 82124 82125 82126 82127 82128 82129 82130 82131 82132 82133 82134 82135 82136 82137 82138 82139 82140 82141 82142 82143 82144 82145 82146 82147 82148 82149 82150 82151 82152 82153 82154 82155 82156 82157 82158 82159 82160 82161 82162 82163 82164 82165 82166 82167 82168 82169 82170 82171 82172 82173 82174 82175 82176 82177 82178 82179 82180 82181 82182 82183 82184 82185 82186 82187 82188 82189 82190 82191 82192 82193 82194 82195 82196 82197 82198 82199 82200 82201 82202 82203 82204 82205 82206 82207 82208 82209 82210 82211 82212 82213 82214 82215 82216 82217 82218 82219 82220 82221 82222 82223 82224 82225 82226 82227 82228 82229 82230 82231 82232 82233 82234 82235 82236 82237 82238 82239 82240 82241 82242 82243 82244 82245 82246 82247 82248 82249 82250 82251 82252 82253 82254 82255 82256 82257 82258 82259 82260 82261 82262 82263 82264 82265 82266 82267 82268 82269 82270 82271 82272 82273 82274 82275 82276 82277 82278 82279 82280 82281 82282 82283 82284 82285 82286 82287 82288 82289 82290 82291 82292 82293 82294 82295 82296 82297 82298 82299 82300 82301 82302 82303 82304 82305 82306 82307 82308 82309 82310 82311 82312 82313 82314 82315 82316 82317 82318 82319 82320 82321 82322 82323 82324 82325 82326 82327 82328 82329 82330 82331 82332 82333 82334 82335 82336 82337 82338 82339 82340 82341 82342 82343 82344 82345 82346 82347 82348 82349 82350 82351 82352 82353 82354 82355 82356 82357 82358 82359 82360 82361 82362 82363 82364 82365 82366 82367 82368 82369 82370 82371 82372 82373 82374 82375 82376 82377 82378 82379 82380 82381 82382 82383 82384 82385 82386 82387 82388 82389 82390 82391 82392 82393 82394 82395 82396 82397 82398 82399 82400 82401 82402 82403 82404 82405 82406 82407 82408 82409 82410 82411 82412 82413 82414 82415 82416 82417 82418 82419 82420 82421 82422 82423 82424 82425 82426 82427 82428 82429 82430 82431 82432 82433 82434 82435 82436 82437 82438 82439 82440 82441 82442 82443 82444 82445 82446 82447 82448 82449 82450 82451 82452 82453 82454 82455 82456 82457 82458 82459 82460 82461 82462 82463 82464 82465 82466 82467 82468 82469 82470 82471 82472 82473 82474 82475 82476 82477 82478 82479 82480 82481 82482 82483 82484 82485 82486 82487 82488 82489 82490 82491 82492 82493 82494 82495 82496 82497 82498 82499 82500 82501 82502 82503 82504 82505 82506 82507 82508 82509 82510 82511 82512 82513 82514 82515 82516 82517 82518 82519 82520 82521 82522 82523 82524 82525 82526 82527 82528 82529 82530 82531 82532 82533 82534 82535 82536 82537 82538 82539 82540 82541 82542 82543 82544 82545 82546 82547 82548 82549 82550 82551 82552 82553 82554 82555 82556 82557 82558 82559 82560 82561 82562 82563 82564 82565 82566 82567 82568 82569 82570 82571 82572 82573 82574 82575 82576 82577 82578 82579 82580 82581 82582 82583 82584 82585 82586 82587 82588 82589 82590 82591 82592 82593 82594 82595 82596 82597 82598 82599 82600 82601 82602 82603 82604 82605 82606 82607 82608 82609 82610 82611 82612 82613 82614 82615 82616 82617 82618 82619 82620 82621 82622 82623 82624 82625 82626 82627 82628 82629 82630 82631 82632 82633 82634 82635 82636 82637 82638 82639 82640 82641 82642 82643 82644 82645 82646 82647 82648 82649 82650 82651 82652 82653 82654 82655 82656 82657 82658 82659 82660 82661 82662 82663 82664 82665 82666 82667 82668 82669 82670 82671 82672 82673 82674 82675 82676 82677 82678 82679 82680 82681 82682 82683 82684 82685 82686 82687 82688 82689 82690 82691 82692 82693 82694 82695 82696 82697 82698 82699 82700 82701 82702 82703 82704 82705 82706 82707 82708 82709 82710 82711 82712 82713 82714 82715 82716 82717 82718 82719 82720 82721 82722 82723 82724 82725 82726 82727 82728 82729 82730 82731 82732 82733 82734 82735 82736 82737 82738 82739 82740 82741 82742 82743 82744 82745 82746 82747 82748 82749 82750 82751 82752 82753 82754 82755 82756 82757 82758 82759 82760 82761 82762 82763 82764 82765 82766 82767 82768 82769 82770 82771 82772 82773 82774 82775 82776 82777 82778 82779 82780 82781 82782 82783 82784 82785 82786 82787 82788 82789 82790 82791 82792 82793 82794 82795 82796 82797 82798 82799 82800 82801 82802 82803 82804 82805 82806 82807 82808 82809 82810 82811 82812 82813 82814 82815 82816 82817 82818 82819 82820 82821 82822 82823 82824 82825 82826 82827 82828 82829 82830 82831 82832 82833 82834 82835 82836 82837 82838 82839 82840 82841 82842 82843 82844 82845 82846 82847 82848 82849 82850 82851 82852 82853 82854 82855 82856 82857 82858 82859 82860 82861 82862 82863 82864 82865 82866 82867 82868 82869 82870 82871 82872 82873 82874 82875 82876 82877 82878 82879 82880 82881 82882 82883 82884 82885 82886 82887 82888 82889 82890 82891 82892 82893 82894 82895 82896 82897 82898 82899 82900 82901 82902 82903 82904 82905 82906 82907 82908 82909 82910 82911 82912 82913 82914 82915 82916 82917 82918 82919 82920 82921 82922 82923 82924 82925 82926 82927 82928 82929 82930 82931 82932 82933 82934 82935 82936 82937 82938 82939 82940 82941 82942 82943 82944 82945 82946 82947 82948 82949 82950 82951 82952 82953 82954 82955 82956 82957 82958 82959 82960 82961 82962 82963 82964 82965 82966 82967 82968 82969 82970 82971 82972 82973 82974 82975 82976 82977 82978 82979 82980 82981 82982 82983 82984 82985 82986 82987 82988 82989 82990 82991 82992 82993 82994 82995 82996 82997 82998 82999 83000 83001 83002 83003 83004 83005 83006 83007 83008 83009 83010 83011 83012 83013 83014 83015 83016 83017 83018 83019 83020 83021 83022 83023 83024 83025 83026 83027 83028 83029 83030 83031 83032 83033 83034 83035 83036 83037 83038 83039 83040 83041 83042 83043 83044 83045 83046 83047 83048 83049 83050 83051 83052 83053 83054 83055 83056 83057 83058 83059 83060 83061 83062 83063 83064 83065 83066 83067 83068 83069 83070 83071 83072 83073 83074 83075 83076 83077 83078 83079 83080 83081 83082 83083 83084 83085 83086 83087 83088 83089 83090 83091 83092 83093 83094 83095 83096 83097 83098 83099 83100 83101 83102 83103 83104 83105 83106 83107 83108 83109 83110 83111 83112 83113 83114 83115 83116 83117 83118 83119 83120 83121 83122 83123 83124 83125 83126 83127 83128 83129 83130 83131 83132 83133 83134 83135 83136 83137 83138 83139 83140 83141 83142 83143 83144 83145 83146 83147 83148 83149 83150 83151 83152 83153 83154 83155 83156 83157 83158 83159 83160 83161 83162 83163 83164 83165 83166 83167 83168 83169 83170 83171 83172 83173 83174 83175 83176 83177 83178 83179 83180 83181 83182 83183 83184 83185 83186 83187 83188 83189 83190 83191 83192 83193 83194 83195 83196 83197 83198 83199 83200 83201 83202 83203 83204 83205 83206 83207 83208 83209 83210 83211 83212 83213 83214 83215 83216 83217 83218 83219 83220 83221 83222 83223 83224 83225 83226 83227 83228 83229 83230 83231 83232 83233 83234 83235 83236 83237 83238 83239 83240 83241 83242 83243 83244 83245 83246 83247 83248 83249 83250 83251 83252 83253 83254 83255 83256 83257 83258 83259 83260 83261 83262 83263 83264 83265 83266 83267 83268 83269 83270 83271 83272 83273 83274 83275 83276 83277 83278 83279 83280 83281 83282 83283 83284 83285 83286 83287 83288 83289 83290 83291 83292 83293 83294 83295 83296 83297 83298 83299 83300 83301 83302 83303 83304 83305 83306 83307 83308 83309 83310 83311 83312 83313 83314 83315 83316 83317 83318 83319 83320 83321 83322 83323 83324 83325 83326 83327 83328 83329 83330 83331 83332 83333 83334 83335 83336 83337 83338 83339 83340 83341 83342 83343 83344 83345 83346 83347 83348 83349 83350 83351 83352 83353 83354 83355 83356 83357 83358 83359 83360 83361 83362 83363 83364 83365 83366 83367 83368 83369 83370 83371 83372 83373 83374 83375 83376 83377 83378 83379 83380 83381 83382 83383 83384 83385 83386 83387 83388 83389 83390 83391 83392 83393 83394 83395 83396 83397 83398 83399 83400 83401 83402 83403 83404 83405 83406 83407 83408 83409 83410 83411 83412 83413 83414 83415 83416 83417 83418 83419 83420 83421 83422 83423 83424 83425 83426 83427 83428 83429 83430 83431 83432 83433 83434 83435 83436 83437 83438 83439 83440 83441 83442 83443 83444 83445 83446 83447 83448 83449 83450 83451 83452 83453 83454 83455 83456 83457 83458 83459 83460 83461 83462 83463 83464 83465 83466 83467 83468 83469 83470 83471 83472 83473 83474 83475 83476 83477 83478 83479 83480 83481 83482 83483 83484 83485 83486 83487 83488 83489 83490 83491 83492 83493 83494 83495 83496 83497 83498 83499 83500 83501 83502 83503 83504 83505 83506 83507 83508 83509 83510 83511 83512 83513 83514 83515 83516 83517 83518 83519 83520 83521 83522 83523 83524 83525 83526 83527 83528 83529 83530 83531 83532 83533 83534 83535 83536 83537 83538 83539 83540 83541 83542 83543 83544 83545 83546 83547 83548 83549 83550 83551 83552 83553 83554 83555 83556 83557 83558 83559 83560 83561 83562 83563 83564 83565 83566 83567 83568 83569 83570 83571 83572 83573 83574 83575 83576 83577 83578 83579 83580 83581 83582 83583 83584 83585 83586 83587 83588 83589 83590 83591 83592 83593 83594 83595 83596 83597 83598 83599 83600 83601 83602 83603 83604 83605 83606 83607 83608 83609 83610 83611 83612 83613 83614 83615 83616 83617 83618 83619 83620 83621 83622 83623 83624 83625 83626 83627 83628 83629 83630 83631 83632 83633 83634 83635 83636 83637 83638 83639 83640 83641 83642 83643 83644 83645 83646 83647 83648 83649 83650 83651 83652 83653 83654 83655 83656 83657 83658 83659 83660 83661 83662 83663 83664 83665 83666 83667 83668 83669 83670 83671 83672 83673 83674 83675 83676 83677 83678 83679 83680 83681 83682 83683 83684 83685 83686 83687 83688 83689 83690 83691 83692 83693 83694 83695 83696 83697 83698 83699 83700 83701 83702 83703 83704 83705 83706 83707 83708 83709 83710 83711 83712 83713 83714 83715 83716 83717 83718 83719 83720 83721 83722 83723 83724 83725 83726 83727 83728 83729 83730 83731 83732 83733 83734 83735 83736 83737 83738 83739 83740 83741 83742 83743 83744 83745 83746 83747 83748 83749 83750 83751 83752 83753 83754 83755 83756 83757 83758 83759 83760 83761 83762 83763 83764 83765 83766 83767 83768 83769 83770 83771 83772 83773 83774 83775 83776 83777 83778 83779 83780 83781 83782 83783 83784 83785 83786 83787 83788 83789 83790 83791 83792 83793 83794 83795 83796 83797 83798 83799 83800 83801 83802 83803 83804 83805 83806 83807 83808 83809 83810 83811 83812 83813 83814 83815 83816 83817 83818 83819 83820 83821 83822 83823 83824 83825 83826 83827 83828 83829 83830 83831 83832 83833 83834 83835 83836 83837 83838 83839 83840 83841 83842 83843 83844 83845 83846 83847 83848 83849 83850 83851 83852 83853 83854 83855 83856 83857 83858 83859 83860 83861 83862 83863 83864 83865 83866 83867 83868 83869 83870 83871 83872 83873 83874 83875 83876 83877 83878 83879 83880 83881 83882 83883 83884 83885 83886 83887 83888 83889 83890 83891 83892 83893 83894 83895 83896 83897 83898 83899 83900 83901 83902 83903 83904 83905 83906 83907 83908 83909 83910 83911 83912 83913 83914 83915 83916 83917 83918 83919 83920 83921 83922 83923 83924 83925 83926 83927 83928 83929 83930 83931 83932 83933 83934 83935 83936 83937 83938 83939 83940 83941 83942 83943 83944 83945 83946 83947 83948 83949 83950 83951 83952 83953 83954 83955 83956 83957 83958 83959 83960 83961 83962 83963 83964 83965 83966 83967 83968 83969 83970 83971 83972 83973 83974 83975 83976 83977 83978 83979 83980 83981 83982 83983 83984 83985 83986 83987 83988 83989 83990 83991 83992 83993 83994 83995 83996 83997 83998 83999 84000 84001 84002 84003 84004 84005 84006 84007 84008 84009 84010 84011 84012 84013 84014 84015 84016 84017 84018 84019 84020 84021 84022 84023 84024 84025 84026 84027 84028 84029 84030 84031 84032 84033 84034 84035 84036 84037 84038 84039 84040 84041 84042 84043 84044 84045 84046 84047 84048 84049 84050 84051 84052 84053 84054 84055 84056 84057 84058 84059 84060 84061 84062 84063 84064 84065 84066 84067 84068 84069 84070 84071 84072 84073 84074 84075 84076 84077 84078 84079 84080 84081 84082 84083 84084 84085 84086 84087 84088 84089 84090 84091 84092 84093 84094 84095 84096 84097 84098 84099 84100 84101 84102 84103 84104 84105 84106 84107 84108 84109 84110 84111 84112 84113 84114 84115 84116 84117 84118 84119 84120 84121 84122 84123 84124 84125 84126 84127 84128 84129 84130 84131 84132 84133 84134 84135 84136 84137 84138 84139 84140 84141 84142 84143 84144 84145 84146 84147 84148 84149 84150 84151 84152 84153 84154 84155 84156 84157 84158 84159 84160 84161 84162 84163 84164 84165 84166 84167 84168 84169 84170 84171 84172 84173 84174 84175 84176 84177 84178 84179 84180 84181 84182 84183 84184 84185 84186 84187 84188 84189 84190 84191 84192 84193 84194 84195 84196 84197 84198 84199 84200 84201 84202 84203 84204 84205 84206 84207 84208 84209 84210 84211 84212 84213 84214 84215 84216 84217 84218 84219 84220 84221 84222 84223 84224 84225 84226 84227 84228 84229 84230 84231 84232 84233 84234 84235 84236 84237 84238 84239 84240 84241 84242 84243 84244 84245 84246 84247 84248 84249 84250 84251 84252 84253 84254 84255 84256 84257 84258 84259 84260 84261 84262 84263 84264 84265 84266 84267 84268 84269 84270 84271 84272 84273 84274 84275 84276 84277 84278 84279 84280 84281 84282 84283 84284 84285 84286 84287 84288 84289 84290 84291 84292 84293 84294 84295 84296 84297 84298 84299 84300 84301 84302 84303 84304 84305 84306 84307 84308 84309 84310 84311 84312 84313 84314 84315 84316 84317 84318 84319 84320 84321 84322 84323 84324 84325 84326 84327 84328 84329 84330 84331 84332 84333 84334 84335 84336 84337 84338 84339 84340 84341 84342 84343 84344 84345 84346 84347 84348 84349 84350 84351 84352 84353 84354 84355 84356 84357 84358 84359 84360 84361 84362 84363 84364 84365 84366 84367 84368 84369 84370 84371 84372 84373 84374 84375 84376 84377 84378 84379 84380 84381 84382 84383 84384 84385 84386 84387 84388 84389 84390 84391 84392 84393 84394 84395 84396 84397 84398 84399 84400 84401 84402 84403 84404 84405 84406 84407 84408 84409 84410 84411 84412 84413 84414 84415 84416 84417 84418 84419 84420 84421 84422 84423 84424 84425 84426 84427 84428 84429 84430 84431 84432 84433 84434 84435 84436 84437 84438 84439 84440 84441 84442 84443 84444 84445 84446 84447 84448 84449 84450 84451 84452 84453 84454 84455 84456 84457 84458 84459 84460 84461 84462 84463 84464 84465 84466 84467 84468 84469 84470 84471 84472 84473 84474 84475 84476 84477 84478 84479 84480 84481 84482 84483 84484 84485 84486 84487 84488 84489 84490 84491 84492 84493 84494 84495 84496 84497 84498 84499 84500 84501 84502 84503 84504 84505 84506 84507 84508 84509 84510 84511 84512 84513 84514 84515 84516 84517 84518 84519 84520 84521 84522 84523 84524 84525 84526 84527 84528 84529 84530 84531 84532 84533 84534 84535 84536 84537 84538 84539 84540 84541 84542 84543 84544 84545 84546 84547 84548 84549 84550 84551 84552 84553 84554 84555 84556 84557 84558 84559 84560 84561 84562 84563 84564 84565 84566 84567 84568 84569 84570 84571 84572 84573 84574 84575 84576 84577 84578 84579 84580 84581 84582 84583 84584 84585 84586 84587 84588 84589 84590 84591 84592 84593 84594 84595 84596 84597 84598 84599 84600 84601 84602 84603 84604 84605 84606 84607 84608 84609 84610 84611 84612 84613 84614 84615 84616 84617 84618 84619 84620 84621 84622 84623 84624 84625 84626 84627 84628 84629 84630 84631 84632 84633 84634 84635 84636 84637 84638 84639 84640 84641 84642 84643 84644 84645 84646 84647 84648 84649 84650 84651 84652 84653 84654 84655 84656 84657 84658 84659 84660 84661 84662 84663 84664 84665 84666 84667 84668 84669 84670 84671 84672 84673 84674 84675 84676 84677 84678 84679 84680 84681 84682 84683 84684 84685 84686 84687 84688 84689 84690 84691 84692 84693 84694 84695 84696 84697 84698 84699 84700 84701 84702 84703 84704 84705 84706 84707 84708 84709 84710 84711 84712 84713 84714 84715 84716 84717 84718 84719 84720 84721 84722 84723 84724 84725 84726 84727 84728 84729 84730 84731 84732 84733 84734 84735 84736 84737 84738 84739 84740 84741 84742 84743 84744 84745 84746 84747 84748 84749 84750 84751 84752 84753 84754 84755 84756 84757 84758 84759 84760 84761 84762 84763 84764 84765 84766 84767 84768 84769 84770 84771 84772 84773 84774 84775 84776 84777 84778 84779 84780 84781 84782 84783 84784 84785 84786 84787 84788 84789 84790 84791 84792 84793 84794 84795 84796 84797 84798 84799 84800 84801 84802 84803 84804 84805 84806 84807 84808 84809 84810 84811 84812 84813 84814 84815 84816 84817 84818 84819 84820 84821 84822 84823 84824 84825 84826 84827 84828 84829 84830 84831 84832 84833 84834 84835 84836 84837 84838 84839 84840 84841 84842 84843 84844 84845 84846 84847 84848 84849 84850 84851 84852 84853 84854 84855 84856 84857 84858 84859 84860 84861 84862 84863 84864 84865 84866 84867 84868 84869 84870 84871 84872 84873 84874 84875 84876 84877 84878 84879 84880 84881 84882 84883 84884 84885 84886 84887 84888 84889 84890 84891 84892 84893 84894 84895 84896 84897 84898 84899 84900 84901 84902 84903 84904 84905 84906 84907 84908 84909 84910 84911 84912 84913 84914 84915 84916 84917 84918 84919 84920 84921 84922 84923 84924 84925 84926 84927 84928 84929 84930 84931 84932 84933 84934 84935 84936 84937 84938 84939 84940 84941 84942 84943 84944 84945 84946 84947 84948 84949 84950 84951 84952 84953 84954 84955 84956 84957 84958 84959 84960 84961 84962 84963 84964 84965 84966 84967 84968 84969 84970 84971 84972 84973 84974 84975 84976 84977 84978 84979 84980 84981 84982 84983 84984 84985 84986 84987 84988 84989 84990 84991 84992 84993 84994 84995 84996 84997 84998 84999 85000 85001 85002 85003 85004 85005 85006 85007 85008 85009 85010 85011 85012 85013 85014 85015 85016 85017 85018 85019 85020 85021 85022 85023 85024 85025 85026 85027 85028 85029 85030 85031 85032 85033 85034 85035 85036 85037 85038 85039 85040 85041 85042 85043 85044 85045 85046 85047 85048 85049 85050 85051 85052 85053 85054 85055 85056 85057 85058 85059 85060 85061 85062 85063 85064 85065 85066 85067 85068 85069 85070 85071 85072 85073 85074 85075 85076 85077 85078 85079 85080 85081 85082 85083 85084 85085 85086 85087 85088 85089 85090 85091 85092 85093 85094 85095 85096 85097 85098 85099 85100 85101 85102 85103 85104 85105 85106 85107 85108 85109 85110 85111 85112 85113 85114 85115 85116 85117 85118 85119 85120 85121 85122 85123 85124 85125 85126 85127 85128 85129 85130 85131 85132 85133 85134 85135 85136 85137 85138 85139 85140 85141 85142 85143 85144 85145 85146 85147 85148 85149 85150 85151 85152 85153 85154 85155 85156 85157 85158 85159 85160 85161 85162 85163 85164 85165 85166 85167 85168 85169 85170 85171 85172 85173 85174 85175 85176 85177 85178 85179 85180 85181 85182 85183 85184 85185 85186 85187 85188 85189 85190 85191 85192 85193 85194 85195 85196 85197 85198 85199 85200 85201 85202 85203 85204 85205 85206 85207 85208 85209 85210 85211 85212 85213 85214 85215 85216 85217 85218 85219 85220 85221 85222 85223 85224 85225 85226 85227 85228 85229 85230 85231 85232 85233 85234 85235 85236 85237 85238 85239 85240 85241 85242 85243 85244 85245 85246 85247 85248 85249 85250 85251 85252 85253 85254 85255 85256 85257 85258 85259 85260 85261 85262 85263 85264 85265 85266 85267 85268 85269 85270 85271 85272 85273 85274 85275 85276 85277 85278 85279 85280 85281 85282 85283 85284 85285 85286 85287 85288 85289 85290 85291 85292 85293 85294 85295 85296 85297 85298 85299 85300 85301 85302 85303 85304 85305 85306 85307 85308 85309 85310 85311 85312 85313 85314 85315 85316 85317 85318 85319 85320 85321 85322 85323 85324 85325 85326 85327 85328 85329 85330 85331 85332 85333 85334 85335 85336 85337 85338 85339 85340 85341 85342 85343 85344 85345 85346 85347 85348 85349 85350 85351 85352 85353 85354 85355 85356 85357 85358 85359 85360 85361 85362 85363 85364 85365 85366 85367 85368 85369 85370 85371 85372 85373 85374 85375 85376 85377 85378 85379 85380 85381 85382 85383 85384 85385 85386 85387 85388 85389 85390 85391 85392 85393 85394 85395 85396 85397 85398 85399 85400 85401 85402 85403 85404 85405 85406 85407 85408 85409 85410 85411 85412 85413 85414 85415 85416 85417 85418 85419 85420 85421 85422 85423 85424 85425 85426 85427 85428 85429 85430 85431 85432 85433 85434 85435 85436 85437 85438 85439 85440 85441 85442 85443 85444 85445 85446 85447 85448 85449 85450 85451 85452 85453 85454 85455 85456 85457 85458 85459 85460 85461 85462 85463 85464 85465 85466 85467 85468 85469 85470 85471 85472 85473 85474 85475 85476 85477 85478 85479 85480 85481 85482 85483 85484 85485 85486 85487 85488 85489 85490 85491 85492 85493 85494 85495 85496 85497 85498 85499 85500 85501 85502 85503 85504 85505 85506 85507 85508 85509 85510 85511 85512 85513 85514 85515 85516 85517 85518 85519 85520 85521 85522 85523 85524 85525 85526 85527 85528 85529 85530 85531 85532 85533 85534 85535 85536 85537 85538 85539 85540 85541 85542 85543 85544 85545 85546 85547 85548 85549 85550 85551 85552 85553 85554 85555 85556 85557 85558 85559 85560 85561 85562 85563 85564 85565 85566 85567 85568 85569 85570 85571 85572 85573 85574 85575 85576 85577 85578 85579 85580 85581 85582 85583 85584 85585 85586 85587 85588 85589 85590 85591 85592 85593 85594 85595 85596 85597 85598 85599 85600 85601 85602 85603 85604 85605 85606 85607 85608 85609 85610 85611 85612 85613 85614 85615 85616 85617 85618 85619 85620 85621 85622 85623 85624 85625 85626 85627 85628 85629 85630 85631 85632 85633 85634 85635 85636 85637 85638 85639 85640 85641 85642 85643 85644 85645 85646 85647 85648 85649 85650 85651 85652 85653 85654 85655 85656 85657 85658 85659 85660 85661 85662 85663 85664 85665 85666 85667 85668 85669 85670 85671 85672 85673 85674 85675 85676 85677 85678 85679 85680 85681 85682 85683 85684 85685 85686 85687 85688 85689 85690 85691 85692 85693 85694 85695 85696 85697 85698 85699 85700 85701 85702 85703 85704 85705 85706 85707 85708 85709 85710 85711 85712 85713 85714 85715 85716 85717 85718 85719 85720 85721 85722 85723 85724 85725 85726 85727 85728 85729 85730 85731 85732 85733 85734 85735 85736 85737 85738 85739 85740 85741 85742 85743 85744 85745 85746 85747 85748 85749 85750 85751 85752 85753 85754 85755 85756 85757 85758 85759 85760 85761 85762 85763 85764 85765 85766 85767 85768 85769 85770 85771 85772 85773 85774 85775 85776 85777 85778 85779 85780 85781 85782 85783 85784 85785 85786 85787 85788 85789 85790 85791 85792 85793 85794 85795 85796 85797 85798 85799 85800 85801 85802 85803 85804 85805 85806 85807 85808 85809 85810 85811 85812 85813 85814 85815 85816 85817 85818 85819 85820 85821 85822 85823 85824 85825 85826 85827 85828 85829 85830 85831 85832 85833 85834 85835 85836 85837 85838 85839 85840 85841 85842 85843 85844 85845 85846 85847 85848 85849 85850 85851 85852 85853 85854 85855 85856 85857 85858 85859 85860 85861 85862 85863 85864 85865 85866 85867 85868 85869 85870 85871 85872 85873 85874 85875 85876 85877 85878 85879 85880 85881 85882 85883 85884 85885 85886 85887 85888 85889 85890 85891 85892 85893 85894 85895 85896 85897 85898 85899 85900 85901 85902 85903 85904 85905 85906 85907 85908 85909 85910 85911 85912 85913 85914 85915 85916 85917 85918 85919 85920 85921 85922 85923 85924 85925 85926 85927 85928 85929 85930 85931 85932 85933 85934 85935 85936 85937 85938 85939 85940 85941 85942 85943 85944 85945 85946 85947 85948 85949 85950 85951 85952 85953 85954 85955 85956 85957 85958 85959 85960 85961 85962 85963 85964 85965 85966 85967 85968 85969 85970 85971 85972 85973 85974 85975 85976 85977 85978 85979 85980 85981 85982 85983 85984 85985 85986 85987 85988 85989 85990 85991 85992 85993 85994 85995 85996 85997 85998 85999 86000 86001 86002 86003 86004 86005 86006 86007 86008 86009 86010 86011 86012 86013 86014 86015 86016 86017 86018 86019 86020 86021 86022 86023 86024 86025 86026 86027 86028 86029 86030 86031 86032 86033 86034 86035 86036 86037 86038 86039 86040 86041 86042 86043 86044 86045 86046 86047 86048 86049 86050 86051 86052 86053 86054 86055 86056 86057 86058 86059 86060 86061 86062 86063 86064 86065 86066 86067 86068 86069 86070 86071 86072 86073 86074 86075 86076 86077 86078 86079 86080 86081 86082 86083 86084 86085 86086 86087 86088 86089 86090 86091 86092 86093 86094 86095 86096 86097 86098 86099 86100 86101 86102 86103 86104 86105 86106 86107 86108 86109 86110 86111 86112 86113 86114 86115 86116 86117 86118 86119 86120 86121 86122 86123 86124 86125 86126 86127 86128 86129 86130 86131 86132 86133 86134 86135 86136 86137 86138 86139 86140 86141 86142 86143 86144 86145 86146 86147 86148 86149 86150 86151 86152 86153 86154 86155 86156 86157 86158 86159 86160 86161 86162 86163 86164 86165 86166 86167 86168 86169 86170 86171 86172 86173 86174 86175 86176 86177 86178 86179 86180 86181 86182 86183 86184 86185 86186 86187 86188 86189 86190 86191 86192 86193 86194 86195 86196 86197 86198 86199 86200 86201 86202 86203 86204 86205 86206 86207 86208 86209 86210 86211 86212 86213 86214 86215 86216 86217 86218 86219 86220 86221 86222 86223 86224 86225 86226 86227 86228 86229 86230 86231 86232 86233 86234 86235 86236 86237 86238 86239 86240 86241 86242 86243 86244 86245 86246 86247 86248 86249 86250 86251 86252 86253 86254 86255 86256 86257 86258 86259 86260 86261 86262 86263 86264 86265 86266 86267 86268 86269 86270 86271 86272 86273 86274 86275 86276 86277 86278 86279 86280 86281 86282 86283 86284 86285 86286 86287 86288 86289 86290 86291 86292 86293 86294 86295 86296 86297 86298 86299 86300 86301 86302 86303 86304 86305 86306 86307 86308 86309 86310 86311 86312 86313 86314 86315 86316 86317 86318 86319 86320 86321 86322 86323 86324 86325 86326 86327 86328 86329 86330 86331 86332 86333 86334 86335 86336 86337 86338 86339 86340 86341 86342 86343 86344 86345 86346 86347 86348 86349 86350 86351 86352 86353 86354 86355 86356 86357 86358 86359 86360 86361 86362 86363 86364 86365 86366 86367 86368 86369 86370 86371 86372 86373 86374 86375 86376 86377 86378 86379 86380 86381 86382 86383 86384 86385 86386 86387 86388 86389 86390 86391 86392 86393 86394 86395 86396 86397 86398 86399 86400 86401 86402 86403 86404 86405 86406 86407 86408 86409 86410 86411 86412 86413 86414 86415 86416 86417 86418 86419 86420 86421 86422 86423 86424 86425 86426 86427 86428 86429 86430 86431 86432 86433 86434 86435 86436 86437 86438 86439 86440 86441 86442 86443 86444 86445 86446 86447 86448 86449 86450 86451 86452 86453 86454 86455 86456 86457 86458 86459 86460 86461 86462 86463 86464 86465 86466 86467 86468 86469 86470 86471 86472 86473 86474 86475 86476 86477 86478 86479 86480 86481 86482 86483 86484 86485 86486 86487 86488 86489 86490 86491 86492 86493 86494 86495 86496 86497 86498 86499 86500 86501 86502 86503 86504 86505 86506 86507 86508 86509 86510 86511 86512 86513 86514 86515 86516 86517 86518 86519 86520 86521 86522 86523 86524 86525 86526 86527 86528 86529 86530 86531 86532 86533 86534 86535 86536 86537 86538 86539 86540 86541 86542 86543 86544 86545 86546 86547 86548 86549 86550 86551 86552 86553 86554 86555 86556 86557 86558 86559 86560 86561 86562 86563 86564 86565 86566 86567 86568 86569 86570 86571 86572 86573 86574 86575 86576 86577 86578 86579 86580 86581 86582 86583 86584 86585 86586 86587 86588 86589 86590 86591 86592 86593 86594 86595 86596 86597 86598 86599 86600 86601 86602 86603 86604 86605 86606 86607 86608 86609 86610 86611 86612 86613 86614 86615 86616 86617 86618 86619 86620 86621 86622 86623 86624 86625 86626 86627 86628 86629 86630 86631 86632 86633 86634 86635 86636 86637 86638 86639 86640 86641 86642 86643 86644 86645 86646 86647 86648 86649 86650 86651 86652 86653 86654 86655 86656 86657 86658 86659 86660 86661 86662 86663 86664 86665 86666 86667 86668 86669 86670 86671 86672 86673 86674 86675 86676 86677 86678 86679 86680 86681 86682 86683 86684 86685 86686 86687 86688 86689 86690 86691 86692 86693 86694 86695 86696 86697 86698 86699 86700 86701 86702 86703 86704 86705 86706 86707 86708 86709 86710 86711 86712 86713 86714 86715 86716 86717 86718 86719 86720 86721 86722 86723 86724 86725 86726 86727 86728 86729 86730 86731 86732 86733 86734 86735 86736 86737 86738 86739 86740 86741 86742 86743 86744 86745 86746 86747 86748 86749 86750 86751 86752 86753 86754 86755 86756 86757 86758 86759 86760 86761 86762 86763 86764 86765 86766 86767 86768 86769 86770 86771 86772 86773 86774 86775 86776 86777 86778 86779 86780 86781 86782 86783 86784 86785 86786 86787 86788 86789 86790 86791 86792 86793 86794 86795 86796 86797 86798 86799 86800 86801 86802 86803 86804 86805 86806 86807 86808 86809 86810 86811 86812 86813 86814 86815 86816 86817 86818 86819 86820 86821 86822 86823 86824 86825 86826 86827 86828 86829 86830 86831 86832 86833 86834 86835 86836 86837 86838 86839 86840 86841 86842 86843 86844 86845 86846 86847 86848 86849 86850 86851 86852 86853 86854 86855 86856 86857 86858 86859 86860 86861 86862 86863 86864 86865 86866 86867 86868 86869 86870 86871 86872 86873 86874 86875 86876 86877 86878 86879 86880 86881 86882 86883 86884 86885 86886 86887 86888 86889 86890 86891 86892 86893 86894 86895 86896 86897 86898 86899 86900 86901 86902 86903 86904 86905 86906 86907 86908 86909 86910 86911 86912 86913 86914 86915 86916 86917 86918 86919 86920 86921 86922 86923 86924 86925 86926 86927 86928 86929 86930 86931 86932 86933 86934 86935 86936 86937 86938 86939 86940 86941 86942 86943 86944 86945 86946 86947 86948 86949 86950 86951 86952 86953 86954 86955 86956 86957 86958 86959 86960 86961 86962 86963 86964 86965 86966 86967 86968 86969 86970 86971 86972 86973 86974 86975 86976 86977 86978 86979 86980 86981 86982 86983 86984 86985 86986 86987 86988 86989 86990 86991 86992 86993 86994 86995 86996 86997 86998 86999 87000 87001 87002 87003 87004 87005 87006 87007 87008 87009 87010 87011 87012 87013 87014 87015 87016 87017 87018 87019 87020 87021 87022 87023 87024 87025 87026 87027 87028 87029 87030 87031 87032 87033 87034 87035 87036 87037 87038 87039 87040 87041 87042 87043 87044 87045 87046 87047 87048 87049 87050 87051 87052 87053 87054 87055 87056 87057 87058 87059 87060 87061 87062 87063 87064 87065 87066 87067 87068 87069 87070 87071 87072 87073 87074 87075 87076 87077 87078 87079 87080 87081 87082 87083 87084 87085 87086 87087 87088 87089 87090 87091 87092 87093 87094 87095 87096 87097 87098 87099 87100 87101 87102 87103 87104 87105 87106 87107 87108 87109 87110 87111 87112 87113 87114 87115 87116 87117 87118 87119 87120 87121 87122 87123 87124 87125 87126 87127 87128 87129 87130 87131 87132 87133 87134 87135 87136 87137 87138 87139 87140 87141 87142 87143 87144 87145 87146 87147 87148 87149 87150 87151 87152 87153 87154 87155 87156 87157 87158 87159 87160 87161 87162 87163 87164 87165 87166 87167 87168 87169 87170 87171 87172 87173 87174 87175 87176 87177 87178 87179 87180 87181 87182 87183 87184 87185 87186 87187 87188 87189 87190 87191 87192 87193 87194 87195 87196 87197 87198 87199 87200 87201 87202 87203 87204 87205 87206 87207 87208 87209 87210 87211 87212 87213 87214 87215 87216 87217 87218 87219 87220 87221 87222 87223 87224 87225 87226 87227 87228 87229 87230 87231 87232 87233 87234 87235 87236 87237 87238 87239 87240 87241 87242 87243 87244 87245 87246 87247 87248 87249 87250 87251 87252 87253 87254 87255 87256 87257 87258 87259 87260 87261 87262 87263 87264 87265 87266 87267 87268 87269 87270 87271 87272 87273 87274 87275 87276 87277 87278 87279 87280 87281 87282 87283 87284 87285 87286 87287 87288 87289 87290 87291 87292 87293 87294 87295 87296 87297 87298 87299 87300 87301 87302 87303 87304 87305 87306 87307 87308 87309 87310 87311 87312 87313 87314 87315 87316 87317 87318 87319 87320 87321 87322 87323 87324 87325 87326 87327 87328 87329 87330 87331 87332 87333 87334 87335 87336 87337 87338 87339 87340 87341 87342 87343 87344 87345 87346 87347 87348 87349 87350 87351 87352 87353 87354 87355 87356 87357 87358 87359 87360 87361 87362 87363 87364 87365 87366 87367 87368 87369 87370 87371 87372 87373 87374 87375 87376 87377 87378 87379 87380 87381 87382 87383 87384 87385 87386 87387 87388 87389 87390 87391 87392 87393 87394 87395 87396 87397 87398 87399 87400 87401 87402 87403 87404 87405 87406 87407 87408 87409 87410 87411 87412 87413 87414 87415 87416 87417 87418 87419 87420 87421 87422 87423 87424 87425 87426 87427 87428 87429 87430 87431 87432 87433 87434 87435 87436 87437 87438 87439 87440 87441 87442 87443 87444 87445 87446 87447 87448 87449 87450 87451 87452 87453 87454 87455 87456 87457 87458 87459 87460 87461 87462 87463 87464 87465 87466 87467 87468 87469 87470 87471 87472 87473 87474 87475 87476 87477 87478 87479 87480 87481 87482 87483 87484 87485 87486 87487 87488 87489 87490 87491 87492 87493 87494 87495 87496 87497 87498 87499 87500 87501 87502 87503 87504 87505 87506 87507 87508 87509 87510 87511 87512 87513 87514 87515 87516 87517 87518 87519 87520 87521 87522 87523 87524 87525 87526 87527 87528 87529 87530 87531 87532 87533 87534 87535 87536 87537 87538 87539 87540 87541 87542 87543 87544 87545 87546 87547 87548 87549 87550 87551 87552 87553 87554 87555 87556 87557 87558 87559 87560 87561 87562 87563 87564 87565 87566 87567 87568 87569 87570 87571 87572 87573 87574 87575 87576 87577 87578 87579 87580 87581 87582 87583 87584 87585 87586 87587 87588 87589 87590 87591 87592 87593 87594 87595 87596 87597 87598 87599 87600 87601 87602 87603 87604 87605 87606 87607 87608 87609 87610 87611 87612 87613 87614 87615 87616 87617 87618 87619 87620 87621 87622 87623 87624 87625 87626 87627 87628 87629 87630 87631 87632 87633 87634 87635 87636 87637 87638 87639 87640 87641 87642 87643 87644 87645 87646 87647 87648 87649 87650 87651 87652 87653 87654 87655 87656 87657 87658 87659 87660 87661 87662 87663 87664 87665 87666 87667 87668 87669 87670 87671 87672 87673 87674 87675 87676 87677 87678 87679 87680 87681 87682 87683 87684 87685 87686 87687 87688 87689 87690 87691 87692 87693 87694 87695 87696 87697 87698 87699 87700 87701 87702 87703 87704 87705 87706 87707 87708 87709 87710 87711 87712 87713 87714 87715 87716 87717 87718 87719 87720 87721 87722 87723 87724 87725 87726 87727 87728 87729 87730 87731 87732 87733 87734 87735 87736 87737 87738 87739 87740 87741 87742 87743 87744 87745 87746 87747 87748 87749 87750 87751 87752 87753 87754 87755 87756 87757 87758 87759 87760 87761 87762 87763 87764 87765 87766 87767 87768 87769 87770 87771 87772 87773 87774 87775 87776 87777 87778 87779 87780 87781 87782 87783 87784 87785 87786 87787 87788 87789 87790 87791 87792 87793 87794 87795 87796 87797 87798 87799 87800 87801 87802 87803 87804 87805 87806 87807 87808 87809 87810 87811 87812 87813 87814 87815 87816 87817 87818 87819 87820 87821 87822 87823 87824 87825 87826 87827 87828 87829 87830 87831 87832 87833 87834 87835 87836 87837 87838 87839 87840 87841 87842 87843 87844 87845 87846 87847 87848 87849 87850 87851 87852 87853 87854 87855 87856 87857 87858 87859 87860 87861 87862 87863 87864 87865 87866 87867 87868 87869 87870 87871 87872 87873 87874 87875 87876 87877 87878 87879 87880 87881 87882 87883 87884 87885 87886 87887 87888 87889 87890 87891 87892 87893 87894 87895 87896 87897 87898 87899 87900 87901 87902 87903 87904 87905 87906 87907 87908 87909 87910 87911 87912 87913 87914 87915 87916 87917 87918 87919 87920 87921 87922 87923 87924 87925 87926 87927 87928 87929 87930 87931 87932 87933 87934 87935 87936 87937 87938 87939 87940 87941 87942 87943 87944 87945 87946 87947 87948 87949 87950 87951 87952 87953 87954 87955 87956 87957 87958 87959 87960 87961 87962 87963 87964 87965 87966 87967 87968 87969 87970 87971 87972 87973 87974 87975 87976 87977 87978 87979 87980 87981 87982 87983 87984 87985 87986 87987 87988 87989 87990 87991 87992 87993 87994 87995 87996 87997 87998 87999 88000 88001 88002 88003 88004 88005 88006 88007 88008 88009 88010 88011 88012 88013 88014 88015 88016 88017 88018 88019 88020 88021 88022 88023 88024 88025 88026 88027 88028 88029 88030 88031 88032 88033 88034 88035 88036 88037 88038 88039 88040 88041 88042 88043 88044 88045 88046 88047 88048 88049 88050 88051 88052 88053 88054 88055 88056 88057 88058 88059 88060 88061 88062 88063 88064 88065 88066 88067 88068 88069 88070 88071 88072 88073 88074 88075 88076 88077 88078 88079 88080 88081 88082 88083 88084 88085 88086 88087 88088 88089 88090 88091 88092 88093 88094 88095 88096 88097 88098 88099 88100 88101 88102 88103 88104 88105 88106 88107 88108 88109 88110 88111 88112 88113 88114 88115 88116 88117 88118 88119 88120 88121 88122 88123 88124 88125 88126 88127 88128 88129 88130 88131 88132 88133 88134 88135 88136 88137 88138 88139 88140 88141 88142 88143 88144 88145 88146 88147 88148 88149 88150 88151 88152 88153 88154 88155 88156 88157 88158 88159 88160 88161 88162 88163 88164 88165 88166 88167 88168 88169 88170 88171 88172 88173 88174 88175 88176 88177 88178 88179 88180 88181 88182 88183 88184 88185 88186 88187 88188 88189 88190 88191 88192 88193 88194 88195 88196 88197 88198 88199 88200 88201 88202 88203 88204 88205 88206 88207 88208 88209 88210 88211 88212 88213 88214 88215 88216 88217 88218 88219 88220 88221 88222 88223 88224 88225 88226 88227 88228 88229 88230 88231 88232 88233 88234 88235 88236 88237 88238 88239 88240 88241 88242 88243 88244 88245 88246 88247 88248 88249 88250 88251 88252 88253 88254 88255 88256 88257 88258 88259 88260 88261 88262 88263 88264 88265 88266 88267 88268 88269 88270 88271 88272 88273 88274 88275 88276 88277 88278 88279 88280 88281 88282 88283 88284 88285 88286 88287 88288 88289 88290 88291 88292 88293 88294 88295 88296 88297 88298 88299 88300 88301 88302 88303 88304 88305 88306 88307 88308 88309 88310 88311 88312 88313 88314 88315 88316 88317 88318 88319 88320 88321 88322 88323 88324 88325 88326 88327 88328 88329 88330 88331 88332 88333 88334 88335 88336 88337 88338 88339 88340 88341 88342 88343 88344 88345 88346 88347 88348 88349 88350 88351 88352 88353 88354 88355 88356 88357 88358 88359 88360 88361 88362 88363 88364 88365 88366 88367 88368 88369 88370 88371 88372 88373 88374 88375 88376 88377 88378 88379 88380 88381 88382 88383 88384 88385 88386 88387 88388 88389 88390 88391 88392 88393 88394 88395 88396 88397 88398 88399 88400 88401 88402 88403 88404 88405 88406 88407 88408 88409 88410 88411 88412 88413 88414 88415 88416 88417 88418 88419 88420 88421 88422 88423 88424 88425 88426 88427 88428 88429 88430 88431 88432 88433 88434 88435 88436 88437 88438 88439 88440 88441 88442 88443 88444 88445 88446 88447 88448 88449 88450 88451 88452 88453 88454 88455 88456 88457 88458 88459 88460 88461 88462 88463 88464 88465 88466 88467 88468 88469 88470 88471 88472 88473 88474 88475 88476 88477 88478 88479 88480 88481 88482 88483 88484 88485 88486 88487 88488 88489 88490 88491 88492 88493 88494 88495 88496 88497 88498 88499 88500 88501 88502 88503 88504 88505 88506 88507 88508 88509 88510 88511 88512 88513 88514 88515 88516 88517 88518 88519 88520 88521 88522 88523 88524 88525 88526 88527 88528 88529 88530 88531 88532 88533 88534 88535 88536 88537 88538 88539 88540 88541 88542 88543 88544 88545 88546 88547 88548 88549 88550 88551 88552 88553 88554 88555 88556 88557 88558 88559 88560 88561 88562 88563 88564 88565 88566 88567 88568 88569 88570 88571 88572 88573 88574 88575 88576 88577 88578 88579 88580 88581 88582 88583 88584 88585 88586 88587 88588 88589 88590 88591 88592 88593 88594 88595 88596 88597 88598 88599 88600 88601 88602 88603 88604 88605 88606 88607 88608 88609 88610 88611 88612 88613 88614 88615 88616 88617 88618 88619 88620 88621 88622 88623 88624 88625 88626 88627 88628 88629 88630 88631 88632 88633 88634 88635 88636 88637 88638 88639 88640 88641 88642 88643 88644 88645 88646 88647 88648 88649 88650 88651 88652 88653 88654 88655 88656 88657 88658 88659 88660 88661 88662 88663 88664 88665 88666 88667 88668 88669 88670 88671 88672 88673 88674 88675 88676 88677 88678 88679 88680 88681 88682 88683 88684 88685 88686 88687 88688 88689 88690 88691 88692 88693 88694 88695 88696 88697 88698 88699 88700 88701 88702 88703 88704 88705 88706 88707 88708 88709 88710 88711 88712 88713 88714 88715 88716 88717 88718 88719 88720 88721 88722 88723 88724 88725 88726 88727 88728 88729 88730 88731 88732 88733 88734 88735 88736 88737 88738 88739 88740 88741 88742 88743 88744 88745 88746 88747 88748 88749 88750 88751 88752 88753 88754 88755 88756 88757 88758 88759 88760 88761 88762 88763 88764 88765 88766 88767 88768 88769 88770 88771 88772 88773 88774 88775 88776 88777 88778 88779 88780 88781 88782 88783 88784 88785 88786 88787 88788 88789 88790 88791 88792 88793 88794 88795 88796 88797 88798 88799 88800 88801 88802 88803 88804 88805 88806 88807 88808 88809 88810 88811 88812 88813 88814 88815 88816 88817 88818 88819 88820 88821 88822 88823 88824 88825 88826 88827 88828 88829 88830 88831 88832 88833 88834 88835 88836 88837 88838 88839 88840 88841 88842 88843 88844 88845 88846 88847 88848 88849 88850 88851 88852 88853 88854 88855 88856 88857 88858 88859 88860 88861 88862 88863 88864 88865 88866 88867 88868 88869 88870 88871 88872 88873 88874 88875 88876 88877 88878 88879 88880 88881 88882 88883 88884 88885 88886 88887 88888 88889 88890 88891 88892 88893 88894 88895 88896 88897 88898 88899 88900 88901 88902 88903 88904 88905 88906 88907 88908 88909 88910 88911 88912 88913 88914 88915 88916 88917 88918 88919 88920 88921 88922 88923 88924 88925 88926 88927 88928 88929 88930 88931 88932 88933 88934 88935 88936 88937 88938 88939 88940 88941 88942 88943 88944 88945 88946 88947 88948 88949 88950 88951 88952 88953 88954 88955 88956 88957 88958 88959 88960 88961 88962 88963 88964 88965 88966 88967 88968 88969 88970 88971 88972 88973 88974 88975 88976 88977 88978 88979 88980 88981 88982 88983 88984 88985 88986 88987 88988 88989 88990 88991 88992 88993 88994 88995 88996 88997 88998 88999 89000 89001 89002 89003 89004 89005 89006 89007 89008 89009 89010 89011 89012 89013 89014 89015 89016 89017 89018 89019 89020 89021 89022 89023 89024 89025 89026 89027 89028 89029 89030 89031 89032 89033 89034 89035 89036 89037 89038 89039 89040 89041 89042 89043 89044 89045 89046 89047 89048 89049 89050 89051 89052 89053 89054 89055 89056 89057 89058 89059 89060 89061 89062 89063 89064 89065 89066 89067 89068 89069 89070 89071 89072 89073 89074 89075 89076 89077 89078 89079 89080 89081 89082 89083 89084 89085 89086 89087 89088 89089 89090 89091 89092 89093 89094 89095 89096 89097 89098 89099 89100 89101 89102 89103 89104 89105 89106 89107 89108 89109 89110 89111 89112 89113 89114 89115 89116 89117 89118 89119 89120 89121 89122 89123 89124 89125 89126 89127 89128 89129 89130 89131 89132 89133 89134 89135 89136 89137 89138 89139 89140 89141 89142 89143 89144 89145 89146 89147 89148 89149 89150 89151 89152 89153 89154 89155 89156 89157 89158 89159 89160 89161 89162 89163 89164 89165 89166 89167 89168 89169 89170 89171 89172 89173 89174 89175 89176 89177 89178 89179 89180 89181 89182 89183 89184 89185 89186 89187 89188 89189 89190 89191 89192 89193 89194 89195 89196 89197 89198 89199 89200 89201 89202 89203 89204 89205 89206 89207 89208 89209 89210 89211 89212 89213 89214 89215 89216 89217 89218 89219 89220 89221 89222 89223 89224 89225 89226 89227 89228 89229 89230 89231 89232 89233 89234 89235 89236 89237 89238 89239 89240 89241 89242 89243 89244 89245 89246 89247 89248 89249 89250 89251 89252 89253 89254 89255 89256 89257 89258 89259 89260 89261 89262 89263 89264 89265 89266 89267 89268 89269 89270 89271 89272 89273 89274 89275 89276 89277 89278 89279 89280 89281 89282 89283 89284 89285 89286 89287 89288 89289 89290 89291 89292 89293 89294 89295 89296 89297 89298 89299 89300 89301 89302 89303 89304 89305 89306 89307 89308 89309 89310 89311 89312 89313 89314 89315 89316 89317 89318 89319 89320 89321 89322 89323 89324 89325 89326 89327 89328 89329 89330 89331 89332 89333 89334 89335 89336 89337 89338 89339 89340 89341 89342 89343 89344 89345 89346 89347 89348 89349 89350 89351 89352 89353 89354 89355 89356 89357 89358 89359 89360 89361 89362 89363 89364 89365 89366 89367 89368 89369 89370 89371 89372 89373 89374 89375 89376 89377 89378 89379 89380 89381 89382 89383 89384 89385 89386 89387 89388 89389 89390 89391 89392 89393 89394 89395 89396 89397 89398 89399 89400 89401 89402 89403 89404 89405 89406 89407 89408 89409 89410 89411 89412 89413 89414 89415 89416 89417 89418 89419 89420 89421 89422 89423 89424 89425 89426 89427 89428 89429 89430 89431 89432 89433 89434 89435 89436 89437 89438 89439 89440 89441 89442 89443 89444 89445 89446 89447 89448 89449 89450 89451 89452 89453 89454 89455 89456 89457 89458 89459 89460 89461 89462 89463 89464 89465 89466 89467 89468 89469 89470 89471 89472 89473 89474 89475 89476 89477 89478 89479 89480 89481 89482 89483 89484 89485 89486 89487 89488 89489 89490 89491 89492 89493 89494 89495 89496 89497 89498 89499 89500 89501 89502 89503 89504 89505 89506 89507 89508 89509 89510 89511 89512 89513 89514 89515 89516 89517 89518 89519 89520 89521 89522 89523 89524 89525 89526 89527 89528 89529 89530 89531 89532 89533 89534 89535 89536 89537 89538 89539 89540 89541 89542 89543 89544 89545 89546 89547 89548 89549 89550 89551 89552 89553 89554 89555 89556 89557 89558 89559 89560 89561 89562 89563 89564 89565 89566 89567 89568 89569 89570 89571 89572 89573 89574 89575 89576 89577 89578 89579 89580 89581 89582 89583 89584 89585 89586 89587 89588 89589 89590 89591 89592 89593 89594 89595 89596 89597 89598 89599 89600 89601 89602 89603 89604 89605 89606 89607 89608 89609 89610 89611 89612 89613 89614 89615 89616 89617 89618 89619 89620 89621 89622 89623 89624 89625 89626 89627 89628 89629 89630 89631 89632 89633 89634 89635 89636 89637 89638 89639 89640 89641 89642 89643 89644 89645 89646 89647 89648 89649 89650 89651 89652 89653 89654 89655 89656 89657 89658 89659 89660 89661 89662 89663 89664 89665 89666 89667 89668 89669 89670 89671 89672 89673 89674 89675 89676 89677 89678 89679 89680 89681 89682 89683 89684 89685 89686 89687 89688 89689 89690 89691 89692 89693 89694 89695 89696 89697 89698 89699 89700 89701 89702 89703 89704 89705 89706 89707 89708 89709 89710 89711 89712 89713 89714 89715 89716 89717 89718 89719 89720 89721 89722 89723 89724 89725 89726 89727 89728 89729 89730 89731 89732 89733 89734 89735 89736 89737 89738 89739 89740 89741 89742 89743 89744 89745 89746 89747 89748 89749 89750 89751 89752 89753 89754 89755 89756 89757 89758 89759 89760 89761 89762 89763 89764 89765 89766 89767 89768 89769 89770 89771 89772 89773 89774 89775 89776 89777 89778 89779 89780 89781 89782 89783 89784 89785 89786 89787 89788 89789 89790 89791 89792 89793 89794 89795 89796 89797 89798 89799 89800 89801 89802 89803 89804 89805 89806 89807 89808 89809 89810 89811 89812 89813 89814 89815 89816 89817 89818 89819 89820 89821 89822 89823 89824 89825 89826 89827 89828 89829 89830 89831 89832 89833 89834 89835 89836 89837 89838 89839 89840 89841 89842 89843 89844 89845 89846 89847 89848 89849 89850 89851 89852 89853 89854 89855 89856 89857 89858 89859 89860 89861 89862 89863 89864 89865 89866 89867 89868 89869 89870 89871 89872 89873 89874 89875 89876 89877 89878 89879 89880 89881 89882 89883 89884 89885 89886 89887 89888 89889 89890 89891 89892 89893 89894 89895 89896 89897 89898 89899 89900 89901 89902 89903 89904 89905 89906 89907 89908 89909 89910 89911 89912 89913 89914 89915 89916 89917 89918 89919 89920 89921 89922 89923 89924 89925 89926 89927 89928 89929 89930 89931 89932 89933 89934 89935 89936 89937 89938 89939 89940 89941 89942 89943 89944 89945 89946 89947 89948 89949 89950 89951 89952 89953 89954 89955 89956 89957 89958 89959 89960 89961 89962 89963 89964 89965 89966 89967 89968 89969 89970 89971 89972 89973 89974 89975 89976 89977 89978 89979 89980 89981 89982 89983 89984 89985 89986 89987 89988 89989 89990 89991 89992 89993 89994 89995 89996 89997 89998 89999 90000 90001 90002 90003 90004 90005 90006 90007 90008 90009 90010 90011 90012 90013 90014 90015 90016 90017 90018 90019 90020 90021 90022 90023 90024 90025 90026 90027 90028 90029 90030 90031 90032 90033 90034 90035 90036 90037 90038 90039 90040 90041 90042 90043 90044 90045 90046 90047 90048 90049 90050 90051 90052 90053 90054 90055 90056 90057 90058 90059 90060 90061 90062 90063 90064 90065 90066 90067 90068 90069 90070 90071 90072 90073 90074 90075 90076 90077 90078 90079 90080 90081 90082 90083 90084 90085 90086 90087 90088 90089 90090 90091 90092 90093 90094 90095 90096 90097 90098 90099 90100 90101 90102 90103 90104 90105 90106 90107 90108 90109 90110 90111 90112 90113 90114 90115 90116 90117 90118 90119 90120 90121 90122 90123 90124 90125 90126 90127 90128 90129 90130 90131 90132 90133 90134 90135 90136 90137 90138 90139 90140 90141 90142 90143 90144 90145 90146 90147 90148 90149 90150 90151 90152 90153 90154 90155 90156 90157 90158 90159 90160 90161 90162 90163 90164 90165 90166 90167 90168 90169 90170 90171 90172 90173 90174 90175 90176 90177 90178 90179 90180 90181 90182 90183 90184 90185 90186 90187 90188 90189 90190 90191 90192 90193 90194 90195 90196 90197 90198 90199 90200 90201 90202 90203 90204 90205 90206 90207 90208 90209 90210 90211 90212 90213 90214 90215 90216 90217 90218 90219 90220 90221 90222 90223 90224 90225 90226 90227 90228 90229 90230 90231 90232 90233 90234 90235 90236 90237 90238 90239 90240 90241 90242 90243 90244 90245 90246 90247 90248 90249 90250 90251 90252 90253 90254 90255 90256 90257 90258 90259 90260 90261 90262 90263 90264 90265 90266 90267 90268 90269 90270 90271 90272 90273 90274 90275 90276 90277 90278 90279 90280 90281 90282 90283 90284 90285 90286 90287 90288 90289 90290 90291 90292 90293 90294 90295 90296 90297 90298 90299 90300 90301 90302 90303 90304 90305 90306 90307 90308 90309 90310 90311 90312 90313 90314 90315 90316 90317 90318 90319 90320 90321 90322 90323 90324 90325 90326 90327 90328 90329 90330 90331 90332 90333 90334 90335 90336 90337 90338 90339 90340 90341 90342 90343 90344 90345 90346 90347 90348 90349 90350 90351 90352 90353 90354 90355 90356 90357 90358 90359 90360 90361 90362 90363 90364 90365 90366 90367 90368 90369 90370 90371 90372 90373 90374 90375 90376 90377 90378 90379 90380 90381 90382 90383 90384 90385 90386 90387 90388 90389 90390 90391 90392 90393 90394 90395 90396 90397 90398 90399 90400 90401 90402 90403 90404 90405 90406 90407 90408 90409 90410 90411 90412 90413 90414 90415 90416 90417 90418 90419 90420 90421 90422 90423 90424 90425 90426 90427 90428 90429 90430 90431 90432 90433 90434 90435 90436 90437 90438 90439 90440 90441 90442 90443 90444 90445 90446 90447 90448 90449 90450 90451 90452 90453 90454 90455 90456 90457 90458 90459 90460 90461 90462 90463 90464 90465 90466 90467 90468 90469 90470 90471 90472 90473 90474 90475 90476 90477 90478 90479 90480 90481 90482 90483 90484 90485 90486 90487 90488 90489 90490 90491 90492 90493 90494 90495 90496 90497 90498 90499 90500 90501 90502 90503 90504 90505 90506 90507 90508 90509 90510 90511 90512 90513 90514 90515 90516 90517 90518 90519 90520 90521 90522 90523 90524 90525 90526 90527 90528 90529 90530 90531 90532 90533 90534 90535 90536 90537 90538 90539 90540 90541 90542 90543 90544 90545 90546 90547 90548 90549 90550 90551 90552 90553 90554 90555 90556 90557 90558 90559 90560 90561 90562 90563 90564 90565 90566 90567 90568 90569 90570 90571 90572 90573 90574 90575 90576 90577 90578 90579 90580 90581 90582 90583 90584 90585 90586 90587 90588 90589 90590 90591 90592 90593 90594 90595 90596 90597 90598 90599 90600 90601 90602 90603 90604 90605 90606 90607 90608 90609 90610 90611 90612 90613 90614 90615 90616 90617 90618 90619 90620 90621 90622 90623 90624 90625 90626 90627 90628 90629 90630 90631 90632 90633 90634 90635 90636 90637 90638 90639 90640 90641 90642 90643 90644 90645 90646 90647 90648 90649 90650 90651 90652 90653 90654 90655 90656 90657 90658 90659 90660 90661 90662 90663 90664 90665 90666 90667 90668 90669 90670 90671 90672 90673 90674 90675 90676 90677 90678 90679 90680 90681 90682 90683 90684 90685 90686 90687 90688 90689 90690 90691 90692 90693 90694 90695 90696 90697 90698 90699 90700 90701 90702 90703 90704 90705 90706 90707 90708 90709 90710 90711 90712 90713 90714 90715 90716 90717 90718 90719 90720 90721 90722 90723 90724 90725 90726 90727 90728 90729 90730 90731 90732 90733 90734 90735 90736 90737 90738 90739 90740 90741 90742 90743 90744 90745 90746 90747 90748 90749 90750 90751 90752 90753 90754 90755 90756 90757 90758 90759 90760 90761 90762 90763 90764 90765 90766 90767 90768 90769 90770 90771 90772 90773 90774 90775 90776 90777 90778 90779 90780 90781 90782 90783 90784 90785 90786 90787 90788 90789 90790 90791 90792 90793 90794 90795 90796 90797 90798 90799 90800 90801 90802 90803 90804 90805 90806 90807 90808 90809 90810 90811 90812 90813 90814 90815 90816 90817 90818 90819 90820 90821 90822 90823 90824 90825 90826 90827 90828 90829 90830 90831 90832 90833 90834 90835 90836 90837 90838 90839 90840 90841 90842 90843 90844 90845 90846 90847 90848 90849 90850 90851 90852 90853 90854 90855 90856 90857 90858 90859 90860 90861 90862 90863 90864 90865 90866 90867 90868 90869 90870 90871 90872 90873 90874 90875 90876 90877 90878 90879 90880 90881 90882 90883 90884 90885 90886 90887 90888 90889 90890 90891 90892 90893 90894 90895 90896 90897 90898 90899 90900 90901 90902 90903 90904 90905 90906 90907 90908 90909 90910 90911 90912 90913 90914 90915 90916 90917 90918 90919 90920 90921 90922 90923 90924 90925 90926 90927 90928 90929 90930 90931 90932 90933 90934 90935 90936 90937 90938 90939 90940 90941 90942 90943 90944 90945 90946 90947 90948 90949 90950 90951 90952 90953 90954 90955 90956 90957 90958 90959 90960 90961 90962 90963 90964 90965 90966 90967 90968 90969 90970 90971 90972 90973 90974 90975 90976 90977 90978 90979 90980 90981 90982 90983 90984 90985 90986 90987 90988 90989 90990 90991 90992 90993 90994 90995 90996 90997 90998 90999 91000 91001 91002 91003 91004 91005 91006 91007 91008 91009 91010 91011 91012 91013 91014 91015 91016 91017 91018 91019 91020 91021 91022 91023 91024 91025 91026 91027 91028 91029 91030 91031 91032 91033 91034 91035 91036 91037 91038 91039 91040 91041 91042 91043 91044 91045 91046 91047 91048 91049 91050 91051 91052 91053 91054 91055 91056 91057 91058 91059 91060 91061 91062 91063 91064 91065 91066 91067 91068 91069 91070 91071 91072 91073 91074 91075 91076 91077 91078 91079 91080 91081 91082 91083 91084 91085 91086 91087 91088 91089 91090 91091 91092 91093 91094 91095 91096 91097 91098 91099 91100 91101 91102 91103 91104 91105 91106 91107 91108 91109 91110 91111 91112 91113 91114 91115 91116 91117 91118 91119 91120 91121 91122 91123 91124 91125 91126 91127 91128 91129 91130 91131 91132 91133 91134 91135 91136 91137 91138 91139 91140 91141 91142 91143 91144 91145 91146 91147 91148 91149 91150 91151 91152 91153 91154 91155 91156 91157 91158 91159 91160 91161 91162 91163 91164 91165 91166 91167 91168 91169 91170 91171 91172 91173 91174 91175 91176 91177 91178 91179 91180 91181 91182 91183 91184 91185 91186 91187 91188 91189 91190 91191 91192 91193 91194 91195 91196 91197 91198 91199 91200 91201 91202 91203 91204 91205 91206 91207 91208 91209 91210 91211 91212 91213 91214 91215 91216 91217 91218 91219 91220 91221 91222 91223 91224 91225 91226 91227 91228 91229 91230 91231 91232 91233 91234 91235 91236 91237 91238 91239 91240 91241 91242 91243 91244 91245 91246 91247 91248 91249 91250 91251 91252 91253 91254 91255 91256 91257 91258 91259 91260 91261 91262 91263 91264 91265 91266 91267 91268 91269 91270 91271 91272 91273 91274 91275 91276 91277 91278 91279 91280 91281 91282 91283 91284 91285 91286 91287 91288 91289 91290 91291 91292 91293 91294 91295 91296 91297 91298 91299 91300 91301 91302 91303 91304 91305 91306 91307 91308 91309 91310 91311 91312 91313 91314 91315 91316 91317 91318 91319 91320 91321 91322 91323 91324 91325 91326 91327 91328 91329 91330 91331 91332 91333 91334 91335 91336 91337 91338 91339 91340 91341 91342 91343 91344 91345 91346 91347 91348 91349 91350 91351 91352 91353 91354 91355 91356 91357 91358 91359 91360 91361 91362 91363 91364 91365 91366 91367 91368 91369 91370 91371 91372 91373 91374 91375 91376 91377 91378 91379 91380 91381 91382 91383 91384 91385 91386 91387 91388 91389 91390 91391 91392 91393 91394 91395 91396 91397 91398 91399 91400 91401 91402 91403 91404 91405 91406 91407 91408 91409 91410 91411 91412 91413 91414 91415 91416 91417 91418 91419 91420 91421 91422 91423 91424 91425 91426 91427 91428 91429 91430 91431 91432 91433 91434 91435 91436 91437 91438 91439 91440 91441 91442 91443 91444 91445 91446 91447 91448 91449 91450 91451 91452 91453 91454 91455 91456 91457 91458 91459 91460 91461 91462 91463 91464 91465 91466 91467 91468 91469 91470 91471 91472 91473 91474 91475 91476 91477 91478 91479 91480 91481 91482 91483 91484 91485 91486 91487 91488 91489 91490 91491 91492 91493 91494 91495 91496 91497 91498 91499 91500 91501 91502 91503 91504 91505 91506 91507 91508 91509 91510 91511 91512 91513 91514 91515 91516 91517 91518 91519 91520 91521 91522 91523 91524 91525 91526 91527 91528 91529 91530 91531 91532 91533 91534 91535 91536 91537 91538 91539 91540 91541 91542 91543 91544 91545 91546 91547 91548 91549 91550 91551 91552 91553 91554 91555 91556 91557 91558 91559 91560 91561 91562 91563 91564 91565 91566 91567 91568 91569 91570 91571 91572 91573 91574 91575 91576 91577 91578 91579 91580 91581 91582 91583 91584 91585 91586 91587 91588 91589 91590 91591 91592 91593 91594 91595 91596 91597 91598 91599 91600 91601 91602 91603 91604 91605 91606 91607 91608 91609 91610 91611 91612 91613 91614 91615 91616 91617 91618 91619 91620 91621 91622 91623 91624 91625 91626 91627 91628 91629 91630 91631 91632 91633 91634 91635 91636 91637 91638 91639 91640 91641 91642 91643 91644 91645 91646 91647 91648 91649 91650 91651 91652 91653 91654 91655 91656 91657 91658 91659 91660 91661 91662 91663 91664 91665 91666 91667 91668 91669 91670 91671 91672 91673 91674 91675 91676 91677 91678 91679 91680 91681 91682 91683 91684 91685 91686 91687 91688 91689 91690 91691 91692 91693 91694 91695 91696 91697 91698 91699 91700 91701 91702 91703 91704 91705 91706 91707 91708 91709 91710 91711 91712 91713 91714 91715 91716 91717 91718 91719 91720 91721 91722 91723 91724 91725 91726 91727 91728 91729 91730 91731 91732 91733 91734 91735 91736 91737 91738 91739 91740 91741 91742 91743 91744 91745 91746 91747 91748 91749 91750 91751 91752 91753 91754 91755 91756 91757 91758 91759 91760 91761 91762 91763 91764 91765 91766 91767 91768 91769 91770 91771 91772 91773 91774 91775 91776 91777 91778 91779 91780 91781 91782 91783 91784 91785 91786 91787 91788 91789 91790 91791 91792 91793 91794 91795 91796 91797 91798 91799 91800 91801 91802 91803 91804 91805 91806 91807 91808 91809 91810 91811 91812 91813 91814 91815 91816 91817 91818 91819 91820 91821 91822 91823 91824 91825 91826 91827 91828 91829 91830 91831 91832 91833 91834 91835 91836 91837 91838 91839 91840 91841 91842 91843 91844 91845 91846 91847 91848 91849 91850 91851 91852 91853 91854 91855 91856 91857 91858 91859 91860 91861 91862 91863 91864 91865 91866 91867 91868 91869 91870 91871 91872 91873 91874 91875 91876 91877 91878 91879 91880 91881 91882 91883 91884 91885 91886 91887 91888 91889 91890 91891 91892 91893 91894 91895 91896 91897 91898 91899 91900 91901 91902 91903 91904 91905 91906 91907 91908 91909 91910 91911 91912 91913 91914 91915 91916 91917 91918 91919 91920 91921 91922 91923 91924 91925 91926 91927 91928 91929 91930 91931 91932 91933 91934 91935 91936 91937 91938 91939 91940 91941 91942 91943 91944 91945 91946 91947 91948 91949 91950 91951 91952 91953 91954 91955 91956 91957 91958 91959 91960 91961 91962 91963 91964 91965 91966 91967 91968 91969 91970 91971 91972 91973 91974 91975 91976 91977 91978 91979 91980 91981 91982 91983 91984 91985 91986 91987 91988 91989 91990 91991 91992 91993 91994 91995 91996 91997 91998 91999 92000 92001 92002 92003 92004 92005 92006 92007 92008 92009 92010 92011 92012 92013 92014 92015 92016 92017 92018 92019 92020 92021 92022 92023 92024 92025 92026 92027 92028 92029 92030 92031 92032 92033 92034 92035 92036 92037 92038 92039 92040 92041 92042 92043 92044 92045 92046 92047 92048 92049 92050 92051 92052 92053 92054 92055 92056 92057 92058 92059 92060 92061 92062 92063 92064 92065 92066 92067 92068 92069 92070 92071 92072 92073 92074 92075 92076 92077 92078 92079 92080 92081 92082 92083 92084 92085 92086 92087 92088 92089 92090 92091 92092 92093 92094 92095 92096 92097 92098 92099 92100 92101 92102 92103 92104 92105 92106 92107 92108 92109 92110 92111 92112 92113 92114 92115 92116 92117 92118 92119 92120 92121 92122 92123 92124 92125 92126 92127 92128 92129 92130 92131 92132 92133 92134 92135 92136 92137 92138 92139 92140 92141 92142 92143 92144 92145 92146 92147 92148 92149 92150 92151 92152 92153 92154 92155 92156 92157 92158 92159 92160 92161 92162 92163 92164 92165 92166 92167 92168 92169 92170 92171 92172 92173 92174 92175 92176 92177 92178 92179 92180 92181 92182 92183 92184 92185 92186 92187 92188 92189 92190 92191 92192 92193 92194 92195 92196 92197 92198 92199 92200 92201 92202 92203 92204 92205 92206 92207 92208 92209 92210 92211 92212 92213 92214 92215 92216 92217 92218 92219 92220 92221 92222 92223 92224 92225 92226 92227 92228 92229 92230 92231 92232 92233 92234 92235 92236 92237 92238 92239 92240 92241 92242 92243 92244 92245 92246 92247 92248 92249 92250 92251 92252 92253 92254 92255 92256 92257 92258 92259 92260 92261 92262 92263 92264 92265 92266 92267 92268 92269 92270 92271 92272 92273 92274 92275 92276 92277 92278 92279 92280 92281 92282 92283 92284 92285 92286 92287 92288 92289 92290 92291 92292 92293 92294 92295 92296 92297 92298 92299 92300 92301 92302 92303 92304 92305 92306 92307 92308 92309 92310 92311 92312 92313 92314 92315 92316 92317 92318 92319 92320 92321 92322 92323 92324 92325 92326 92327 92328 92329 92330 92331 92332 92333 92334 92335 92336 92337 92338 92339 92340 92341 92342 92343 92344 92345 92346 92347 92348 92349 92350 92351 92352 92353 92354 92355 92356 92357 92358 92359 92360 92361 92362 92363 92364 92365 92366 92367 92368 92369 92370 92371 92372 92373 92374 92375 92376 92377 92378 92379 92380 92381 92382 92383 92384 92385 92386 92387 92388 92389 92390 92391 92392 92393 92394 92395 92396 92397 92398 92399 92400 92401 92402 92403 92404 92405 92406 92407 92408 92409 92410 92411 92412 92413 92414 92415 92416 92417 92418 92419 92420 92421 92422 92423 92424 92425 92426 92427 92428 92429 92430 92431 92432 92433 92434 92435 92436 92437 92438 92439 92440 92441 92442 92443 92444 92445 92446 92447 92448 92449 92450 92451 92452 92453 92454 92455 92456 92457 92458 92459 92460 92461 92462 92463 92464 92465 92466 92467 92468 92469 92470 92471 92472 92473 92474 92475 92476 92477 92478 92479 92480 92481 92482 92483 92484 92485 92486 92487 92488 92489 92490 92491 92492 92493 92494 92495 92496 92497 92498 92499 92500 92501 92502 92503 92504 92505 92506 92507 92508 92509 92510 92511 92512 92513 92514 92515 92516 92517 92518 92519 92520 92521 92522 92523 92524 92525 92526 92527 92528 92529 92530 92531 92532 92533 92534 92535 92536 92537 92538 92539 92540 92541 92542 92543 92544 92545 92546 92547 92548 92549 92550 92551 92552 92553 92554 92555 92556 92557 92558 92559 92560 92561 92562 92563 92564 92565 92566 92567 92568 92569 92570 92571 92572 92573 92574 92575 92576 92577 92578 92579 92580 92581 92582 92583 92584 92585 92586 92587 92588 92589 92590 92591 92592 92593 92594 92595 92596 92597 92598 92599 92600 92601 92602 92603 92604 92605 92606 92607 92608 92609 92610 92611 92612 92613 92614 92615 92616 92617 92618 92619 92620 92621 92622 92623 92624 92625 92626 92627 92628 92629 92630 92631 92632 92633 92634 92635 92636 92637 92638 92639 92640 92641 92642 92643 92644 92645 92646 92647 92648 92649 92650 92651 92652 92653 92654 92655 92656 92657 92658 92659 92660 92661 92662 92663 92664 92665 92666 92667 92668 92669 92670 92671 92672 92673 92674 92675 92676 92677 92678 92679 92680 92681 92682 92683 92684 92685 92686 92687 92688 92689 92690 92691 92692 92693 92694 92695 92696 92697 92698 92699 92700 92701 92702 92703 92704 92705 92706 92707 92708 92709 92710 92711 92712 92713 92714 92715 92716 92717 92718 92719 92720 92721 92722 92723 92724 92725 92726 92727 92728 92729 92730 92731 92732 92733 92734 92735 92736 92737 92738 92739 92740 92741 92742 92743 92744 92745 92746 92747 92748 92749 92750 92751 92752 92753 92754 92755 92756 92757 92758 92759 92760 92761 92762 92763 92764 92765 92766 92767 92768 92769 92770 92771 92772 92773 92774 92775 92776 92777 92778 92779 92780 92781 92782 92783 92784 92785 92786 92787 92788 92789 92790 92791 92792 92793 92794 92795 92796 92797 92798 92799 92800 92801 92802 92803 92804 92805 92806 92807 92808 92809 92810 92811 92812 92813 92814 92815 92816 92817 92818 92819 92820 92821 92822 92823 92824 92825 92826 92827 92828 92829 92830 92831 92832 92833 92834 92835 92836 92837 92838 92839 92840 92841 92842 92843 92844 92845 92846 92847 92848 92849 92850 92851 92852 92853 92854 92855 92856 92857 92858 92859 92860 92861 92862 92863 92864 92865 92866 92867 92868 92869 92870 92871 92872 92873 92874 92875 92876 92877 92878 92879 92880 92881 92882 92883 92884 92885 92886 92887 92888 92889 92890 92891 92892 92893 92894 92895 92896 92897 92898 92899 92900 92901 92902 92903 92904 92905 92906 92907 92908 92909 92910 92911 92912 92913 92914 92915 92916 92917 92918 92919 92920 92921 92922 92923 92924 92925 92926 92927 92928 92929 92930 92931 92932 92933 92934 92935 92936 92937 92938 92939 92940 92941 92942 92943 92944 92945 92946 92947 92948 92949 92950 92951 92952 92953 92954 92955 92956 92957 92958 92959 92960 92961 92962 92963 92964 92965 92966 92967 92968 92969 92970 92971 92972 92973 92974 92975 92976 92977 92978 92979 92980 92981 92982 92983 92984 92985 92986 92987 92988 92989 92990 92991 92992 92993 92994 92995 92996 92997 92998 92999 93000 93001 93002 93003 93004 93005 93006 93007 93008 93009 93010 93011 93012 93013 93014 93015 93016 93017 93018 93019 93020 93021 93022 93023 93024 93025 93026 93027 93028 93029 93030 93031 93032 93033 93034 93035 93036 93037 93038 93039 93040 93041 93042 93043 93044 93045 93046 93047 93048 93049 93050 93051 93052 93053 93054 93055 93056 93057 93058 93059 93060 93061 93062 93063 93064 93065 93066 93067 93068 93069 93070 93071 93072 93073 93074 93075 93076 93077 93078 93079 93080 93081 93082 93083 93084 93085 93086 93087 93088 93089 93090 93091 93092 93093 93094 93095 93096 93097 93098 93099 93100 93101 93102 93103 93104 93105 93106 93107 93108 93109 93110 93111 93112 93113 93114 93115 93116 93117 93118 93119 93120 93121 93122 93123 93124 93125 93126 93127 93128 93129 93130 93131 93132 93133 93134 93135 93136 93137 93138 93139 93140 93141 93142 93143 93144 93145 93146 93147 93148 93149 93150 93151 93152 93153 93154 93155 93156 93157 93158 93159 93160 93161 93162 93163 93164 93165 93166 93167 93168 93169 93170 93171 93172 93173 93174 93175 93176 93177 93178 93179 93180 93181 93182 93183 93184 93185 93186 93187 93188 93189 93190 93191 93192 93193 93194 93195 93196 93197 93198 93199 93200 93201 93202 93203 93204 93205 93206 93207 93208 93209 93210 93211 93212 93213 93214 93215 93216 93217 93218 93219 93220 93221 93222 93223 93224 93225 93226 93227 93228 93229 93230 93231 93232 93233 93234 93235 93236 93237 93238 93239 93240 93241 93242 93243 93244 93245 93246 93247 93248 93249 93250 93251 93252 93253 93254 93255 93256 93257 93258 93259 93260 93261 93262 93263 93264 93265 93266 93267 93268 93269 93270 93271 93272 93273 93274 93275 93276 93277 93278 93279 93280 93281 93282 93283 93284 93285 93286 93287 93288 93289 93290 93291 93292 93293 93294 93295 93296 93297 93298 93299 93300 93301 93302 93303 93304 93305 93306 93307 93308 93309 93310 93311 93312 93313 93314 93315 93316 93317 93318 93319 93320 93321 93322 93323 93324 93325 93326 93327 93328 93329 93330 93331 93332 93333 93334 93335 93336 93337 93338 93339 93340 93341 93342 93343 93344 93345 93346 93347 93348 93349 93350 93351 93352 93353 93354 93355 93356 93357 93358 93359 93360 93361 93362 93363 93364 93365 93366 93367 93368 93369 93370 93371 93372 93373 93374 93375 93376 93377 93378 93379 93380 93381 93382 93383 93384 93385 93386 93387 93388 93389 93390 93391 93392 93393 93394 93395 93396 93397 93398 93399 93400 93401 93402 93403 93404 93405 93406 93407 93408 93409 93410 93411 93412 93413 93414 93415 93416 93417 93418 93419 93420 93421 93422 93423 93424 93425 93426 93427 93428 93429 93430 93431 93432 93433 93434 93435 93436 93437 93438 93439 93440 93441 93442 93443 93444 93445 93446 93447 93448 93449 93450 93451 93452 93453 93454 93455 93456 93457 93458 93459 93460 93461 93462 93463 93464 93465 93466 93467 93468 93469 93470 93471 93472 93473 93474 93475 93476 93477 93478 93479 93480 93481 93482 93483 93484 93485 93486 93487 93488 93489 93490 93491 93492 93493 93494 93495 93496 93497 93498 93499 93500 93501 93502 93503 93504 93505 93506 93507 93508 93509 93510 93511 93512 93513 93514 93515 93516 93517 93518 93519 93520 93521 93522 93523 93524 93525 93526 93527 93528 93529 93530 93531 93532 93533 93534 93535 93536 93537 93538 93539 93540 93541 93542 93543 93544 93545 93546 93547 93548 93549 93550 93551 93552 93553 93554 93555 93556 93557 93558 93559 93560 93561 93562 93563 93564 93565 93566 93567 93568 93569 93570 93571 93572 93573 93574 93575 93576 93577 93578 93579 93580 93581 93582 93583 93584 93585 93586 93587 93588 93589 93590 93591 93592 93593 93594 93595 93596 93597 93598 93599 93600 93601 93602 93603 93604 93605 93606 93607 93608 93609 93610 93611 93612 93613 93614 93615 93616 93617 93618 93619 93620 93621 93622 93623 93624 93625 93626 93627 93628 93629 93630 93631 93632 93633 93634 93635 93636 93637 93638 93639 93640 93641 93642 93643 93644 93645 93646 93647 93648 93649 93650 93651 93652 93653 93654 93655 93656 93657 93658 93659 93660 93661 93662 93663 93664 93665 93666 93667 93668 93669 93670 93671 93672 93673 93674 93675 93676 93677 93678 93679 93680 93681 93682 93683 93684 93685 93686 93687 93688 93689 93690 93691 93692 93693 93694 93695 93696 93697 93698 93699 93700 93701 93702 93703 93704 93705 93706 93707 93708 93709 93710 93711 93712 93713 93714 93715 93716 93717 93718 93719 93720 93721 93722 93723 93724 93725 93726 93727 93728 93729 93730 93731 93732 93733 93734 93735 93736 93737 93738 93739 93740 93741 93742 93743 93744 93745 93746 93747 93748 93749 93750 93751 93752 93753 93754 93755 93756 93757 93758 93759 93760 93761 93762 93763 93764 93765 93766 93767 93768 93769 93770 93771 93772 93773 93774 93775 93776 93777 93778 93779 93780 93781 93782 93783 93784 93785 93786 93787 93788 93789 93790 93791 93792 93793 93794 93795 93796 93797 93798 93799 93800 93801 93802 93803 93804 93805 93806 93807 93808 93809 93810 93811 93812 93813 93814 93815 93816 93817 93818 93819 93820 93821 93822 93823 93824 93825 93826 93827 93828 93829 93830 93831 93832 93833 93834 93835 93836 93837 93838 93839 93840 93841 93842 93843 93844 93845 93846 93847 93848 93849 93850 93851 93852 93853 93854 93855 93856 93857 93858 93859 93860 93861 93862 93863 93864 93865 93866 93867 93868 93869 93870 93871 93872 93873 93874 93875 93876 93877 93878 93879 93880 93881 93882 93883 93884 93885 93886 93887 93888 93889 93890 93891 93892 93893 93894 93895 93896 93897 93898 93899 93900 93901 93902 93903 93904 93905 93906 93907 93908 93909 93910 93911 93912 93913 93914 93915 93916 93917 93918 93919 93920 93921 93922 93923 93924 93925 93926 93927 93928 93929 93930 93931 93932 93933 93934 93935 93936 93937 93938 93939 93940 93941 93942 93943 93944 93945 93946 93947 93948 93949 93950 93951 93952 93953 93954 93955 93956 93957 93958 93959 93960 93961 93962 93963 93964 93965 93966 93967 93968 93969 93970 93971 93972 93973 93974 93975 93976 93977 93978 93979 93980 93981 93982 93983 93984 93985 93986 93987 93988 93989 93990 93991 93992 93993 93994 93995 93996 93997 93998 93999 94000 94001 94002 94003 94004 94005 94006 94007 94008 94009 94010 94011 94012 94013 94014 94015 94016 94017 94018 94019 94020 94021 94022 94023 94024 94025 94026 94027 94028 94029 94030 94031 94032 94033 94034 94035 94036 94037 94038 94039 94040 94041 94042 94043 94044 94045 94046 94047 94048 94049 94050 94051 94052 94053 94054 94055 94056 94057 94058 94059 94060 94061 94062 94063 94064 94065 94066 94067 94068 94069 94070 94071 94072 94073 94074 94075 94076 94077 94078 94079 94080 94081 94082 94083 94084 94085 94086 94087 94088 94089 94090 94091 94092 94093 94094 94095 94096 94097 94098 94099 94100 94101 94102 94103 94104 94105 94106 94107 94108 94109 94110 94111 94112 94113 94114 94115 94116 94117 94118 94119 94120 94121 94122 94123 94124 94125 94126 94127 94128 94129 94130 94131 94132 94133 94134 94135 94136 94137 94138 94139 94140 94141 94142 94143 94144 94145 94146 94147 94148 94149 94150 94151 94152 94153 94154 94155 94156 94157 94158 94159 94160 94161 94162 94163 94164 94165 94166 94167 94168 94169 94170 94171 94172 94173 94174 94175 94176 94177 94178 94179 94180 94181 94182 94183 94184 94185 94186 94187 94188 94189 94190 94191 94192 94193 94194 94195 94196 94197 94198 94199 94200 94201 94202 94203 94204 94205 94206 94207 94208 94209 94210 94211 94212 94213 94214 94215 94216 94217 94218 94219 94220 94221 94222 94223 94224 94225 94226 94227 94228 94229 94230 94231 94232 94233 94234 94235 94236 94237 94238 94239 94240 94241 94242 94243 94244 94245 94246 94247 94248 94249 94250 94251 94252 94253 94254 94255 94256 94257 94258 94259 94260 94261 94262 94263 94264 94265 94266 94267 94268 94269 94270 94271 94272 94273 94274 94275 94276 94277 94278 94279 94280 94281 94282 94283 94284 94285 94286 94287 94288 94289 94290 94291 94292 94293 94294 94295 94296 94297 94298 94299 94300 94301 94302 94303 94304 94305 94306 94307 94308 94309 94310 94311 94312 94313 94314 94315 94316 94317 94318 94319 94320 94321 94322 94323 94324 94325 94326 94327 94328 94329 94330 94331 94332 94333 94334 94335 94336 94337 94338 94339 94340 94341 94342 94343 94344 94345 94346 94347 94348 94349 94350 94351 94352 94353 94354 94355 94356 94357 94358 94359 94360 94361 94362 94363 94364 94365 94366 94367 94368 94369 94370 94371 94372 94373 94374 94375 94376 94377 94378 94379 94380 94381 94382 94383 94384 94385 94386 94387 94388 94389 94390 94391 94392 94393 94394 94395 94396 94397 94398 94399 94400 94401 94402 94403 94404 94405 94406 94407 94408 94409 94410 94411 94412 94413 94414 94415 94416 94417 94418 94419 94420 94421 94422 94423 94424 94425 94426 94427 94428 94429 94430 94431 94432 94433 94434 94435 94436 94437 94438 94439 94440 94441 94442 94443 94444 94445 94446 94447 94448 94449 94450 94451 94452 94453 94454 94455 94456 94457 94458 94459 94460 94461 94462 94463 94464 94465 94466 94467 94468 94469 94470 94471 94472 94473 94474 94475 94476 94477 94478 94479 94480 94481 94482 94483 94484 94485 94486 94487 94488 94489 94490 94491 94492 94493 94494 94495 94496 94497 94498 94499 94500 94501 94502 94503 94504 94505 94506 94507 94508 94509 94510 94511 94512 94513 94514 94515 94516 94517 94518 94519 94520 94521 94522 94523 94524 94525 94526 94527 94528 94529 94530 94531 94532 94533 94534 94535 94536 94537 94538 94539 94540 94541 94542 94543 94544 94545 94546 94547 94548 94549 94550 94551 94552 94553 94554 94555 94556 94557 94558 94559 94560 94561 94562 94563 94564 94565 94566 94567 94568 94569 94570 94571 94572 94573 94574 94575 94576 94577 94578 94579 94580 94581 94582 94583 94584 94585 94586 94587 94588 94589 94590 94591 94592 94593 94594 94595 94596 94597 94598 94599 94600 94601 94602 94603 94604 94605 94606 94607 94608 94609 94610 94611 94612 94613 94614 94615 94616 94617 94618 94619 94620 94621 94622 94623 94624 94625 94626 94627 94628 94629 94630 94631 94632 94633 94634 94635 94636 94637 94638 94639 94640 94641 94642 94643 94644 94645 94646 94647 94648 94649 94650 94651 94652 94653 94654 94655 94656 94657 94658 94659 94660 94661 94662 94663 94664 94665 94666 94667 94668 94669 94670 94671 94672 94673 94674 94675 94676 94677 94678 94679 94680 94681 94682 94683 94684 94685 94686 94687 94688 94689 94690 94691 94692 94693 94694 94695 94696 94697 94698 94699 94700 94701 94702 94703 94704 94705 94706 94707 94708 94709 94710 94711 94712 94713 94714 94715 94716 94717 94718 94719 94720 94721 94722 94723 94724 94725 94726 94727 94728 94729 94730 94731 94732 94733 94734 94735 94736 94737 94738 94739 94740 94741 94742 94743 94744 94745 94746 94747 94748 94749 94750 94751 94752 94753 94754 94755 94756 94757 94758 94759 94760 94761 94762 94763 94764 94765 94766 94767 94768 94769 94770 94771 94772 94773 94774 94775 94776 94777 94778 94779 94780 94781 94782 94783 94784 94785 94786 94787 94788 94789 94790 94791 94792 94793 94794 94795 94796 94797 94798 94799 94800 94801 94802 94803 94804 94805 94806 94807 94808 94809 94810 94811 94812 94813 94814 94815 94816 94817 94818 94819 94820 94821 94822 94823 94824 94825 94826 94827 94828 94829 94830 94831 94832 94833 94834 94835 94836 94837 94838 94839 94840 94841 94842 94843 94844 94845 94846 94847 94848 94849 94850 94851 94852 94853 94854 94855 94856 94857 94858 94859 94860 94861 94862 94863 94864 94865 94866 94867 94868 94869 94870 94871 94872 94873 94874 94875 94876 94877 94878 94879 94880 94881 94882 94883 94884 94885 94886 94887 94888 94889 94890 94891 94892 94893 94894 94895 94896 94897 94898 94899 94900 94901 94902 94903 94904 94905 94906 94907 94908 94909 94910 94911 94912 94913 94914 94915 94916 94917 94918 94919 94920 94921 94922 94923 94924 94925 94926 94927 94928 94929 94930 94931 94932 94933 94934 94935 94936 94937 94938 94939 94940 94941 94942 94943 94944 94945 94946 94947 94948 94949 94950 94951 94952 94953 94954 94955 94956 94957 94958 94959 94960 94961 94962 94963 94964 94965 94966 94967 94968 94969 94970 94971 94972 94973 94974 94975 94976 94977 94978 94979 94980 94981 94982 94983 94984 94985 94986 94987 94988 94989 94990 94991 94992 94993 94994 94995 94996 94997 94998 94999 95000 95001 95002 95003 95004 95005 95006 95007 95008 95009 95010 95011 95012 95013 95014 95015 95016 95017 95018 95019 95020 95021 95022 95023 95024 95025 95026 95027 95028 95029 95030 95031 95032 95033 95034 95035 95036 95037 95038 95039 95040 95041 95042 95043 95044 95045 95046 95047 95048 95049 95050 95051 95052 95053 95054 95055 95056 95057 95058 95059 95060 95061 95062 95063 95064 95065 95066 95067 95068 95069 95070 95071 95072 95073 95074 95075 95076 95077 95078 95079 95080 95081 95082 95083 95084 95085 95086 95087 95088 95089 95090 95091 95092 95093 95094 95095 95096 95097 95098 95099 95100 95101 95102 95103 95104 95105 95106 95107 95108 95109 95110 95111 95112 95113 95114 95115 95116 95117 95118 95119 95120 95121 95122 95123 95124 95125 95126 95127 95128 95129 95130 95131 95132 95133 95134 95135 95136 95137 95138 95139 95140 95141 95142 95143 95144 95145 95146 95147 95148 95149 95150 95151 95152 95153 95154 95155 95156 95157 95158 95159 95160 95161 95162 95163 95164 95165 95166 95167 95168 95169 95170 95171 95172 95173 95174 95175 95176 95177 95178 95179 95180 95181 95182 95183 95184 95185 95186 95187 95188 95189 95190 95191 95192 95193 95194 95195 95196 95197 95198 95199 95200 95201 95202 95203 95204 95205 95206 95207 95208 95209 95210 95211 95212 95213 95214 95215 95216 95217 95218 95219 95220 95221 95222 95223 95224 95225 95226 95227 95228 95229 95230 95231 95232 95233 95234 95235 95236 95237 95238 95239 95240 95241 95242 95243 95244 95245 95246 95247 95248 95249 95250 95251 95252 95253 95254 95255 95256 95257 95258 95259 95260 95261 95262 95263 95264 95265 95266 95267 95268 95269 95270 95271 95272 95273 95274 95275 95276 95277 95278 95279 95280 95281 95282 95283 95284 95285 95286 95287 95288 95289 95290 95291 95292 95293 95294 95295 95296 95297 95298 95299 95300 95301 95302 95303 95304 95305 95306 95307 95308 95309 95310 95311 95312 95313 95314 95315 95316 95317 95318 95319 95320 95321 95322 95323 95324 95325 95326 95327 95328 95329 95330 95331 95332 95333 95334 95335 95336 95337 95338 95339 95340 95341 95342 95343 95344 95345 95346 95347 95348 95349 95350 95351 95352 95353 95354 95355 95356 95357 95358 95359 95360 95361 95362 95363 95364 95365 95366 95367 95368 95369 95370 95371 95372 95373 95374 95375 95376 95377 95378 95379 95380 95381 95382 95383 95384 95385 95386 95387 95388 95389 95390 95391 95392 95393 95394 95395 95396 95397 95398 95399 95400 95401 95402 95403 95404 95405 95406 95407 95408 95409 95410 95411 95412 95413 95414 95415 95416 95417 95418 95419 95420 95421 95422 95423 95424 95425 95426 95427 95428 95429 95430 95431 95432 95433 95434 95435 95436 95437 95438 95439 95440 95441 95442 95443 95444 95445 95446 95447 95448 95449 95450 95451 95452 95453 95454 95455 95456 95457 95458 95459 95460 95461 95462 95463 95464 95465 95466 95467 95468 95469 95470 95471 95472 95473 95474 95475 95476 95477 95478 95479 95480 95481 95482 95483 95484 95485 95486 95487 95488 95489 95490 95491 95492 95493 95494 95495 95496 95497 95498 95499 95500 95501 95502 95503 95504 95505 95506 95507 95508 95509 95510 95511 95512 95513 95514 95515 95516 95517 95518 95519 95520 95521 95522 95523 95524 95525 95526 95527 95528 95529 95530 95531 95532 95533 95534 95535 95536 95537 95538 95539 95540 95541 95542 95543 95544 95545 95546 95547 95548 95549 95550 95551 95552 95553 95554 95555 95556 95557 95558 95559 95560 95561 95562 95563 95564 95565 95566 95567 95568 95569 95570 95571 95572 95573 95574 95575 95576 95577 95578 95579 95580 95581 95582 95583 95584 95585 95586 95587 95588 95589 95590 95591 95592 95593 95594 95595 95596 95597 95598 95599 95600 95601 95602 95603 95604 95605 95606 95607 95608 95609 95610 95611 95612 95613 95614 95615 95616 95617 95618 95619 95620 95621 95622 95623 95624 95625 95626 95627 95628 95629 95630 95631 95632 95633 95634 95635 95636 95637 95638 95639 95640 95641 95642 95643 95644 95645 95646 95647 95648 95649 95650 95651 95652 95653 95654 95655 95656 95657 95658 95659 95660 95661 95662 95663 95664 95665 95666 95667 95668 95669 95670 95671 95672 95673 95674 95675 95676 95677 95678 95679 95680 95681 95682 95683 95684 95685 95686 95687 95688 95689 95690 95691 95692 95693 95694 95695 95696 95697 95698 95699 95700 95701 95702 95703 95704 95705 95706 95707 95708 95709 95710 95711 95712 95713 95714 95715 95716 95717 95718 95719 95720 95721 95722 95723 95724 95725 95726 95727 95728 95729 95730 95731 95732 95733 95734 95735 95736 95737 95738 95739 95740 95741 95742 95743 95744 95745 95746 95747 95748 95749 95750 95751 95752 95753 95754 95755 95756 95757 95758 95759 95760 95761 95762 95763 95764 95765 95766 95767 95768 95769 95770 95771 95772 95773 95774 95775 95776 95777 95778 95779 95780 95781 95782 95783 95784 95785 95786 95787 95788 95789 95790 95791 95792 95793 95794 95795 95796 95797 95798 95799 95800 95801 95802 95803 95804 95805 95806 95807 95808 95809 95810 95811 95812 95813 95814 95815 95816 95817 95818 95819 95820 95821 95822 95823 95824 95825 95826 95827 95828 95829 95830 95831 95832 95833 95834 95835 95836 95837 95838 95839 95840 95841 95842 95843 95844 95845 95846 95847 95848 95849 95850 95851 95852 95853 95854 95855 95856 95857 95858 95859 95860 95861 95862 95863 95864 95865 95866 95867 95868 95869 95870 95871 95872 95873 95874 95875 95876 95877 95878 95879 95880 95881 95882 95883 95884 95885 95886 95887 95888 95889 95890 95891 95892 95893 95894 95895 95896 95897 95898 95899 95900 95901 95902 95903 95904 95905 95906 95907 95908 95909 95910 95911 95912 95913 95914 95915 95916 95917 95918 95919 95920 95921 95922 95923 95924 95925 95926 95927 95928 95929 95930 95931 95932 95933 95934 95935 95936 95937 95938 95939 95940 95941 95942 95943 95944 95945 95946 95947 95948 95949 95950 95951 95952 95953 95954 95955 95956 95957 95958 95959 95960 95961 95962 95963 95964 95965 95966 95967 95968 95969 95970 95971 95972 95973 95974 95975 95976 95977 95978 95979 95980 95981 95982 95983 95984 95985 95986 95987 95988 95989 95990 95991 95992 95993 95994 95995 95996 95997 95998 95999 96000 96001 96002 96003 96004 96005 96006 96007 96008 96009 96010 96011 96012 96013 96014 96015 96016 96017 96018 96019 96020 96021 96022 96023 96024 96025 96026 96027 96028 96029 96030 96031 96032 96033 96034 96035 96036 96037 96038 96039 96040 96041 96042 96043 96044 96045 96046 96047 96048 96049 96050 96051 96052 96053 96054 96055 96056 96057 96058 96059 96060 96061 96062 96063 96064 96065 96066 96067 96068 96069 96070 96071 96072 96073 96074 96075 96076 96077 96078 96079 96080 96081 96082 96083 96084 96085 96086 96087 96088 96089 96090 96091 96092 96093 96094 96095 96096 96097 96098 96099 96100 96101 96102 96103 96104 96105 96106 96107 96108 96109 96110 96111 96112 96113 96114 96115 96116 96117 96118 96119 96120 96121 96122 96123 96124 96125 96126 96127 96128 96129 96130 96131 96132 96133 96134 96135 96136 96137 96138 96139 96140 96141 96142 96143 96144 96145 96146 96147 96148 96149 96150 96151 96152 96153 96154 96155 96156 96157 96158 96159 96160 96161 96162 96163 96164 96165 96166 96167 96168 96169 96170 96171 96172 96173 96174 96175 96176 96177 96178 96179 96180 96181 96182 96183 96184 96185 96186 96187 96188 96189 96190 96191 96192 96193 96194 96195 96196 96197 96198 96199 96200 96201 96202 96203 96204 96205 96206 96207 96208 96209 96210 96211 96212 96213 96214 96215 96216 96217 96218 96219 96220 96221 96222 96223 96224 96225 96226 96227 96228 96229 96230 96231 96232 96233 96234 96235 96236 96237 96238 96239 96240 96241 96242 96243 96244 96245 96246 96247 96248 96249 96250 96251 96252 96253 96254 96255 96256 96257 96258 96259 96260 96261 96262 96263 96264 96265 96266 96267 96268 96269 96270 96271 96272 96273 96274 96275 96276 96277 96278 96279 96280 96281 96282 96283 96284 96285 96286 96287 96288 96289 96290 96291 96292 96293 96294 96295 96296 96297 96298 96299 96300 96301 96302 96303 96304 96305 96306 96307 96308 96309 96310 96311 96312 96313 96314 96315 96316 96317 96318 96319 96320 96321 96322 96323 96324 96325 96326 96327 96328 96329 96330 96331 96332 96333 96334 96335 96336 96337 96338 96339 96340 96341 96342 96343 96344 96345 96346 96347 96348 96349 96350 96351 96352 96353 96354 96355 96356 96357 96358 96359 96360 96361 96362 96363 96364 96365 96366 96367 96368 96369 96370 96371 96372 96373 96374 96375 96376 96377 96378 96379 96380 96381 96382 96383 96384 96385 96386 96387 96388 96389 96390 96391 96392 96393 96394 96395 96396 96397 96398 96399 96400 96401 96402 96403 96404 96405 96406 96407 96408 96409 96410 96411 96412 96413 96414 96415 96416 96417 96418 96419 96420 96421 96422 96423 96424 96425 96426 96427 96428 96429 96430 96431 96432 96433 96434 96435 96436 96437 96438 96439 96440 96441 96442 96443 96444 96445 96446 96447 96448 96449 96450 96451 96452 96453 96454 96455 96456 96457 96458 96459 96460 96461 96462 96463 96464 96465 96466 96467 96468 96469 96470 96471 96472 96473 96474 96475 96476 96477 96478 96479 96480 96481 96482 96483 96484 96485 96486 96487 96488 96489 96490 96491 96492 96493 96494 96495 96496 96497 96498 96499 96500 96501 96502 96503 96504 96505 96506 96507 96508 96509 96510 96511 96512 96513 96514 96515 96516 96517 96518 96519 96520 96521 96522 96523 96524 96525 96526 96527 96528 96529 96530 96531 96532 96533 96534 96535 96536 96537 96538 96539 96540 96541 96542 96543 96544 96545 96546 96547 96548 96549 96550 96551 96552 96553 96554 96555 96556 96557 96558 96559 96560 96561 96562 96563 96564 96565 96566 96567 96568 96569 96570 96571 96572 96573 96574 96575 96576 96577 96578 96579 96580 96581 96582 96583 96584 96585 96586 96587 96588 96589 96590 96591 96592 96593 96594 96595 96596 96597 96598 96599 96600 96601 96602 96603 96604 96605 96606 96607 96608 96609 96610 96611 96612 96613 96614 96615 96616 96617 96618 96619 96620 96621 96622 96623 96624 96625 96626 96627 96628 96629 96630 96631 96632 96633 96634 96635 96636 96637 96638 96639 96640 96641 96642 96643 96644 96645 96646 96647 96648 96649 96650 96651 96652 96653 96654 96655 96656 96657 96658 96659 96660 96661 96662 96663 96664 96665 96666 96667 96668 96669 96670 96671 96672 96673 96674 96675 96676 96677 96678 96679 96680 96681 96682 96683 96684 96685 96686 96687 96688 96689 96690 96691 96692 96693 96694 96695 96696 96697 96698 96699 96700 96701 96702 96703 96704 96705 96706 96707 96708 96709 96710 96711 96712 96713 96714 96715 96716 96717 96718 96719 96720 96721 96722 96723 96724 96725 96726 96727 96728 96729 96730 96731 96732 96733 96734 96735 96736 96737 96738 96739 96740 96741 96742 96743 96744 96745 96746 96747 96748 96749 96750 96751 96752 96753 96754 96755 96756 96757 96758 96759 96760 96761 96762 96763 96764 96765 96766 96767 96768 96769 96770 96771 96772 96773 96774 96775 96776 96777 96778 96779 96780 96781 96782 96783 96784 96785 96786 96787 96788 96789 96790 96791 96792 96793 96794 96795 96796 96797 96798 96799 96800 96801 96802 96803 96804 96805 96806 96807 96808 96809 96810 96811 96812 96813 96814 96815 96816 96817 96818 96819 96820 96821 96822 96823 96824 96825 96826 96827 96828 96829 96830 96831 96832 96833 96834 96835 96836 96837 96838 96839 96840 96841 96842 96843 96844 96845 96846 96847 96848 96849 96850 96851 96852 96853 96854 96855 96856 96857 96858 96859 96860 96861 96862 96863 96864 96865 96866 96867 96868 96869 96870 96871 96872 96873 96874 96875 96876 96877 96878 96879 96880 96881 96882 96883 96884 96885 96886 96887 96888 96889 96890 96891 96892 96893 96894 96895 96896 96897 96898 96899 96900 96901 96902 96903 96904 96905 96906 96907 96908 96909 96910 96911 96912 96913 96914 96915 96916 96917 96918 96919 96920 96921 96922 96923 96924 96925 96926 96927 96928 96929 96930 96931 96932 96933 96934 96935 96936 96937 96938 96939 96940 96941 96942 96943 96944 96945 96946 96947 96948 96949 96950 96951 96952 96953 96954 96955 96956 96957 96958 96959 96960 96961 96962 96963 96964 96965 96966 96967 96968 96969 96970 96971 96972 96973 96974 96975 96976 96977 96978 96979 96980 96981 96982 96983 96984 96985 96986 96987 96988 96989 96990 96991 96992 96993 96994 96995 96996 96997 96998 96999 97000 97001 97002 97003 97004 97005 97006 97007 97008 97009 97010 97011 97012 97013 97014 97015 97016 97017 97018 97019 97020 97021 97022 97023 97024 97025 97026 97027 97028 97029 97030 97031 97032 97033 97034 97035 97036 97037 97038 97039 97040 97041 97042 97043 97044 97045 97046 97047 97048 97049 97050 97051 97052 97053 97054 97055 97056 97057 97058 97059 97060 97061 97062 97063 97064 97065 97066 97067 97068 97069 97070 97071 97072 97073 97074 97075 97076 97077 97078 97079 97080 97081 97082 97083 97084 97085 97086 97087 97088 97089 97090 97091 97092 97093 97094 97095 97096 97097 97098 97099 97100 97101 97102 97103 97104 97105 97106 97107 97108 97109 97110 97111 97112 97113 97114 97115 97116 97117 97118 97119 97120 97121 97122 97123 97124 97125 97126 97127 97128 97129 97130 97131 97132 97133 97134 97135 97136 97137 97138 97139 97140 97141 97142 97143 97144 97145 97146 97147 97148 97149 97150 97151 97152 97153 97154 97155 97156 97157 97158 97159 97160 97161 97162 97163 97164 97165 97166 97167 97168 97169 97170 97171 97172 97173 97174 97175 97176 97177 97178 97179 97180 97181 97182 97183 97184 97185 97186 97187 97188 97189 97190 97191 97192 97193 97194 97195 97196 97197 97198 97199 97200 97201 97202 97203 97204 97205 97206 97207 97208 97209 97210 97211 97212 97213 97214 97215 97216 97217 97218 97219 97220 97221 97222 97223 97224 97225 97226 97227 97228 97229 97230 97231 97232 97233 97234 97235 97236 97237 97238 97239 97240 97241 97242 97243 97244 97245 97246 97247 97248 97249 97250 97251 97252 97253 97254 97255 97256 97257 97258 97259 97260 97261 97262 97263 97264 97265 97266 97267 97268 97269 97270 97271 97272 97273 97274 97275 97276 97277 97278 97279 97280 97281 97282 97283 97284 97285 97286 97287 97288 97289 97290 97291 97292 97293 97294 97295 97296 97297 97298 97299 97300 97301 97302 97303 97304 97305 97306 97307 97308 97309 97310 97311 97312 97313 97314 97315 97316 97317 97318 97319 97320 97321 97322 97323 97324 97325 97326 97327 97328 97329 97330 97331 97332 97333 97334 97335 97336 97337 97338 97339 97340 97341 97342 97343 97344 97345 97346 97347 97348 97349 97350 97351 97352 97353 97354 97355 97356 97357 97358 97359 97360 97361 97362 97363 97364 97365 97366 97367 97368 97369 97370 97371 97372 97373 97374 97375 97376 97377 97378 97379 97380 97381 97382 97383 97384 97385 97386 97387 97388 97389 97390 97391 97392 97393 97394 97395 97396 97397 97398 97399 97400 97401 97402 97403 97404 97405 97406 97407 97408 97409 97410 97411 97412 97413 97414 97415 97416 97417 97418 97419 97420 97421 97422 97423 97424 97425 97426 97427 97428 97429 97430 97431 97432 97433 97434 97435 97436 97437 97438 97439 97440 97441 97442 97443 97444 97445 97446 97447 97448 97449 97450 97451 97452 97453 97454 97455 97456 97457 97458 97459 97460 97461 97462 97463 97464 97465 97466 97467 97468 97469 97470 97471 97472 97473 97474 97475 97476 97477 97478 97479 97480 97481 97482 97483 97484 97485 97486 97487 97488 97489 97490 97491 97492 97493 97494 97495 97496 97497 97498 97499 97500 97501 97502 97503 97504 97505 97506 97507 97508 97509 97510 97511 97512 97513 97514 97515 97516 97517 97518 97519 97520 97521 97522 97523 97524 97525 97526 97527 97528 97529 97530 97531 97532 97533 97534 97535 97536 97537 97538 97539 97540 97541 97542 97543 97544 97545 97546 97547 97548 97549 97550 97551 97552 97553 97554 97555 97556 97557 97558 97559 97560 97561 97562 97563 97564 97565 97566 97567 97568 97569 97570 97571 97572 97573 97574 97575 97576 97577 97578 97579 97580 97581 97582 97583 97584 97585 97586 97587 97588 97589 97590 97591 97592 97593 97594 97595 97596 97597 97598 97599 97600 97601 97602 97603 97604 97605 97606 97607 97608 97609 97610 97611 97612 97613 97614 97615 97616 97617 97618 97619 97620 97621 97622 97623 97624 97625 97626 97627 97628 97629 97630 97631 97632 97633 97634 97635 97636 97637 97638 97639 97640 97641 97642 97643 97644 97645 97646 97647 97648 97649 97650 97651 97652 97653 97654 97655 97656 97657 97658 97659 97660 97661 97662 97663 97664 97665 97666 97667 97668 97669 97670 97671 97672 97673 97674 97675 97676 97677 97678 97679 97680 97681 97682 97683 97684 97685 97686 97687 97688 97689 97690 97691 97692 97693 97694 97695 97696 97697 97698 97699 97700 97701 97702 97703 97704 97705 97706 97707 97708 97709 97710 97711 97712 97713 97714 97715 97716 97717 97718 97719 97720 97721 97722 97723 97724 97725 97726 97727 97728 97729 97730 97731 97732 97733 97734 97735 97736 97737 97738 97739 97740 97741 97742 97743 97744 97745 97746 97747 97748 97749 97750 97751 97752 97753 97754 97755 97756 97757 97758 97759 97760 97761 97762 97763 97764 97765 97766 97767 97768 97769 97770 97771 97772 97773 97774 97775 97776 97777 97778 97779 97780 97781 97782 97783 97784 97785 97786 97787 97788 97789 97790 97791 97792 97793 97794 97795 97796 97797 97798 97799 97800 97801 97802 97803 97804 97805 97806 97807 97808 97809 97810 97811 97812 97813 97814 97815 97816 97817 97818 97819 97820 97821 97822 97823 97824 97825 97826 97827 97828 97829 97830 97831 97832 97833 97834 97835 97836 97837 97838 97839 97840 97841 97842 97843 97844 97845 97846 97847 97848 97849 97850 97851 97852 97853 97854 97855 97856 97857 97858 97859 97860 97861 97862 97863 97864 97865 97866 97867 97868 97869 97870 97871 97872 97873 97874 97875 97876 97877 97878 97879 97880 97881 97882 97883 97884 97885 97886 97887 97888 97889 97890 97891 97892 97893 97894 97895 97896 97897 97898 97899 97900 97901 97902 97903 97904 97905 97906 97907 97908 97909 97910 97911 97912 97913 97914 97915 97916 97917 97918 97919 97920 97921 97922 97923 97924 97925 97926 97927 97928 97929 97930 97931 97932 97933 97934 97935 97936 97937 97938 97939 97940 97941 97942 97943 97944 97945 97946 97947 97948 97949 97950 97951 97952 97953 97954 97955 97956 97957 97958 97959 97960 97961 97962 97963 97964 97965 97966 97967 97968 97969 97970 97971 97972 97973 97974 97975 97976 97977 97978 97979 97980 97981 97982 97983 97984 97985 97986 97987 97988 97989 97990 97991 97992 97993 97994 97995 97996 97997 97998 97999 98000 98001 98002 98003 98004 98005 98006 98007 98008 98009 98010 98011 98012 98013 98014 98015 98016 98017 98018 98019 98020 98021 98022 98023 98024 98025 98026 98027 98028 98029 98030 98031 98032 98033 98034 98035 98036 98037 98038 98039 98040 98041 98042 98043 98044 98045 98046 98047 98048 98049 98050 98051 98052 98053 98054 98055 98056 98057 98058 98059 98060 98061 98062 98063 98064 98065 98066 98067 98068 98069 98070 98071 98072 98073 98074 98075 98076 98077 98078 98079 98080 98081 98082 98083 98084 98085 98086 98087 98088 98089 98090 98091 98092 98093 98094 98095 98096 98097 98098 98099 98100 98101 98102 98103 98104 98105 98106 98107 98108 98109 98110 98111 98112 98113 98114 98115 98116 98117 98118 98119 98120 98121 98122 98123 98124 98125 98126 98127 98128 98129 98130 98131 98132 98133 98134 98135 98136 98137 98138 98139 98140 98141 98142 98143 98144 98145 98146 98147 98148 98149 98150 98151 98152 98153 98154 98155 98156 98157 98158 98159 98160 98161 98162 98163 98164 98165 98166 98167 98168 98169 98170 98171 98172 98173 98174 98175 98176 98177 98178 98179 98180 98181 98182 98183 98184 98185 98186 98187 98188 98189 98190 98191 98192 98193 98194 98195 98196 98197 98198 98199 98200 98201 98202 98203 98204 98205 98206 98207 98208 98209 98210 98211 98212 98213 98214 98215 98216 98217 98218 98219 98220 98221 98222 98223 98224 98225 98226 98227 98228 98229 98230 98231 98232 98233 98234 98235 98236 98237 98238 98239 98240 98241 98242 98243 98244 98245 98246 98247 98248 98249 98250 98251 98252 98253 98254 98255 98256 98257 98258 98259 98260 98261 98262 98263 98264 98265 98266 98267 98268 98269 98270 98271 98272 98273 98274 98275 98276 98277 98278 98279 98280 98281 98282 98283 98284 98285 98286 98287 98288 98289 98290 98291 98292 98293 98294 98295 98296 98297 98298 98299 98300 98301 98302 98303 98304 98305 98306 98307 98308 98309 98310 98311 98312 98313 98314 98315 98316 98317 98318 98319 98320 98321 98322 98323 98324 98325 98326 98327 98328 98329 98330 98331 98332 98333 98334 98335 98336 98337 98338 98339 98340 98341 98342 98343 98344 98345 98346 98347 98348 98349 98350 98351 98352 98353 98354 98355 98356 98357 98358 98359 98360 98361 98362 98363 98364 98365 98366 98367 98368 98369 98370 98371 98372 98373 98374 98375 98376 98377 98378 98379 98380 98381 98382 98383 98384 98385 98386 98387 98388 98389 98390 98391 98392 98393 98394 98395 98396 98397 98398 98399 98400 98401 98402 98403 98404 98405 98406 98407 98408 98409 98410 98411 98412 98413 98414 98415 98416 98417 98418 98419 98420 98421 98422 98423 98424 98425 98426 98427 98428 98429 98430 98431 98432 98433 98434 98435 98436 98437 98438 98439 98440 98441 98442 98443 98444 98445 98446 98447 98448 98449 98450 98451 98452 98453 98454 98455 98456 98457 98458 98459 98460 98461 98462 98463 98464 98465 98466 98467 98468 98469 98470 98471 98472 98473 98474 98475 98476 98477 98478 98479 98480 98481 98482 98483 98484 98485 98486 98487 98488 98489 98490 98491 98492 98493 98494 98495 98496 98497 98498 98499 98500 98501 98502 98503 98504 98505 98506 98507 98508 98509 98510 98511 98512 98513 98514 98515 98516 98517 98518 98519 98520 98521 98522 98523 98524 98525 98526 98527 98528 98529 98530 98531 98532 98533 98534 98535 98536 98537 98538 98539 98540 98541 98542 98543 98544 98545 98546 98547 98548 98549 98550 98551 98552 98553 98554 98555 98556 98557 98558 98559 98560 98561 98562 98563 98564 98565 98566 98567 98568 98569 98570 98571 98572 98573 98574 98575 98576 98577 98578 98579 98580 98581 98582 98583 98584 98585 98586 98587 98588 98589 98590 98591 98592 98593 98594 98595 98596 98597 98598 98599 98600 98601 98602 98603 98604 98605 98606 98607 98608 98609 98610 98611 98612 98613 98614 98615 98616 98617 98618 98619 98620 98621 98622 98623 98624 98625 98626 98627 98628 98629 98630 98631 98632 98633 98634 98635 98636 98637 98638 98639 98640 98641 98642 98643 98644 98645 98646 98647 98648 98649 98650 98651 98652 98653 98654 98655 98656 98657 98658 98659 98660 98661 98662 98663 98664 98665 98666 98667 98668 98669 98670 98671 98672 98673 98674 98675 98676 98677 98678 98679 98680 98681 98682 98683 98684 98685 98686 98687 98688 98689 98690 98691 98692 98693 98694 98695 98696 98697 98698 98699 98700 98701 98702 98703 98704 98705 98706 98707 98708 98709 98710 98711 98712 98713 98714 98715 98716 98717 98718 98719 98720 98721 98722 98723 98724 98725 98726 98727 98728 98729 98730 98731 98732 98733 98734 98735 98736 98737 98738 98739 98740 98741 98742 98743 98744 98745 98746 98747 98748 98749 98750 98751 98752 98753 98754 98755 98756 98757 98758 98759 98760 98761 98762 98763 98764 98765 98766 98767 98768 98769 98770 98771 98772 98773 98774 98775 98776 98777 98778 98779 98780 98781 98782 98783 98784 98785 98786 98787 98788 98789 98790 98791 98792 98793 98794 98795 98796 98797 98798 98799 98800 98801 98802 98803 98804 98805 98806 98807 98808 98809 98810 98811 98812 98813 98814 98815 98816 98817 98818 98819 98820 98821 98822 98823 98824 98825 98826 98827 98828 98829 98830 98831 98832 98833 98834 98835 98836 98837 98838 98839 98840 98841 98842 98843 98844 98845 98846 98847 98848 98849 98850 98851 98852 98853 98854 98855 98856 98857 98858 98859 98860 98861 98862 98863 98864 98865 98866 98867 98868 98869 98870 98871 98872 98873 98874 98875 98876 98877 98878 98879 98880 98881 98882 98883 98884 98885 98886 98887 98888 98889 98890 98891 98892 98893 98894 98895 98896 98897 98898 98899 98900 98901 98902 98903 98904 98905 98906 98907 98908 98909 98910 98911 98912 98913 98914 98915 98916 98917 98918 98919 98920 98921 98922 98923 98924 98925 98926 98927 98928 98929 98930 98931 98932 98933 98934 98935 98936 98937 98938 98939 98940 98941 98942 98943 98944 98945 98946 98947 98948 98949 98950 98951 98952 98953 98954 98955 98956 98957 98958 98959 98960 98961 98962 98963 98964 98965 98966 98967 98968 98969 98970 98971 98972 98973 98974 98975 98976 98977 98978 98979 98980 98981 98982 98983 98984 98985 98986 98987 98988 98989 98990 98991 98992 98993 98994 98995 98996 98997 98998 98999 99000 99001 99002 99003 99004 99005 99006 99007 99008 99009 99010 99011 99012 99013 99014 99015 99016 99017 99018 99019 99020 99021 99022 99023 99024 99025 99026 99027 99028 99029 99030 99031 99032 99033 99034 99035 99036 99037 99038 99039 99040 99041 99042 99043 99044 99045 99046 99047 99048 99049 99050 99051 99052 99053 99054 99055 99056 99057 99058 99059 99060 99061 99062 99063 99064 99065 99066 99067 99068 99069 99070 99071 99072 99073 99074 99075 99076 99077 99078 99079 99080 99081 99082 99083 99084 99085 99086 99087 99088 99089 99090 99091 99092 99093 99094 99095 99096 99097 99098 99099 99100 99101 99102 99103 99104 99105 99106 99107 99108 99109 99110 99111 99112 99113 99114 99115 99116 99117 99118 99119 99120 99121 99122 99123 99124 99125 99126 99127 99128 99129 99130 99131 99132 99133 99134 99135 99136 99137 99138 99139 99140 99141 99142 99143 99144 99145 99146 99147 99148 99149 99150 99151 99152 99153 99154 99155 99156 99157 99158 99159 99160 99161 99162 99163 99164 99165 99166 99167 99168 99169 99170 99171 99172 99173 99174 99175 99176 99177 99178 99179 99180 99181 99182 99183 99184 99185 99186 99187 99188 99189 99190 99191 99192 99193 99194 99195 99196 99197 99198 99199 99200 99201 99202 99203 99204 99205 99206 99207 99208 99209 99210 99211 99212 99213 99214 99215 99216 99217 99218 99219 99220 99221 99222 99223 99224 99225 99226 99227 99228 99229 99230 99231 99232 99233 99234 99235 99236 99237 99238 99239 99240 99241 99242 99243 99244 99245 99246 99247 99248 99249 99250 99251 99252 99253 99254 99255 99256 99257 99258 99259 99260 99261 99262 99263 99264 99265 99266 99267 99268 99269 99270 99271 99272 99273 99274 99275 99276 99277 99278 99279 99280 99281 99282 99283 99284 99285 99286 99287 99288 99289 99290 99291 99292 99293 99294 99295 99296 99297 99298 99299 99300 99301 99302 99303 99304 99305 99306 99307 99308 99309 99310 99311 99312 99313 99314 99315 99316 99317 99318 99319 99320 99321 99322 99323 99324 99325 99326 99327 99328 99329 99330 99331 99332 99333 99334 99335 99336 99337 99338 99339 99340 99341 99342 99343 99344 99345 99346 99347 99348 99349 99350 99351 99352 99353 99354 99355 99356 99357 99358 99359 99360 99361 99362 99363 99364 99365 99366 99367 99368 99369 99370 99371 99372 99373 99374 99375 99376 99377 99378 99379 99380 99381 99382 99383 99384 99385 99386 99387 99388 99389 99390 99391 99392 99393 99394 99395 99396 99397 99398 99399 99400 99401 99402 99403 99404 99405 99406 99407 99408 99409 99410 99411 99412 99413 99414 99415 99416 99417 99418 99419 99420 99421 99422 99423 99424 99425 99426 99427 99428 99429 99430 99431 99432 99433 99434 99435 99436 99437 99438 99439 99440 99441 99442 99443 99444 99445 99446 99447 99448 99449 99450 99451 99452 99453 99454 99455 99456 99457 99458 99459 99460 99461 99462 99463 99464 99465 99466 99467 99468 99469 99470 99471 99472 99473 99474 99475 99476 99477 99478 99479 99480 99481 99482 99483 99484 99485 99486 99487 99488 99489 99490 99491 99492 99493 99494 99495 99496 99497 99498 99499 99500 99501 99502 99503 99504 99505 99506 99507 99508 99509 99510 99511 99512 99513 99514 99515 99516 99517 99518 99519 99520 99521 99522 99523 99524 99525 99526 99527 99528 99529 99530 99531 99532 99533 99534 99535 99536 99537 99538 99539 99540 99541 99542 99543 99544 99545 99546 99547 99548 99549 99550 99551 99552 99553 99554 99555 99556 99557 99558 99559 99560 99561 99562 99563 99564 99565 99566 99567 99568 99569 99570 99571 99572 99573 99574 99575 99576 99577 99578 99579 99580 99581 99582 99583 99584 99585 99586 99587 99588 99589 99590 99591 99592 99593 99594 99595 99596 99597 99598 99599 99600 99601 99602 99603 99604 99605 99606 99607 99608 99609 99610 99611 99612 99613 99614 99615 99616 99617 99618 99619 99620 99621 99622 99623 99624 99625 99626 99627 99628 99629 99630 99631 99632 99633 99634 99635 99636 99637 99638 99639 99640 99641 99642 99643 99644 99645 99646 99647 99648 99649 99650 99651 99652 99653 99654 99655 99656 99657 99658 99659 99660 99661 99662 99663 99664 99665 99666 99667 99668 99669 99670 99671 99672 99673 99674 99675 99676 99677 99678 99679 99680 99681 99682 99683 99684 99685 99686 99687 99688 99689 99690 99691 99692 99693 99694 99695 99696 99697 99698 99699 99700 99701 99702 99703 99704 99705 99706 99707 99708 99709 99710 99711 99712 99713 99714 99715 99716 99717 99718 99719 99720 99721 99722 99723 99724 99725 99726 99727 99728 99729 99730 99731 99732 99733 99734 99735 99736 99737 99738 99739 99740 99741 99742 99743 99744 99745 99746 99747 99748 99749 99750 99751 99752 99753 99754 99755 99756 99757 99758 99759 99760 99761 99762 99763 99764 99765 99766 99767 99768 99769 99770 99771 99772 99773 99774 99775 99776 99777 99778 99779 99780 99781 99782 99783 99784 99785 99786 99787 99788 99789 99790 99791 99792 99793 99794 99795 99796 99797 99798 99799 99800 99801 99802 99803 99804 99805 99806 99807 99808 99809 99810 99811 99812 99813 99814 99815 99816 99817 99818 99819 99820 99821 99822 99823 99824 99825 99826 99827 99828 99829 99830 99831 99832 99833 99834 99835 99836 99837 99838 99839 99840 99841 99842 99843 99844 99845 99846 99847 99848 99849 99850 99851 99852 99853 99854 99855 99856 99857 99858 99859 99860 99861 99862 99863 99864 99865 99866 99867 99868 99869 99870 99871 99872 99873 99874 99875 99876 99877 99878 99879 99880 99881 99882 99883 99884 99885 99886 99887 99888 99889 99890 99891 99892 99893 99894 99895 99896 99897 99898 99899 99900 99901 99902 99903 99904 99905 99906 99907 99908 99909 99910 99911 99912 99913 99914 99915 99916 99917 99918 99919 99920 99921 99922 99923 99924 99925 99926 99927 99928 99929 99930 99931 99932 99933 99934 99935 99936 99937 99938 99939 99940 99941 99942 99943 99944 99945 99946 99947 99948 99949 99950 99951 99952 99953 99954 99955 99956 99957 99958 99959 99960 99961 99962 99963 99964 99965 99966 99967 99968 99969 99970 99971 99972 99973 99974 99975 99976 99977 99978 99979 99980 99981 99982 99983 99984 99985 99986 99987 99988 99989 99990 99991 99992 99993 99994 99995 99996 99997 99998 99999 100000 100001 100002 100003 100004 100005 100006 100007 100008 100009 100010 100011 100012 100013 100014 100015 100016 100017 100018 100019 100020 100021 100022 100023 100024 100025 100026 100027 100028 100029 100030 100031 100032 100033 100034 100035 100036 100037 100038 100039 100040 100041 100042 100043 100044 100045 100046 100047 100048 100049 100050 100051 100052 100053 100054 100055 100056 100057 100058 100059 100060 100061 100062 100063 100064 100065 100066 100067 100068 100069 100070 100071 100072 100073 100074 100075 100076 100077 100078 100079 100080 100081 100082 100083 100084 100085 100086 100087 100088 100089 100090 100091 100092 100093 100094 100095 100096 100097 100098 100099 100100 100101 100102 100103 100104 100105 100106 100107 100108 100109 100110 100111 100112 100113 100114 100115 100116 100117 100118 100119 100120 100121 100122 100123 100124 100125 100126 100127 100128 100129 100130 100131 100132 100133 100134 100135 100136 100137 100138 100139 100140 100141 100142 100143 100144 100145 100146 100147 100148 100149 100150 100151 100152 100153 100154 100155 100156 100157 100158 100159 100160 100161 100162 100163 100164 100165 100166 100167 100168 100169 100170 100171 100172 100173 100174 100175 100176 100177 100178 100179 100180 100181 100182 100183 100184 100185 100186 100187 100188 100189 100190 100191 100192 100193 100194 100195 100196 100197 100198 100199 100200 100201 100202 100203 100204 100205 100206 100207 100208 100209 100210 100211 100212 100213 100214 100215 100216 100217 100218 100219 100220 100221 100222 100223 100224 100225 100226 100227 100228 100229 100230 100231 100232 100233 100234 100235 100236 100237 100238 100239 100240 100241 100242 100243 100244 100245 100246 100247 100248 100249 100250 100251 100252 100253 100254 100255 100256 100257 100258 100259 100260 100261 100262 100263 100264 100265 100266 100267 100268 100269 100270 100271 100272 100273 100274 100275 100276 100277 100278 100279 100280 100281 100282 100283 100284 100285 100286 100287 100288 100289 100290 100291 100292 100293 100294 100295 100296 100297 100298 100299 100300 100301 100302 100303 100304 100305 100306 100307 100308 100309 100310 100311 100312 100313 100314 100315 100316 100317 100318 100319 100320 100321 100322 100323 100324 100325 100326 100327 100328 100329 100330 100331 100332 100333 100334 100335 100336 100337 100338 100339 100340 100341 100342 100343 100344 100345 100346 100347 100348 100349 100350 100351 100352 100353 100354 100355 100356 100357 100358 100359 100360 100361 100362 100363 100364 100365 100366 100367 100368 100369 100370 100371 100372 100373 100374 100375 100376 100377 100378 100379 100380 100381 100382 100383 100384 100385 100386 100387 100388 100389 100390 100391 100392 100393 100394 100395 100396 100397 100398 100399 100400 100401 100402 100403 100404 100405 100406 100407 100408 100409 100410 100411 100412 100413 100414 100415 100416 100417 100418 100419 100420 100421 100422 100423 100424 100425 100426 100427 100428 100429 100430 100431 100432 100433 100434 100435 100436 100437 100438 100439 100440 100441 100442 100443 100444 100445 100446 100447 100448 100449 100450 100451 100452 100453 100454 100455 100456 100457 100458 100459 100460 100461 100462 100463 100464 100465 100466 100467 100468 100469 100470 100471 100472 100473 100474 100475 100476 100477 100478 100479 100480 100481 100482 100483 100484 100485 100486 100487 100488 100489 100490 100491 100492 100493 100494 100495 100496 100497 100498 100499 100500 100501 100502 100503 100504 100505 100506 100507 100508 100509 100510 100511 100512 100513 100514 100515 100516 100517 100518 100519 100520 100521 100522 100523 100524 100525 100526 100527 100528 100529 100530 100531 100532 100533 100534 100535 100536 100537 100538 100539 100540 100541 100542 100543 100544 100545 100546 100547 100548 100549 100550 100551 100552 100553 100554 100555 100556 100557 100558 100559 100560 100561 100562 100563 100564 100565 100566 100567 100568 100569 100570 100571 100572 100573 100574 100575 100576 100577 100578 100579 100580 100581 100582 100583 100584 100585 100586 100587 100588 100589 100590 100591 100592 100593 100594 100595 100596 100597 100598 100599 100600 100601 100602 100603 100604 100605 100606 100607 100608 100609 100610 100611 100612 100613 100614 100615 100616 100617 100618 100619 100620 100621 100622 100623 100624 100625 100626 100627 100628 100629 100630 100631 100632 100633 100634 100635 100636 100637 100638 100639 100640 100641 100642 100643 100644 100645 100646 100647 100648 100649 100650 100651 100652 100653 100654 100655 100656 100657 100658 100659 100660 100661 100662 100663 100664 100665 100666 100667 100668 100669 100670 100671 100672 100673 100674 100675 100676 100677 100678 100679 100680 100681 100682 100683 100684 100685 100686 100687 100688 100689 100690 100691 100692 100693 100694 100695 100696 100697 100698 100699 100700 100701 100702 100703 100704 100705 100706 100707 100708 100709 100710 100711 100712 100713 100714 100715 100716 100717 100718 100719 100720 100721 100722 100723 100724 100725 100726 100727 100728 100729 100730 100731 100732 100733 100734 100735 100736 100737 100738 100739 100740 100741 100742 100743 100744 100745 100746 100747 100748 100749 100750 100751 100752 100753 100754 100755 100756 100757 100758 100759 100760 100761 100762 100763 100764 100765 100766 100767 100768 100769 100770 100771 100772 100773 100774 100775 100776 100777 100778 100779 100780 100781 100782 100783 100784 100785 100786 100787 100788 100789 100790 100791 100792 100793 100794 100795 100796 100797 100798 100799 100800 100801 100802 100803 100804 100805 100806 100807 100808 100809 100810 100811 100812 100813 100814 100815 100816 100817 100818 100819 100820 100821 100822 100823 100824 100825 100826 100827 100828 100829 100830 100831 100832 100833 100834 100835 100836 100837 100838 100839 100840 100841 100842 100843 100844 100845 100846 100847 100848 100849 100850 100851 100852 100853 100854 100855 100856 100857 100858 100859 100860 100861 100862 100863 100864 100865 100866 100867 100868 100869 100870 100871 100872 100873 100874 100875 100876 100877 100878 100879 100880 100881 100882 100883 100884 100885 100886 100887 100888 100889 100890 100891 100892 100893 100894 100895 100896 100897 100898 100899 100900 100901 100902 100903 100904 100905 100906 100907 100908 100909 100910 100911 100912 100913 100914 100915 100916 100917 100918 100919 100920 100921 100922 100923 100924 100925 100926 100927 100928 100929 100930 100931 100932 100933 100934 100935 100936 100937 100938 100939 100940 100941 100942 100943 100944 100945 100946 100947 100948 100949 100950 100951 100952 100953 100954 100955 100956 100957 100958 100959 100960 100961 100962 100963 100964 100965 100966 100967 100968 100969 100970 100971 100972 100973 100974 100975 100976 100977 100978 100979 100980 100981 100982 100983 100984 100985 100986 100987 100988 100989 100990 100991 100992 100993 100994 100995 100996 100997 100998 100999 101000 101001 101002 101003 101004 101005 101006 101007 101008 101009 101010 101011 101012 101013 101014 101015 101016 101017 101018 101019 101020 101021 101022 101023 101024 101025 101026 101027 101028 101029 101030 101031 101032 101033 101034 101035 101036 101037 101038 101039 101040 101041 101042 101043 101044 101045 101046 101047 101048 101049 101050 101051 101052 101053 101054 101055 101056 101057 101058 101059 101060 101061 101062 101063 101064 101065 101066 101067 101068 101069 101070 101071 101072 101073 101074 101075 101076 101077 101078 101079 101080 101081 101082 101083 101084 101085 101086 101087 101088 101089 101090 101091 101092 101093 101094 101095 101096 101097 101098 101099 101100 101101 101102 101103 101104 101105 101106 101107 101108 101109 101110 101111 101112 101113 101114 101115 101116 101117 101118 101119 101120 101121 101122 101123 101124 101125 101126 101127 101128 101129 101130 101131 101132 101133 101134 101135 101136 101137 101138 101139 101140 101141 101142 101143 101144 101145 101146 101147 101148 101149 101150 101151 101152 101153 101154 101155 101156 101157 101158 101159 101160 101161 101162 101163 101164 101165 101166 101167 101168 101169 101170 101171 101172 101173 101174 101175 101176 101177 101178 101179 101180 101181 101182 101183 101184 101185 101186 101187 101188 101189 101190 101191 101192 101193 101194 101195 101196 101197 101198 101199 101200 101201 101202 101203 101204 101205 101206 101207 101208 101209 101210 101211 101212 101213 101214 101215 101216 101217 101218 101219 101220 101221 101222 101223 101224 101225 101226 101227 101228 101229 101230 101231 101232 101233 101234 101235 101236 101237 101238 101239 101240 101241 101242 101243 101244 101245 101246 101247 101248 101249 101250 101251 101252 101253 101254 101255 101256 101257 101258 101259 101260 101261 101262 101263 101264 101265 101266 101267 101268 101269 101270 101271 101272 101273 101274 101275 101276 101277 101278 101279 101280 101281 101282 101283 101284 101285 101286 101287 101288 101289 101290 101291 101292 101293 101294 101295 101296 101297 101298 101299 101300 101301 101302 101303 101304 101305 101306 101307 101308 101309 101310 101311 101312 101313 101314 101315 101316 101317 101318 101319 101320 101321 101322 101323 101324 101325 101326 101327 101328 101329 101330 101331 101332 101333 101334 101335 101336 101337 101338 101339 101340 101341 101342 101343 101344 101345 101346 101347 101348 101349 101350 101351 101352 101353 101354 101355 101356 101357 101358 101359 101360 101361 101362 101363 101364 101365 101366 101367 101368 101369 101370 101371 101372 101373 101374 101375 101376 101377 101378 101379 101380 101381 101382 101383 101384 101385 101386 101387 101388 101389 101390 101391 101392 101393 101394 101395 101396 101397 101398 101399 101400 101401 101402 101403 101404 101405 101406 101407 101408 101409 101410 101411 101412 101413 101414 101415 101416 101417 101418 101419 101420 101421 101422 101423 101424 101425 101426 101427 101428 101429 101430 101431 101432 101433 101434 101435 101436 101437 101438 101439 101440 101441 101442 101443 101444 101445 101446 101447 101448 101449 101450 101451 101452 101453 101454 101455 101456 101457 101458 101459 101460 101461 101462 101463 101464 101465 101466 101467 101468 101469 101470 101471 101472 101473 101474 101475 101476 101477 101478 101479 101480 101481 101482 101483 101484 101485 101486 101487 101488 101489 101490 101491 101492 101493 101494 101495 101496 101497 101498 101499 101500 101501 101502 101503 101504 101505 101506 101507 101508 101509 101510 101511 101512 101513 101514 101515 101516 101517 101518 101519 101520 101521 101522 101523 101524 101525 101526 101527 101528 101529 101530 101531 101532 101533 101534 101535 101536 101537 101538 101539 101540 101541 101542 101543 101544 101545 101546 101547 101548 101549 101550 101551 101552 101553 101554 101555 101556 101557 101558 101559 101560 101561 101562 101563 101564 101565 101566 101567 101568 101569 101570 101571 101572 101573 101574 101575 101576 101577 101578 101579 101580 101581 101582 101583 101584 101585 101586 101587 101588 101589 101590 101591 101592 101593 101594 101595 101596 101597 101598 101599 101600 101601 101602 101603 101604 101605 101606 101607 101608 101609 101610 101611 101612 101613 101614 101615 101616 101617 101618 101619 101620 101621 101622 101623 101624 101625 101626 101627 101628 101629 101630 101631 101632 101633 101634 101635 101636 101637 101638 101639 101640 101641 101642 101643 101644 101645 101646 101647 101648 101649 101650 101651 101652 101653 101654 101655 101656 101657 101658 101659 101660 101661 101662 101663 101664 101665 101666 101667 101668 101669 101670 101671 101672 101673 101674 101675 101676 101677 101678 101679 101680 101681 101682 101683 101684 101685 101686 101687 101688 101689 101690 101691 101692 101693 101694 101695 101696 101697 101698 101699 101700 101701 101702 101703 101704 101705 101706 101707 101708 101709 101710 101711 101712 101713 101714 101715 101716 101717 101718 101719 101720 101721 101722 101723 101724 101725 101726 101727 101728 101729 101730 101731 101732 101733 101734 101735 101736 101737 101738 101739 101740 101741 101742 101743 101744 101745 101746 101747 101748 101749 101750 101751 101752 101753 101754 101755 101756 101757 101758 101759 101760 101761 101762 101763 101764 101765 101766 101767 101768 101769 101770 101771 101772 101773 101774 101775 101776 101777 101778 101779 101780 101781 101782 101783 101784 101785 101786 101787 101788 101789 101790 101791 101792 101793 101794 101795 101796 101797 101798 101799 101800 101801 101802 101803 101804 101805 101806 101807 101808 101809 101810 101811 101812 101813 101814 101815 101816 101817 101818 101819 101820 101821 101822 101823 101824 101825 101826 101827 101828 101829 101830 101831 101832 101833 101834 101835 101836 101837 101838 101839 101840 101841 101842 101843 101844 101845 101846 101847 101848 101849 101850 101851 101852 101853 101854 101855 101856 101857 101858 101859 101860 101861 101862 101863 101864 101865 101866 101867 101868 101869 101870 101871 101872 101873 101874 101875 101876 101877 101878 101879 101880 101881 101882 101883 101884 101885 101886 101887 101888 101889 101890 101891 101892 101893 101894 101895 101896 101897 101898 101899 101900 101901 101902 101903 101904 101905 101906 101907 101908 101909 101910 101911 101912 101913 101914 101915 101916 101917 101918 101919 101920 101921 101922 101923 101924 101925 101926 101927 101928 101929 101930 101931 101932 101933 101934 101935 101936 101937 101938 101939 101940 101941 101942 101943 101944 101945 101946 101947 101948 101949 101950 101951 101952 101953 101954 101955 101956 101957 101958 101959 101960 101961 101962 101963 101964 101965 101966 101967 101968 101969 101970 101971 101972 101973 101974 101975 101976 101977 101978 101979 101980 101981 101982 101983 101984 101985 101986 101987 101988 101989 101990 101991 101992 101993 101994 101995 101996 101997 101998 101999 102000 102001 102002 102003 102004 102005 102006 102007 102008 102009 102010 102011 102012 102013 102014 102015 102016 102017 102018 102019 102020 102021 102022 102023 102024 102025 102026 102027 102028 102029 102030 102031 102032 102033 102034 102035 102036 102037 102038 102039 102040 102041 102042 102043 102044 102045 102046 102047 102048 102049 102050 102051 102052 102053 102054 102055 102056 102057 102058 102059 102060 102061 102062 102063 102064 102065 102066 102067 102068 102069 102070 102071 102072 102073 102074 102075 102076 102077 102078 102079 102080 102081 102082 102083 102084 102085 102086 102087 102088 102089 102090 102091 102092 102093 102094 102095 102096 102097 102098 102099 102100 102101 102102 102103 102104 102105 102106 102107 102108 102109 102110 102111 102112 102113 102114 102115 102116 102117 102118 102119 102120 102121 102122 102123 102124 102125 102126 102127 102128 102129 102130 102131 102132 102133 102134 102135 102136 102137 102138 102139 102140 102141 102142 102143 102144 102145 102146 102147 102148 102149 102150 102151 102152 102153 102154 102155 102156 102157 102158 102159 102160 102161 102162 102163 102164 102165 102166 102167 102168 102169 102170 102171 102172 102173 102174 102175 102176 102177 102178 102179 102180 102181 102182 102183 102184 102185 102186 102187 102188 102189 102190 102191 102192 102193 102194 102195 102196 102197 102198 102199 102200 102201 102202 102203 102204 102205 102206 102207 102208 102209 102210 102211 102212 102213 102214 102215 102216 102217 102218 102219 102220 102221 102222 102223 102224 102225 102226 102227 102228 102229 102230 102231 102232 102233 102234 102235 102236 102237 102238 102239 102240 102241 102242 102243 102244 102245 102246 102247 102248 102249 102250 102251 102252 102253 102254 102255 102256 102257 102258 102259 102260 102261 102262 102263 102264 102265 102266 102267 102268 102269 102270 102271 102272 102273 102274 102275 102276 102277 102278 102279 102280 102281 102282 102283 102284 102285 102286 102287 102288 102289 102290 102291 102292 102293 102294 102295 102296 102297 102298 102299 102300 102301 102302 102303 102304 102305 102306 102307 102308 102309 102310 102311 102312 102313 102314 102315 102316 102317 102318 102319 102320 102321 102322 102323 102324 102325 102326 102327 102328 102329 102330 102331 102332 102333 102334 102335 102336 102337 102338 102339 102340 102341 102342 102343 102344 102345 102346 102347 102348 102349 102350 102351 102352 102353 102354 102355 102356 102357 102358 102359 102360 102361 102362 102363 102364 102365 102366 102367 102368 102369 102370 102371 102372 102373 102374 102375 102376 102377 102378 102379 102380 102381 102382 102383 102384 102385 102386 102387 102388 102389 102390 102391 102392 102393 102394 102395 102396 102397 102398 102399 102400 102401 102402 102403 102404 102405 102406 102407 102408 102409 102410 102411 102412 102413 102414 102415 102416 102417 102418 102419 102420 102421 102422 102423 102424 102425 102426 102427 102428 102429 102430 102431 102432 102433 102434 102435 102436 102437 102438 102439 102440 102441 102442 102443 102444 102445 102446 102447 102448 102449 102450 102451 102452 102453 102454 102455 102456 102457 102458 102459 102460 102461 102462 102463 102464 102465 102466 102467 102468 102469 102470 102471 102472 102473 102474 102475 102476 102477 102478 102479 102480 102481 102482 102483 102484 102485 102486 102487 102488 102489 102490 102491 102492 102493 102494 102495 102496 102497 102498 102499 102500 102501 102502 102503 102504 102505 102506 102507 102508 102509 102510 102511 102512 102513 102514 102515 102516 102517 102518 102519 102520 102521 102522 102523 102524 102525 102526 102527 102528 102529 102530 102531 102532 102533 102534 102535 102536 102537 102538 102539 102540 102541 102542 102543 102544 102545 102546 102547 102548 102549 102550 102551 102552 102553 102554 102555 102556 102557 102558 102559 102560 102561 102562 102563 102564 102565 102566 102567 102568 102569 102570 102571 102572 102573 102574 102575 102576 102577 102578 102579 102580 102581 102582 102583 102584 102585 102586 102587 102588 102589 102590 102591 102592 102593 102594 102595 102596 102597 102598 102599 102600 102601 102602 102603 102604 102605 102606 102607 102608 102609 102610 102611 102612 102613 102614 102615 102616 102617 102618 102619 102620 102621 102622 102623 102624 102625 102626 102627 102628 102629 102630 102631 102632 102633 102634 102635 102636 102637 102638 102639 102640 102641 102642 102643 102644 102645 102646 102647 102648 102649 102650 102651 102652 102653 102654 102655 102656 102657 102658 102659 102660 102661 102662 102663 102664 102665 102666 102667 102668 102669 102670 102671 102672 102673 102674 102675 102676 102677 102678 102679 102680 102681 102682 102683 102684 102685 102686 102687 102688 102689 102690 102691 102692 102693 102694 102695 102696 102697 102698 102699 102700 102701 102702 102703 102704 102705 102706 102707 102708 102709 102710 102711 102712 102713 102714 102715 102716 102717 102718 102719 102720 102721 102722 102723 102724 102725 102726 102727 102728 102729 102730 102731 102732 102733 102734 102735 102736 102737 102738 102739 102740 102741 102742 102743 102744 102745 102746 102747 102748 102749 102750 102751 102752 102753 102754 102755 102756 102757 102758 102759 102760 102761 102762 102763 102764 102765 102766 102767 102768 102769 102770 102771 102772 102773 102774 102775 102776 102777 102778 102779 102780 102781 102782 102783 102784 102785 102786 102787 102788 102789 102790 102791 102792 102793 102794 102795 102796 102797 102798 102799 102800 102801 102802 102803 102804 102805 102806 102807 102808 102809 102810 102811 102812 102813 102814 102815 102816 102817 102818 102819 102820 102821 102822 102823 102824 102825 102826 102827 102828 102829 102830 102831 102832 102833 102834 102835 102836 102837 102838 102839 102840 102841 102842 102843 102844 102845 102846 102847 102848 102849 102850 102851 102852 102853 102854 102855 102856 102857 102858 102859 102860 102861 102862 102863 102864 102865 102866 102867 102868 102869 102870 102871 102872 102873 102874 102875 102876 102877 102878 102879 102880 102881 102882 102883 102884 102885 102886 102887 102888 102889 102890 102891 102892 102893 102894 102895 102896 102897 102898 102899 102900 102901 102902 102903 102904 102905 102906 102907 102908 102909 102910 102911 102912 102913 102914 102915 102916 102917 102918 102919 102920 102921 102922 102923 102924 102925 102926 102927 102928 102929 102930 102931 102932 102933 102934 102935 102936 102937 102938 102939 102940 102941 102942 102943 102944 102945 102946 102947 102948 102949 102950 102951 102952 102953 102954 102955 102956 102957 102958 102959 102960 102961 102962 102963 102964 102965 102966 102967 102968 102969 102970 102971 102972 102973 102974 102975 102976 102977 102978 102979 102980 102981 102982 102983 102984 102985 102986 102987 102988 102989 102990 102991 102992 102993 102994 102995 102996 102997 102998 102999 103000 103001 103002 103003 103004 103005 103006 103007 103008 103009 103010 103011 103012 103013 103014 103015 103016 103017 103018 103019 103020 103021 103022 103023 103024 103025 103026 103027 103028 103029 103030 103031 103032 103033 103034 103035 103036 103037 103038 103039 103040 103041 103042 103043 103044 103045 103046 103047 103048 103049 103050 103051 103052 103053 103054 103055 103056 103057 103058 103059 103060 103061 103062 103063 103064 103065 103066 103067 103068 103069 103070 103071 103072 103073 103074 103075 103076 103077 103078 103079 103080 103081 103082 103083 103084 103085 103086 103087 103088 103089 103090 103091 103092 103093 103094 103095 103096 103097 103098 103099 103100 103101 103102 103103 103104 103105 103106 103107 103108 103109 103110 103111 103112 103113 103114 103115 103116 103117 103118 103119 103120 103121 103122 103123 103124 103125 103126 103127 103128 103129 103130 103131 103132 103133 103134 103135 103136 103137 103138 103139 103140 103141 103142 103143 103144 103145 103146 103147 103148 103149 103150 103151 103152 103153 103154 103155 103156 103157 103158 103159 103160 103161 103162 103163 103164 103165 103166 103167 103168 103169 103170 103171 103172 103173 103174 103175 103176 103177 103178 103179 103180 103181 103182 103183 103184 103185 103186 103187 103188 103189 103190 103191 103192 103193 103194 103195 103196 103197 103198 103199 103200 103201 103202 103203 103204 103205 103206 103207 103208 103209 103210 103211 103212 103213 103214 103215 103216 103217 103218 103219 103220 103221 103222 103223 103224 103225 103226 103227 103228 103229 103230 103231 103232 103233 103234 103235 103236 103237 103238 103239 103240 103241 103242 103243 103244 103245 103246 103247 103248 103249 103250 103251 103252 103253 103254 103255 103256 103257 103258 103259 103260 103261 103262 103263 103264 103265 103266 103267 103268 103269 103270 103271 103272 103273 103274 103275 103276 103277 103278 103279 103280 103281 103282 103283 103284 103285 103286 103287 103288 103289 103290 103291 103292 103293 103294 103295 103296 103297 103298 103299 103300 103301 103302 103303 103304 103305 103306 103307 103308 103309 103310 103311 103312 103313 103314 103315 103316 103317 103318 103319 103320 103321 103322 103323 103324 103325 103326 103327 103328 103329 103330 103331 103332 103333 103334 103335 103336 103337 103338 103339 103340 103341 103342 103343 103344 103345 103346 103347 103348 103349 103350 103351 103352 103353 103354 103355 103356 103357 103358 103359 103360 103361 103362 103363 103364 103365 103366 103367 103368 103369 103370 103371 103372 103373 103374 103375 103376 103377 103378 103379 103380 103381 103382 103383 103384 103385 103386 103387 103388 103389 103390 103391 103392 103393 103394 103395 103396 103397 103398 103399 103400 103401 103402 103403 103404 103405 103406 103407 103408 103409 103410 103411 103412 103413 103414 103415 103416 103417 103418 103419 103420 103421 103422 103423 103424 103425 103426 103427 103428 103429 103430 103431 103432 103433 103434 103435 103436 103437 103438 103439 103440 103441 103442 103443 103444 103445 103446 103447 103448 103449 103450 103451 103452 103453 103454 103455 103456 103457 103458 103459 103460 103461 103462 103463 103464 103465 103466 103467 103468 103469 103470 103471 103472 103473 103474 103475 103476 103477 103478 103479 103480 103481 103482 103483 103484 103485 103486 103487 103488 103489 103490 103491 103492 103493 103494 103495 103496 103497 103498 103499 103500 103501 103502 103503 103504 103505 103506 103507 103508 103509 103510 103511 103512 103513 103514 103515 103516 103517 103518 103519 103520 103521 103522 103523 103524 103525 103526 103527 103528 103529 103530 103531 103532 103533 103534 103535 103536 103537 103538 103539 103540 103541 103542 103543 103544 103545 103546 103547 103548 103549 103550 103551 103552 103553 103554 103555 103556 103557 103558 103559 103560 103561 103562 103563 103564 103565 103566 103567 103568 103569 103570 103571 103572 103573 103574 103575 103576 103577 103578 103579 103580 103581 103582 103583 103584 103585 103586 103587 103588 103589 103590 103591 103592 103593 103594 103595 103596 103597 103598 103599 103600 103601 103602 103603 103604 103605 103606 103607 103608 103609 103610 103611 103612 103613 103614 103615 103616 103617 103618 103619 103620 103621 103622 103623 103624 103625 103626 103627 103628 103629 103630 103631 103632 103633 103634 103635 103636 103637 103638 103639 103640 103641 103642 103643 103644 103645 103646 103647 103648 103649 103650 103651 103652 103653 103654 103655 103656 103657 103658 103659 103660 103661 103662 103663 103664 103665 103666 103667 103668 103669 103670 103671 103672 103673 103674 103675 103676 103677 103678 103679 103680 103681 103682 103683 103684 103685 103686 103687 103688 103689 103690 103691 103692 103693 103694 103695 103696 103697 103698 103699 103700 103701 103702 103703 103704 103705 103706 103707 103708 103709 103710 103711 103712 103713 103714 103715 103716 103717 103718 103719 103720 103721 103722 103723 103724 103725 103726 103727 103728 103729 103730 103731 103732 103733 103734 103735 103736 103737 103738 103739 103740 103741 103742 103743 103744 103745 103746 103747 103748 103749 103750 103751 103752 103753 103754 103755 103756 103757 103758 103759 103760 103761 103762 103763 103764 103765 103766 103767 103768 103769 103770 103771 103772 103773 103774 103775 103776 103777 103778 103779 103780 103781 103782 103783 103784 103785 103786 103787 103788 103789 103790 103791 103792 103793 103794 103795 103796 103797 103798 103799 103800 103801 103802 103803 103804 103805 103806 103807 103808 103809 103810 103811 103812 103813 103814 103815 103816 103817 103818 103819 103820 103821 103822 103823 103824 103825 103826 103827 103828 103829 103830 103831 103832 103833 103834 103835 103836 103837 103838 103839 103840 103841 103842 103843 103844 103845 103846 103847 103848 103849 103850 103851 103852 103853 103854 103855 103856 103857 103858 103859 103860 103861 103862 103863 103864 103865 103866 103867 103868 103869 103870 103871 103872 103873 103874 103875 103876 103877 103878 103879 103880 103881 103882 103883 103884 103885 103886 103887 103888 103889 103890 103891 103892 103893 103894 103895 103896 103897 103898 103899 103900 103901 103902 103903 103904 103905 103906 103907 103908 103909 103910 103911 103912 103913 103914 103915 103916 103917 103918 103919 103920 103921 103922 103923 103924 103925 103926 103927 103928 103929 103930 103931 103932 103933 103934 103935 103936 103937 103938 103939 103940 103941 103942 103943 103944 103945 103946 103947 103948 103949 103950 103951 103952 103953 103954 103955 103956 103957 103958 103959 103960 103961 103962 103963 103964 103965 103966 103967 103968 103969 103970 103971 103972 103973 103974 103975 103976 103977 103978 103979 103980 103981 103982 103983 103984 103985 103986 103987 103988 103989 103990 103991 103992 103993 103994 103995 103996 103997 103998 103999 104000 104001 104002 104003 104004 104005 104006 104007 104008 104009 104010 104011 104012 104013 104014 104015 104016 104017 104018 104019 104020 104021 104022 104023 104024 104025 104026 104027 104028 104029 104030 104031 104032 104033 104034 104035 104036 104037 104038 104039 104040 104041 104042 104043 104044 104045 104046 104047 104048 104049 104050 104051 104052 104053 104054 104055 104056 104057 104058 104059 104060 104061 104062 104063 104064 104065 104066 104067 104068 104069 104070 104071 104072 104073 104074 104075 104076 104077 104078 104079 104080 104081 104082 104083 104084 104085 104086 104087 104088 104089 104090 104091 104092 104093 104094 104095 104096 104097 104098 104099 104100 104101 104102 104103 104104 104105 104106 104107 104108 104109 104110 104111 104112 104113 104114 104115 104116 104117 104118 104119 104120 104121 104122 104123 104124 104125 104126 104127 104128 104129 104130 104131 104132 104133 104134 104135 104136 104137 104138 104139 104140 104141 104142 104143 104144 104145 104146 104147 104148 104149 104150 104151 104152 104153 104154 104155 104156 104157 104158 104159 104160 104161 104162 104163 104164 104165 104166 104167 104168 104169 104170 104171 104172 104173 104174 104175 104176 104177 104178 104179 104180 104181 104182 104183 104184 104185 104186 104187 104188 104189 104190 104191 104192 104193 104194 104195 104196 104197 104198 104199 104200 104201 104202 104203 104204 104205 104206 104207 104208 104209 104210 104211 104212 104213 104214 104215 104216 104217 104218 104219 104220 104221 104222 104223 104224 104225 104226 104227 104228 104229 104230 104231 104232 104233 104234 104235 104236 104237 104238 104239 104240 104241 104242 104243 104244 104245 104246 104247 104248 104249 104250 104251 104252 104253 104254 104255 104256 104257 104258 104259 104260 104261 104262 104263 104264 104265 104266 104267 104268 104269 104270 104271 104272 104273 104274 104275 104276 104277 104278 104279 104280 104281 104282 104283 104284 104285 104286 104287 104288 104289 104290 104291 104292 104293 104294 104295 104296 104297 104298 104299 104300 104301 104302 104303 104304 104305 104306 104307 104308 104309 104310 104311 104312 104313 104314 104315 104316 104317 104318 104319 104320 104321 104322 104323 104324 104325 104326 104327 104328 104329 104330 104331 104332 104333 104334 104335 104336 104337 104338 104339 104340 104341 104342 104343 104344 104345 104346 104347 104348 104349 104350 104351 104352 104353 104354 104355 104356 104357 104358 104359 104360 104361 104362 104363 104364 104365 104366 104367 104368 104369 104370 104371 104372 104373 104374 104375 104376 104377 104378 104379 104380 104381 104382 104383 104384 104385 104386 104387 104388 104389 104390 104391 104392 104393 104394 104395 104396 104397 104398 104399 104400 104401 104402 104403 104404 104405 104406 104407 104408 104409 104410 104411 104412 104413 104414 104415 104416 104417 104418 104419 104420 104421 104422 104423 104424 104425 104426 104427 104428 104429 104430 104431 104432 104433 104434 104435 104436 104437 104438 104439 104440 104441 104442 104443 104444 104445 104446 104447 104448 104449 104450 104451 104452 104453 104454 104455 104456 104457 104458 104459 104460 104461 104462 104463 104464 104465 104466 104467 104468 104469 104470 104471 104472 104473 104474 104475 104476 104477 104478 104479 104480 104481 104482 104483 104484 104485 104486 104487 104488 104489 104490 104491 104492 104493 104494 104495 104496 104497 104498 104499 104500 104501 104502 104503 104504 104505 104506 104507 104508 104509 104510 104511 104512 104513 104514 104515 104516 104517 104518 104519 104520 104521 104522 104523 104524 104525 104526 104527 104528 104529 104530 104531 104532 104533 104534 104535 104536 104537 104538 104539 104540 104541 104542 104543 104544 104545 104546 104547 104548 104549 104550 104551 104552 104553 104554 104555 104556 104557 104558 104559 104560 104561 104562 104563 104564 104565 104566 104567 104568 104569 104570 104571 104572 104573 104574 104575 104576 104577 104578 104579 104580 104581 104582 104583 104584 104585 104586 104587 104588 104589 104590 104591 104592 104593 104594 104595 104596 104597 104598 104599 104600 104601 104602 104603 104604 104605 104606 104607 104608 104609 104610 104611 104612 104613 104614 104615 104616 104617 104618 104619 104620 104621 104622 104623 104624 104625 104626 104627 104628 104629 104630 104631 104632 104633 104634 104635 104636 104637 104638 104639 104640 104641 104642 104643 104644 104645 104646 104647 104648 104649 104650 104651 104652 104653 104654 104655 104656 104657 104658 104659 104660 104661 104662 104663 104664 104665 104666 104667 104668 104669 104670 104671 104672 104673 104674 104675 104676 104677 104678 104679 104680 104681 104682 104683 104684 104685 104686 104687 104688 104689 104690 104691 104692 104693 104694 104695 104696 104697 104698 104699 104700 104701 104702 104703 104704 104705 104706 104707 104708 104709 104710 104711 104712 104713 104714 104715 104716 104717 104718 104719 104720 104721 104722 104723 104724 104725 104726 104727 104728 104729 104730 104731 104732 104733 104734 104735 104736 104737 104738 104739 104740 104741 104742 104743 104744 104745 104746 104747 104748 104749 104750 104751 104752 104753 104754 104755 104756 104757 104758 104759 104760 104761 104762 104763 104764 104765 104766 104767 104768 104769 104770 104771 104772 104773 104774 104775 104776 104777 104778 104779 104780 104781 104782 104783 104784 104785 104786 104787 104788 104789 104790 104791 104792 104793 104794 104795 104796 104797 104798 104799 104800 104801 104802 104803 104804 104805 104806 104807 104808 104809 104810 104811 104812 104813 104814 104815 104816 104817 104818 104819 104820 104821 104822 104823 104824 104825 104826 104827 104828 104829 104830 104831 104832 104833 104834 104835 104836 104837 104838 104839 104840 104841 104842 104843 104844 104845 104846 104847 104848 104849 104850 104851 104852 104853 104854 104855 104856 104857 104858 104859 104860 104861 104862 104863 104864 104865 104866 104867 104868 104869 104870 104871 104872 104873 104874 104875 104876 104877 104878 104879 104880 104881 104882 104883 104884 104885 104886 104887 104888 104889 104890 104891 104892 104893 104894 104895 104896 104897 104898 104899 104900 104901 104902 104903 104904 104905 104906 104907 104908 104909 104910 104911 104912 104913 104914 104915 104916 104917 104918 104919 104920 104921 104922 104923 104924 104925 104926 104927 104928 104929 104930 104931 104932 104933 104934 104935 104936 104937 104938 104939 104940 104941 104942 104943 104944 104945 104946 104947 104948 104949 104950 104951 104952 104953 104954 104955 104956 104957 104958 104959 104960 104961 104962 104963 104964 104965 104966 104967 104968 104969 104970 104971 104972 104973 104974 104975 104976 104977 104978 104979 104980 104981 104982 104983 104984 104985 104986 104987 104988 104989 104990 104991 104992 104993 104994 104995 104996 104997 104998 104999 105000 105001 105002 105003 105004 105005 105006 105007 105008 105009 105010 105011 105012 105013 105014 105015 105016 105017 105018 105019 105020 105021 105022 105023 105024 105025 105026 105027 105028 105029 105030 105031 105032 105033 105034 105035 105036 105037 105038 105039 105040 105041 105042 105043 105044 105045 105046 105047 105048 105049 105050 105051 105052 105053 105054 105055 105056 105057 105058 105059 105060 105061 105062 105063 105064 105065 105066 105067 105068 105069 105070 105071 105072 105073 105074 105075 105076 105077 105078 105079 105080 105081 105082 105083 105084 105085 105086 105087 105088 105089 105090 105091 105092 105093 105094 105095 105096 105097 105098 105099 105100 105101 105102 105103 105104 105105 105106 105107 105108 105109 105110 105111 105112 105113 105114 105115 105116 105117 105118 105119 105120 105121 105122 105123 105124 105125 105126 105127 105128 105129 105130 105131 105132 105133 105134 105135 105136 105137 105138 105139 105140 105141 105142 105143 105144 105145 105146 105147 105148 105149 105150 105151 105152 105153 105154 105155 105156 105157 105158 105159 105160 105161 105162 105163 105164 105165 105166 105167 105168 105169 105170 105171 105172 105173 105174 105175 105176 105177 105178 105179 105180 105181 105182 105183 105184 105185 105186 105187 105188 105189 105190 105191 105192 105193 105194 105195 105196 105197 105198 105199 105200 105201 105202 105203 105204 105205 105206 105207 105208 105209 105210 105211 105212 105213 105214 105215 105216 105217 105218 105219 105220 105221 105222 105223 105224 105225 105226 105227 105228 105229 105230 105231 105232 105233 105234 105235 105236 105237 105238 105239 105240 105241 105242 105243 105244 105245 105246 105247 105248 105249 105250 105251 105252 105253 105254 105255 105256 105257 105258 105259 105260 105261 105262 105263 105264 105265 105266 105267 105268 105269 105270 105271 105272 105273 105274 105275 105276 105277 105278 105279 105280 105281 105282 105283 105284 105285 105286 105287 105288 105289 105290 105291 105292 105293 105294 105295 105296 105297 105298 105299 105300 105301 105302 105303 105304 105305 105306 105307 105308 105309 105310 105311 105312 105313 105314 105315 105316 105317 105318 105319 105320 105321 105322 105323 105324 105325 105326 105327 105328 105329 105330 105331 105332 105333 105334 105335 105336 105337 105338 105339 105340 105341 105342 105343 105344 105345 105346 105347 105348 105349 105350 105351 105352 105353 105354 105355 105356 105357 105358 105359 105360 105361 105362 105363 105364 105365 105366 105367 105368 105369 105370 105371 105372 105373 105374 105375 105376 105377 105378 105379 105380 105381 105382 105383 105384 105385 105386 105387 105388 105389 105390 105391 105392 105393 105394 105395 105396 105397 105398 105399 105400 105401 105402 105403 105404 105405 105406 105407 105408 105409 105410 105411 105412 105413 105414 105415 105416 105417 105418 105419 105420 105421 105422 105423 105424 105425 105426 105427 105428 105429 105430 105431 105432 105433 105434 105435 105436 105437 105438 105439 105440 105441 105442 105443 105444 105445 105446 105447 105448 105449 105450 105451 105452 105453 105454 105455 105456 105457 105458 105459 105460 105461 105462 105463 105464 105465 105466 105467 105468 105469 105470 105471 105472 105473 105474 105475 105476 105477 105478 105479 105480 105481 105482 105483 105484 105485 105486 105487 105488 105489 105490 105491 105492 105493 105494 105495 105496 105497 105498 105499 105500 105501 105502 105503 105504 105505 105506 105507 105508 105509 105510 105511 105512 105513 105514 105515 105516 105517 105518 105519 105520 105521 105522 105523 105524 105525 105526 105527 105528 105529 105530 105531 105532 105533 105534 105535 105536 105537 105538 105539 105540 105541 105542 105543 105544 105545 105546 105547 105548 105549 105550 105551 105552 105553 105554 105555 105556 105557 105558 105559 105560 105561 105562 105563 105564 105565 105566 105567 105568 105569 105570 105571 105572 105573 105574 105575 105576 105577 105578 105579 105580 105581 105582 105583 105584 105585 105586 105587 105588 105589 105590 105591 105592 105593 105594 105595 105596 105597 105598 105599 105600 105601 105602 105603 105604 105605 105606 105607 105608 105609 105610 105611 105612 105613 105614 105615 105616 105617 105618 105619 105620 105621 105622 105623 105624 105625 105626 105627 105628 105629 105630 105631 105632 105633 105634 105635 105636 105637 105638 105639 105640 105641 105642 105643 105644 105645 105646 105647 105648 105649 105650 105651 105652 105653 105654 105655 105656 105657 105658 105659 105660 105661 105662 105663 105664 105665 105666 105667 105668 105669 105670 105671 105672 105673 105674 105675 105676 105677 105678 105679 105680 105681 105682 105683 105684 105685 105686 105687 105688 105689 105690 105691 105692 105693 105694 105695 105696 105697 105698 105699 105700 105701 105702 105703 105704 105705 105706 105707 105708 105709 105710 105711 105712 105713 105714 105715 105716 105717 105718 105719 105720 105721 105722 105723 105724 105725 105726 105727 105728 105729 105730 105731 105732 105733 105734 105735 105736 105737 105738 105739 105740 105741 105742 105743 105744 105745 105746 105747 105748 105749 105750 105751 105752 105753 105754 105755 105756 105757 105758 105759 105760 105761 105762 105763 105764 105765 105766 105767 105768 105769 105770 105771 105772 105773 105774 105775 105776 105777 105778 105779 105780 105781 105782 105783 105784 105785 105786 105787 105788 105789 105790 105791 105792 105793 105794 105795 105796 105797 105798 105799 105800 105801 105802 105803 105804 105805 105806 105807 105808 105809 105810 105811 105812 105813 105814 105815 105816 105817 105818 105819 105820 105821 105822 105823 105824 105825 105826 105827 105828 105829 105830 105831 105832 105833 105834 105835 105836 105837 105838 105839 105840 105841 105842 105843 105844 105845 105846 105847 105848 105849 105850 105851 105852 105853 105854 105855 105856 105857 105858 105859 105860 105861 105862 105863 105864 105865 105866 105867 105868 105869 105870 105871 105872 105873 105874 105875 105876 105877 105878 105879 105880 105881 105882 105883 105884 105885 105886 105887 105888 105889 105890 105891 105892 105893 105894 105895 105896 105897 105898 105899 105900 105901 105902 105903 105904 105905 105906 105907 105908 105909 105910 105911 105912 105913 105914 105915 105916 105917 105918 105919 105920 105921 105922 105923 105924 105925 105926 105927 105928 105929 105930 105931 105932 105933 105934 105935 105936 105937 105938 105939 105940 105941 105942 105943 105944 105945 105946 105947 105948 105949 105950 105951 105952 105953 105954 105955 105956 105957 105958 105959 105960 105961 105962 105963 105964 105965 105966 105967 105968 105969 105970 105971 105972 105973 105974 105975 105976 105977 105978 105979 105980 105981 105982 105983 105984 105985 105986 105987 105988 105989 105990 105991 105992 105993 105994 105995 105996 105997 105998 105999 106000 106001 106002 106003 106004 106005 106006 106007 106008 106009 106010 106011 106012 106013 106014 106015 106016 106017 106018 106019 106020 106021 106022 106023 106024 106025 106026 106027 106028 106029 106030 106031 106032 106033 106034 106035 106036 106037 106038 106039 106040 106041 106042 106043 106044 106045 106046 106047 106048 106049 106050 106051 106052 106053 106054 106055 106056 106057 106058 106059 106060 106061 106062 106063 106064 106065 106066 106067 106068 106069 106070 106071 106072 106073 106074 106075 106076 106077 106078 106079 106080 106081 106082 106083 106084 106085 106086 106087 106088 106089 106090 106091 106092 106093 106094 106095 106096 106097 106098 106099 106100 106101 106102 106103 106104 106105 106106 106107 106108 106109 106110 106111 106112 106113 106114 106115 106116 106117 106118 106119 106120 106121 106122 106123 106124 106125 106126 106127 106128 106129 106130 106131 106132 106133 106134 106135 106136 106137 106138 106139 106140 106141 106142 106143 106144 106145 106146 106147 106148 106149 106150 106151 106152 106153 106154 106155 106156 106157 106158 106159 106160 106161 106162 106163 106164 106165 106166 106167 106168 106169 106170 106171 106172 106173 106174 106175 106176 106177 106178 106179 106180 106181 106182 106183 106184 106185 106186 106187 106188 106189 106190 106191 106192 106193 106194 106195 106196 106197 106198 106199 106200 106201 106202 106203 106204 106205 106206 106207 106208 106209 106210 106211 106212 106213 106214 106215 106216 106217 106218 106219 106220 106221 106222 106223 106224 106225 106226 106227 106228 106229 106230 106231 106232 106233 106234 106235 106236 106237 106238 106239 106240 106241 106242 106243 106244 106245 106246 106247 106248 106249 106250 106251 106252 106253 106254 106255 106256 106257 106258 106259 106260 106261 106262 106263 106264 106265 106266 106267 106268 106269 106270 106271 106272 106273 106274 106275 106276 106277 106278 106279 106280 106281 106282 106283 106284 106285 106286 106287 106288 106289 106290 106291 106292 106293 106294 106295 106296 106297 106298 106299 106300 106301 106302 106303 106304 106305 106306 106307 106308 106309 106310 106311 106312 106313 106314 106315 106316 106317 106318 106319 106320 106321 106322 106323 106324 106325 106326 106327 106328 106329 106330 106331 106332 106333 106334 106335 106336 106337 106338 106339 106340 106341 106342 106343 106344 106345 106346 106347 106348 106349 106350 106351 106352 106353 106354 106355 106356 106357 106358 106359 106360 106361 106362 106363 106364 106365 106366 106367 106368 106369 106370 106371 106372 106373 106374 106375 106376 106377 106378 106379 106380 106381 106382 106383 106384 106385 106386 106387 106388 106389 106390 106391 106392 106393 106394 106395 106396 106397 106398 106399 106400 106401 106402 106403 106404 106405 106406 106407 106408 106409 106410 106411 106412 106413 106414 106415 106416 106417 106418 106419 106420 106421 106422 106423 106424 106425 106426 106427 106428 106429 106430 106431 106432 106433 106434 106435 106436 106437 106438 106439 106440 106441 106442 106443 106444 106445 106446 106447 106448 106449 106450 106451 106452 106453 106454 106455 106456 106457 106458 106459 106460 106461 106462 106463 106464 106465 106466 106467 106468 106469 106470 106471 106472 106473 106474 106475 106476 106477 106478 106479 106480 106481 106482 106483 106484 106485 106486 106487 106488 106489 106490 106491 106492 106493 106494 106495 106496 106497 106498 106499 106500 106501 106502 106503 106504 106505 106506 106507 106508 106509 106510 106511 106512 106513 106514 106515 106516 106517 106518 106519 106520 106521 106522 106523 106524 106525 106526 106527 106528 106529 106530 106531 106532 106533 106534 106535 106536 106537 106538 106539 106540 106541 106542 106543 106544 106545 106546 106547 106548 106549 106550 106551 106552 106553 106554 106555 106556 106557 106558 106559 106560 106561 106562 106563 106564 106565 106566 106567 106568 106569 106570 106571 106572 106573 106574 106575 106576 106577 106578 106579 106580 106581 106582 106583 106584 106585 106586 106587 106588 106589 106590 106591 106592 106593 106594 106595 106596 106597 106598 106599 106600 106601 106602 106603 106604 106605 106606 106607 106608 106609 106610 106611 106612 106613 106614 106615 106616 106617 106618 106619 106620 106621 106622 106623 106624 106625 106626 106627 106628 106629 106630 106631 106632 106633 106634 106635 106636 106637 106638 106639 106640 106641 106642 106643 106644 106645 106646 106647 106648 106649 106650 106651 106652 106653 106654 106655 106656 106657 106658 106659 106660 106661 106662 106663 106664 106665 106666 106667 106668 106669 106670 106671 106672 106673 106674 106675 106676 106677 106678 106679 106680 106681 106682 106683 106684 106685 106686 106687 106688 106689 106690 106691 106692 106693 106694 106695 106696 106697 106698 106699 106700 106701 106702 106703 106704 106705 106706 106707 106708 106709 106710 106711 106712 106713 106714 106715 106716 106717 106718 106719 106720 106721 106722 106723 106724 106725 106726 106727 106728 106729 106730 106731 106732 106733 106734 106735 106736 106737 106738 106739 106740 106741 106742 106743 106744 106745 106746 106747 106748 106749 106750 106751 106752 106753 106754 106755 106756 106757 106758 106759 106760 106761 106762 106763 106764 106765 106766 106767 106768 106769 106770 106771 106772 106773 106774 106775 106776 106777 106778 106779 106780 106781 106782 106783 106784 106785 106786 106787 106788 106789 106790 106791 106792 106793 106794 106795 106796 106797 106798 106799 106800 106801 106802 106803 106804 106805 106806 106807 106808 106809 106810 106811 106812 106813 106814 106815 106816 106817 106818 106819 106820 106821 106822 106823 106824 106825 106826 106827 106828 106829 106830 106831 106832 106833 106834 106835 106836 106837 106838 106839 106840 106841 106842 106843 106844 106845 106846 106847 106848 106849 106850 106851 106852 106853 106854 106855 106856 106857 106858 106859 106860 106861 106862 106863 106864 106865 106866 106867 106868 106869 106870 106871 106872 106873 106874 106875 106876 106877 106878 106879 106880 106881 106882 106883 106884 106885 106886 106887 106888 106889 106890 106891 106892 106893 106894 106895 106896 106897 106898 106899 106900 106901 106902 106903 106904 106905 106906 106907 106908 106909 106910 106911 106912 106913 106914 106915 106916 106917 106918 106919 106920 106921 106922 106923 106924 106925 106926 106927 106928 106929 106930 106931 106932 106933 106934 106935 106936 106937 106938 106939 106940 106941 106942 106943 106944 106945 106946 106947 106948 106949 106950 106951 106952 106953 106954 106955 106956 106957 106958 106959 106960 106961 106962 106963 106964 106965 106966 106967 106968 106969 106970 106971 106972 106973 106974 106975 106976 106977 106978 106979 106980 106981 106982 106983 106984 106985 106986 106987 106988 106989 106990 106991 106992 106993 106994 106995 106996 106997 106998 106999 107000 107001 107002 107003 107004 107005 107006 107007 107008 107009 107010 107011 107012 107013 107014 107015 107016 107017 107018 107019 107020 107021 107022 107023 107024 107025 107026 107027 107028 107029 107030 107031 107032 107033 107034 107035 107036 107037 107038 107039 107040 107041 107042 107043 107044 107045 107046 107047 107048 107049 107050 107051 107052 107053 107054 107055 107056 107057 107058 107059 107060 107061 107062 107063 107064 107065 107066 107067 107068 107069 107070 107071 107072 107073 107074 107075 107076 107077 107078 107079 107080 107081 107082 107083 107084 107085 107086 107087 107088 107089 107090 107091 107092 107093 107094 107095 107096 107097 107098 107099 107100 107101 107102 107103 107104 107105 107106 107107 107108 107109 107110 107111 107112 107113 107114 107115 107116 107117 107118 107119 107120 107121 107122 107123 107124 107125 107126 107127 107128 107129 107130 107131 107132 107133 107134 107135 107136 107137 107138 107139 107140 107141 107142 107143 107144 107145 107146 107147 107148 107149 107150 107151 107152 107153 107154 107155 107156 107157 107158 107159 107160 107161 107162 107163 107164 107165 107166 107167 107168 107169 107170 107171 107172 107173 107174 107175 107176 107177 107178 107179 107180 107181 107182 107183 107184 107185 107186 107187 107188 107189 107190 107191 107192 107193 107194 107195 107196 107197 107198 107199 107200 107201 107202 107203 107204 107205 107206 107207 107208 107209 107210 107211 107212 107213 107214 107215 107216 107217 107218 107219 107220 107221 107222 107223 107224 107225 107226 107227 107228 107229 107230 107231 107232 107233 107234 107235 107236 107237 107238 107239 107240 107241 107242 107243 107244 107245 107246 107247 107248 107249 107250 107251 107252 107253 107254 107255 107256 107257 107258 107259 107260 107261 107262 107263 107264 107265 107266 107267 107268 107269 107270 107271 107272 107273 107274 107275 107276 107277 107278 107279 107280 107281 107282 107283 107284 107285 107286 107287 107288 107289 107290 107291 107292 107293 107294 107295 107296 107297 107298 107299 107300 107301 107302 107303 107304 107305 107306 107307 107308 107309 107310 107311 107312 107313 107314 107315 107316 107317 107318 107319 107320 107321 107322 107323 107324 107325 107326 107327 107328 107329 107330 107331 107332 107333 107334 107335 107336 107337 107338 107339 107340 107341 107342 107343 107344 107345 107346 107347 107348 107349 107350 107351 107352 107353 107354 107355 107356 107357 107358 107359 107360 107361 107362 107363 107364 107365 107366 107367 107368 107369 107370 107371 107372 107373 107374 107375 107376 107377 107378 107379 107380 107381 107382 107383 107384 107385 107386 107387 107388 107389 107390 107391 107392 107393 107394 107395 107396 107397 107398 107399 107400 107401 107402 107403 107404 107405 107406 107407 107408 107409 107410 107411 107412 107413 107414 107415 107416 107417 107418 107419 107420 107421 107422 107423 107424 107425 107426 107427 107428 107429 107430 107431 107432 107433 107434 107435 107436 107437 107438 107439 107440 107441 107442 107443 107444 107445 107446 107447 107448 107449 107450 107451 107452 107453 107454 107455 107456 107457 107458 107459 107460 107461 107462 107463 107464 107465 107466 107467 107468 107469 107470 107471 107472 107473 107474 107475 107476 107477 107478 107479 107480 107481 107482 107483 107484 107485 107486 107487 107488 107489 107490 107491 107492 107493 107494 107495 107496 107497 107498 107499 107500 107501 107502 107503 107504 107505 107506 107507 107508 107509 107510 107511 107512 107513 107514 107515 107516 107517 107518 107519 107520 107521 107522 107523 107524 107525 107526 107527 107528 107529 107530 107531 107532 107533 107534 107535 107536 107537 107538 107539 107540 107541 107542 107543 107544 107545 107546 107547 107548 107549 107550 107551 107552 107553 107554 107555 107556 107557 107558 107559 107560 107561 107562 107563 107564 107565 107566 107567 107568 107569 107570 107571 107572 107573 107574 107575 107576 107577 107578 107579 107580 107581 107582 107583 107584 107585 107586 107587 107588 107589 107590 107591 107592 107593 107594 107595 107596 107597 107598 107599 107600 107601 107602 107603 107604 107605 107606 107607 107608 107609 107610 107611 107612 107613 107614 107615 107616 107617 107618 107619 107620 107621 107622 107623 107624 107625 107626 107627 107628 107629 107630 107631 107632 107633 107634 107635 107636 107637 107638 107639 107640 107641 107642 107643 107644 107645 107646 107647 107648 107649 107650 107651 107652 107653 107654 107655 107656 107657 107658 107659 107660 107661 107662 107663 107664 107665 107666 107667 107668 107669 107670 107671 107672 107673 107674 107675 107676 107677 107678 107679 107680 107681 107682 107683 107684 107685 107686 107687 107688 107689 107690 107691 107692 107693 107694 107695 107696 107697 107698 107699 107700 107701 107702 107703 107704 107705 107706 107707 107708 107709 107710 107711 107712 107713 107714 107715 107716 107717 107718 107719 107720 107721 107722 107723 107724 107725 107726 107727 107728 107729 107730 107731 107732 107733 107734 107735 107736 107737 107738 107739 107740 107741 107742 107743 107744 107745 107746 107747 107748 107749 107750 107751 107752 107753 107754 107755 107756 107757 107758 107759 107760 107761 107762 107763 107764 107765 107766 107767 107768 107769 107770 107771 107772 107773 107774 107775 107776 107777 107778 107779 107780 107781 107782 107783 107784 107785 107786 107787 107788 107789 107790 107791 107792 107793 107794 107795 107796 107797 107798 107799 107800 107801 107802 107803 107804 107805 107806 107807 107808 107809 107810 107811 107812 107813 107814 107815 107816 107817 107818 107819 107820 107821 107822 107823 107824 107825 107826 107827 107828 107829 107830 107831 107832 107833 107834 107835 107836 107837 107838 107839 107840 107841 107842 107843 107844 107845 107846 107847 107848 107849 107850 107851 107852 107853 107854 107855 107856 107857 107858 107859 107860 107861 107862 107863 107864 107865 107866 107867 107868 107869 107870 107871 107872 107873 107874 107875 107876 107877 107878 107879 107880 107881 107882 107883 107884 107885 107886 107887 107888 107889 107890 107891 107892 107893 107894 107895 107896 107897 107898 107899 107900 107901 107902 107903 107904 107905 107906 107907 107908 107909 107910 107911 107912 107913 107914 107915 107916 107917 107918 107919 107920 107921 107922 107923 107924 107925 107926 107927 107928 107929 107930 107931 107932 107933 107934 107935 107936 107937 107938 107939 107940 107941 107942 107943 107944 107945 107946 107947 107948 107949 107950 107951 107952 107953 107954 107955 107956 107957 107958 107959 107960 107961 107962 107963 107964 107965 107966 107967 107968 107969 107970 107971 107972 107973 107974 107975 107976 107977 107978 107979 107980 107981 107982 107983 107984 107985 107986 107987 107988 107989 107990 107991 107992 107993 107994 107995 107996 107997 107998 107999 108000 108001 108002 108003 108004 108005 108006 108007 108008 108009 108010 108011 108012 108013 108014 108015 108016 108017 108018 108019 108020 108021 108022 108023 108024 108025 108026 108027 108028 108029 108030 108031 108032 108033 108034 108035 108036 108037 108038 108039 108040 108041 108042 108043 108044 108045 108046 108047 108048 108049 108050 108051 108052 108053 108054 108055 108056 108057 108058 108059 108060 108061 108062 108063 108064 108065 108066 108067 108068 108069 108070 108071 108072 108073 108074 108075 108076 108077 108078 108079 108080 108081 108082 108083 108084 108085 108086 108087 108088 108089 108090 108091 108092 108093 108094 108095 108096 108097 108098 108099 108100 108101 108102 108103 108104 108105 108106 108107 108108 108109 108110 108111 108112 108113 108114 108115 108116 108117 108118 108119 108120 108121 108122 108123 108124 108125 108126 108127 108128 108129 108130 108131 108132 108133 108134 108135 108136 108137 108138 108139 108140 108141 108142 108143 108144 108145 108146 108147 108148 108149 108150 108151 108152 108153 108154 108155 108156 108157 108158 108159 108160 108161 108162 108163 108164 108165 108166 108167 108168 108169 108170 108171 108172 108173 108174 108175 108176 108177 108178 108179 108180 108181 108182 108183 108184 108185 108186 108187 108188 108189 108190 108191 108192 108193 108194 108195 108196 108197 108198 108199 108200 108201 108202 108203 108204 108205 108206 108207 108208 108209 108210 108211 108212 108213 108214 108215 108216 108217 108218 108219 108220 108221 108222 108223 108224 108225 108226 108227 108228 108229 108230 108231 108232 108233 108234 108235 108236 108237 108238 108239 108240 108241 108242 108243 108244 108245 108246 108247 108248 108249 108250 108251 108252 108253 108254 108255 108256 108257 108258 108259 108260 108261 108262 108263 108264 108265 108266 108267 108268 108269 108270 108271 108272 108273 108274 108275 108276 108277 108278 108279 108280 108281 108282 108283 108284 108285 108286 108287 108288 108289 108290 108291 108292 108293 108294 108295 108296 108297 108298 108299 108300 108301 108302 108303 108304 108305 108306 108307 108308 108309 108310 108311 108312 108313 108314 108315 108316 108317 108318 108319 108320 108321 108322 108323 108324 108325 108326 108327 108328 108329 108330 108331 108332 108333 108334 108335 108336 108337 108338 108339 108340 108341 108342 108343 108344 108345 108346 108347 108348 108349 108350 108351 108352 108353 108354 108355 108356 108357 108358 108359 108360 108361 108362 108363 108364 108365 108366 108367 108368 108369 108370 108371 108372 108373 108374 108375 108376 108377 108378 108379 108380 108381 108382 108383 108384 108385 108386 108387 108388 108389 108390 108391 108392 108393 108394 108395 108396 108397 108398 108399 108400 108401 108402 108403 108404 108405 108406 108407 108408 108409 108410 108411 108412 108413 108414 108415 108416 108417 108418 108419 108420 108421 108422 108423 108424 108425 108426 108427 108428 108429 108430 108431 108432 108433 108434 108435 108436 108437 108438 108439 108440 108441 108442 108443 108444 108445 108446 108447 108448 108449 108450 108451 108452 108453 108454 108455 108456 108457 108458 108459 108460 108461 108462 108463 108464 108465 108466 108467 108468 108469 108470 108471 108472 108473 108474 108475 108476 108477 108478 108479 108480 108481 108482 108483 108484 108485 108486 108487 108488 108489 108490 108491 108492 108493 108494 108495 108496 108497 108498 108499 108500 108501 108502 108503 108504 108505 108506 108507 108508 108509 108510 108511 108512 108513 108514 108515 108516 108517 108518 108519 108520 108521 108522 108523 108524 108525 108526 108527 108528 108529 108530 108531 108532 108533 108534 108535 108536 108537 108538 108539 108540 108541 108542 108543 108544 108545 108546 108547 108548 108549 108550 108551 108552 108553 108554 108555 108556 108557 108558 108559 108560 108561 108562 108563 108564 108565 108566 108567 108568 108569 108570 108571 108572 108573 108574 108575 108576 108577 108578 108579 108580 108581 108582 108583 108584 108585 108586 108587 108588 108589 108590 108591 108592 108593 108594 108595 108596 108597 108598 108599 108600 108601 108602 108603 108604 108605 108606 108607 108608 108609 108610 108611 108612 108613 108614 108615 108616 108617 108618 108619 108620 108621 108622 108623 108624 108625 108626 108627 108628 108629 108630 108631 108632 108633 108634 108635 108636 108637 108638 108639 108640 108641 108642 108643 108644 108645 108646 108647 108648 108649 108650 108651 108652 108653 108654 108655 108656 108657 108658 108659 108660 108661 108662 108663 108664 108665 108666 108667 108668 108669 108670 108671 108672 108673 108674 108675 108676 108677 108678 108679 108680 108681 108682 108683 108684 108685 108686 108687 108688 108689 108690 108691 108692 108693 108694 108695 108696 108697 108698 108699 108700 108701 108702 108703 108704 108705 108706 108707 108708 108709 108710 108711 108712 108713 108714 108715 108716 108717 108718 108719 108720 108721 108722 108723 108724 108725 108726 108727 108728 108729 108730 108731 108732 108733 108734 108735 108736 108737 108738 108739 108740 108741 108742 108743 108744 108745 108746 108747 108748 108749 108750 108751 108752 108753 108754 108755 108756 108757 108758 108759 108760 108761 108762 108763 108764 108765 108766 108767 108768 108769 108770 108771 108772 108773 108774 108775 108776 108777 108778 108779 108780 108781 108782 108783 108784 108785 108786 108787 108788 108789 108790 108791 108792 108793 108794 108795 108796 108797 108798 108799 108800 108801 108802 108803 108804 108805 108806 108807 108808 108809 108810 108811 108812 108813 108814 108815 108816 108817 108818 108819 108820 108821 108822 108823 108824 108825 108826 108827 108828 108829 108830 108831 108832 108833 108834 108835 108836 108837 108838 108839 108840 108841 108842 108843 108844 108845 108846 108847 108848 108849 108850 108851 108852 108853 108854 108855 108856 108857 108858 108859 108860 108861 108862 108863 108864 108865 108866 108867 108868 108869 108870 108871 108872 108873 108874 108875 108876 108877 108878 108879 108880 108881 108882 108883 108884 108885 108886 108887 108888 108889 108890 108891 108892 108893 108894 108895 108896 108897 108898 108899 108900 108901 108902 108903 108904 108905 108906 108907 108908 108909 108910 108911 108912 108913 108914 108915 108916 108917 108918 108919 108920 108921 108922 108923 108924 108925 108926 108927 108928 108929 108930 108931 108932 108933 108934 108935 108936 108937 108938 108939 108940 108941 108942 108943 108944 108945 108946 108947 108948 108949 108950 108951 108952 108953 108954 108955 108956 108957 108958 108959 108960 108961 108962 108963 108964 108965 108966 108967 108968 108969 108970 108971 108972 108973 108974 108975 108976 108977 108978 108979 108980 108981 108982 108983 108984 108985 108986 108987 108988 108989 108990 108991 108992 108993 108994 108995 108996 108997 108998 108999 109000 109001 109002 109003 109004 109005 109006 109007 109008 109009 109010 109011 109012 109013 109014 109015 109016 109017 109018 109019 109020 109021 109022 109023 109024 109025 109026 109027 109028 109029 109030 109031 109032 109033 109034 109035 109036 109037 109038 109039 109040 109041 109042 109043 109044 109045 109046 109047 109048 109049 109050 109051 109052 109053 109054 109055 109056 109057 109058 109059 109060 109061 109062 109063 109064 109065 109066 109067 109068 109069 109070 109071 109072 109073 109074 109075 109076 109077 109078 109079 109080 109081 109082 109083 109084 109085 109086 109087 109088 109089 109090 109091 109092 109093 109094 109095 109096 109097 109098 109099 109100 109101 109102 109103 109104 109105 109106 109107 109108 109109 109110 109111 109112 109113 109114 109115 109116 109117 109118 109119 109120 109121 109122 109123 109124 109125 109126 109127 109128 109129 109130 109131 109132 109133 109134 109135 109136 109137 109138 109139 109140 109141 109142 109143 109144 109145 109146 109147 109148 109149 109150 109151 109152 109153 109154 109155 109156 109157 109158 109159 109160 109161 109162 109163 109164 109165 109166 109167 109168 109169 109170 109171 109172 109173 109174 109175 109176 109177 109178 109179 109180 109181 109182 109183 109184 109185 109186 109187 109188 109189 109190 109191 109192 109193 109194 109195 109196 109197 109198 109199 109200 109201 109202 109203 109204 109205 109206 109207 109208 109209 109210 109211 109212 109213 109214 109215 109216 109217 109218 109219 109220 109221 109222 109223 109224 109225 109226 109227 109228 109229 109230 109231 109232 109233 109234 109235 109236 109237 109238 109239 109240 109241 109242 109243 109244 109245 109246 109247 109248 109249 109250 109251 109252 109253 109254 109255 109256 109257 109258 109259 109260 109261 109262 109263 109264 109265 109266 109267 109268 109269 109270 109271 109272 109273 109274 109275 109276 109277 109278 109279 109280 109281 109282 109283 109284 109285 109286 109287 109288 109289 109290 109291 109292 109293 109294 109295 109296 109297 109298 109299 109300 109301 109302 109303 109304 109305 109306 109307 109308 109309 109310 109311 109312 109313 109314 109315 109316 109317 109318 109319 109320 109321 109322 109323 109324 109325 109326 109327 109328 109329 109330 109331 109332 109333 109334 109335 109336 109337 109338 109339 109340 109341 109342 109343 109344 109345 109346 109347 109348 109349 109350 109351 109352 109353 109354 109355 109356 109357 109358 109359 109360 109361 109362 109363 109364 109365 109366 109367 109368 109369 109370 109371 109372 109373 109374 109375 109376 109377 109378 109379 109380 109381 109382 109383 109384 109385 109386 109387 109388 109389 109390 109391 109392 109393 109394 109395 109396 109397 109398 109399 109400 109401 109402 109403 109404 109405 109406 109407 109408 109409 109410 109411 109412 109413 109414 109415 109416 109417 109418 109419 109420 109421 109422 109423 109424 109425 109426 109427 109428 109429 109430 109431 109432 109433 109434 109435 109436 109437 109438 109439 109440 109441 109442 109443 109444 109445 109446 109447 109448 109449 109450 109451 109452 109453 109454 109455 109456 109457 109458 109459 109460 109461 109462 109463 109464 109465 109466 109467 109468 109469 109470 109471 109472 109473 109474 109475 109476 109477 109478 109479 109480 109481 109482 109483 109484 109485 109486 109487 109488 109489 109490 109491 109492 109493 109494 109495 109496 109497 109498 109499 109500 109501 109502 109503 109504 109505 109506 109507 109508 109509 109510 109511 109512 109513 109514 109515 109516 109517 109518 109519 109520 109521 109522 109523 109524 109525 109526 109527 109528 109529 109530 109531 109532 109533 109534 109535 109536 109537 109538 109539 109540 109541 109542 109543 109544 109545 109546 109547 109548 109549 109550 109551 109552 109553 109554 109555 109556 109557 109558 109559 109560 109561 109562 109563 109564 109565 109566 109567 109568 109569 109570 109571 109572 109573 109574 109575 109576 109577 109578 109579 109580 109581 109582 109583 109584 109585 109586 109587 109588 109589 109590 109591 109592 109593 109594 109595 109596 109597 109598 109599 109600 109601 109602 109603 109604 109605 109606 109607 109608 109609 109610 109611 109612 109613 109614 109615 109616 109617 109618 109619 109620 109621 109622 109623 109624 109625 109626 109627 109628 109629 109630 109631 109632 109633 109634 109635 109636 109637 109638 109639 109640 109641 109642 109643 109644 109645 109646 109647 109648 109649 109650 109651 109652 109653 109654 109655 109656 109657 109658 109659 109660 109661 109662 109663 109664 109665 109666 109667 109668 109669 109670 109671 109672 109673 109674 109675 109676 109677 109678 109679 109680 109681 109682 109683 109684 109685 109686 109687 109688 109689 109690 109691 109692 109693 109694 109695 109696 109697 109698 109699 109700 109701 109702 109703 109704 109705 109706 109707 109708 109709 109710 109711 109712 109713 109714 109715 109716 109717 109718 109719 109720 109721 109722 109723 109724 109725 109726 109727 109728 109729 109730 109731 109732 109733 109734 109735 109736 109737 109738 109739 109740 109741 109742 109743 109744 109745 109746 109747 109748 109749 109750 109751 109752 109753 109754 109755 109756 109757 109758 109759 109760 109761 109762 109763 109764 109765 109766 109767 109768 109769 109770 109771 109772 109773 109774 109775 109776 109777 109778 109779 109780 109781 109782 109783 109784 109785 109786 109787 109788 109789 109790 109791 109792 109793 109794 109795 109796 109797 109798 109799 109800 109801 109802 109803 109804 109805 109806 109807 109808 109809 109810 109811 109812 109813 109814 109815 109816 109817 109818 109819 109820 109821 109822 109823 109824 109825 109826 109827 109828 109829 109830 109831 109832 109833 109834 109835 109836 109837 109838 109839 109840 109841 109842 109843 109844 109845 109846 109847 109848 109849 109850 109851 109852 109853 109854 109855 109856 109857 109858 109859 109860 109861 109862 109863 109864 109865 109866 109867 109868 109869 109870 109871 109872 109873 109874 109875 109876 109877 109878 109879 109880 109881 109882 109883 109884 109885 109886 109887 109888 109889 109890 109891 109892 109893 109894 109895 109896 109897 109898 109899 109900 109901 109902 109903 109904 109905 109906 109907 109908 109909 109910 109911 109912 109913 109914 109915 109916 109917 109918 109919 109920 109921 109922 109923 109924 109925 109926 109927 109928 109929 109930 109931 109932 109933 109934 109935 109936 109937 109938 109939 109940 109941 109942 109943 109944 109945 109946 109947 109948 109949 109950 109951 109952 109953 109954 109955 109956 109957 109958 109959 109960 109961 109962 109963 109964 109965 109966 109967 109968 109969 109970 109971 109972 109973 109974 109975 109976 109977 109978 109979 109980 109981 109982 109983 109984 109985 109986 109987 109988 109989 109990 109991 109992 109993 109994 109995 109996 109997 109998 109999 110000 110001 110002 110003 110004 110005 110006 110007 110008 110009 110010 110011 110012 110013 110014 110015 110016 110017 110018 110019 110020 110021 110022 110023 110024 110025 110026 110027 110028 110029 110030 110031 110032 110033 110034 110035 110036 110037 110038 110039 110040 110041 110042 110043 110044 110045 110046 110047 110048 110049 110050 110051 110052 110053 110054 110055 110056 110057 110058 110059 110060 110061 110062 110063 110064 110065 110066 110067 110068 110069 110070 110071 110072 110073 110074 110075 110076 110077 110078 110079 110080 110081 110082 110083 110084 110085 110086 110087 110088 110089 110090 110091 110092 110093 110094 110095 110096 110097 110098 110099 110100 110101 110102 110103 110104 110105 110106 110107 110108 110109 110110 110111 110112 110113 110114 110115 110116 110117 110118 110119 110120 110121 110122 110123 110124 110125 110126 110127 110128 110129 110130 110131 110132 110133 110134 110135 110136 110137 110138 110139 110140 110141 110142 110143 110144 110145 110146 110147 110148 110149 110150 110151 110152 110153 110154 110155 110156 110157 110158 110159 110160 110161 110162 110163 110164 110165 110166 110167 110168 110169 110170 110171 110172 110173 110174 110175 110176 110177 110178 110179 110180 110181 110182 110183 110184 110185 110186 110187 110188 110189 110190 110191 110192 110193 110194 110195 110196 110197 110198 110199 110200 110201 110202 110203 110204 110205 110206 110207 110208 110209 110210 110211 110212 110213 110214 110215 110216 110217 110218 110219 110220 110221 110222 110223 110224 110225 110226 110227 110228 110229 110230 110231 110232 110233 110234 110235 110236 110237 110238 110239 110240 110241 110242 110243 110244 110245 110246 110247 110248 110249 110250 110251 110252 110253 110254 110255 110256 110257 110258 110259 110260 110261 110262 110263 110264 110265 110266 110267 110268 110269 110270 110271 110272 110273 110274 110275 110276 110277 110278 110279 110280 110281 110282 110283 110284 110285 110286 110287 110288 110289 110290 110291 110292 110293 110294 110295 110296 110297 110298 110299 110300 110301 110302 110303 110304 110305 110306 110307 110308 110309 110310 110311 110312 110313 110314 110315 110316 110317 110318 110319 110320 110321 110322 110323 110324 110325 110326 110327 110328 110329 110330 110331 110332 110333 110334 110335 110336 110337 110338 110339 110340 110341 110342 110343 110344 110345 110346 110347 110348 110349 110350 110351 110352 110353 110354 110355 110356 110357 110358 110359 110360 110361 110362 110363 110364 110365 110366 110367 110368 110369 110370 110371 110372 110373 110374 110375 110376 110377 110378 110379 110380 110381 110382 110383 110384 110385 110386 110387 110388 110389 110390 110391 110392 110393 110394 110395 110396 110397 110398 110399 110400 110401 110402 110403 110404 110405 110406 110407 110408 110409 110410 110411 110412 110413 110414 110415 110416 110417 110418 110419 110420 110421 110422 110423 110424 110425 110426 110427 110428 110429 110430 110431 110432 110433 110434 110435 110436 110437 110438 110439 110440 110441 110442 110443 110444 110445 110446 110447 110448 110449 110450 110451 110452 110453 110454 110455 110456 110457 110458 110459 110460 110461 110462 110463 110464 110465 110466 110467 110468 110469 110470 110471 110472 110473 110474 110475 110476 110477 110478 110479 110480 110481 110482 110483 110484 110485 110486 110487 110488 110489 110490 110491 110492 110493 110494 110495 110496 110497 110498 110499 110500 110501 110502 110503 110504 110505 110506 110507 110508 110509 110510 110511 110512 110513 110514 110515 110516 110517 110518 110519 110520 110521 110522 110523 110524 110525 110526 110527 110528 110529 110530 110531 110532 110533 110534 110535 110536 110537 110538 110539 110540 110541 110542 110543 110544 110545 110546 110547 110548 110549 110550 110551 110552 110553 110554 110555 110556 110557 110558 110559 110560 110561 110562 110563 110564 110565 110566 110567 110568 110569 110570 110571 110572 110573 110574 110575 110576 110577 110578 110579 110580 110581 110582 110583 110584 110585 110586 110587 110588 110589 110590 110591 110592 110593 110594 110595 110596 110597 110598 110599 110600 110601 110602 110603 110604 110605 110606 110607 110608 110609 110610 110611 110612 110613 110614 110615 110616 110617 110618 110619 110620 110621 110622 110623 110624 110625 110626 110627 110628 110629 110630 110631 110632 110633 110634 110635 110636 110637 110638 110639 110640 110641 110642 110643 110644 110645 110646 110647 110648 110649 110650 110651 110652 110653 110654 110655 110656 110657 110658 110659 110660 110661 110662 110663 110664 110665 110666 110667 110668 110669 110670 110671 110672 110673 110674 110675 110676 110677 110678 110679 110680 110681 110682 110683 110684 110685 110686 110687 110688 110689 110690 110691 110692 110693 110694 110695 110696 110697 110698 110699 110700 110701 110702 110703 110704 110705 110706 110707 110708 110709 110710 110711 110712 110713 110714 110715 110716 110717 110718 110719 110720 110721 110722 110723 110724 110725 110726 110727 110728 110729 110730 110731 110732 110733 110734 110735 110736 110737 110738 110739 110740 110741 110742 110743 110744 110745 110746 110747 110748 110749 110750 110751 110752 110753 110754 110755 110756 110757 110758 110759 110760 110761 110762 110763 110764 110765 110766 110767 110768 110769 110770 110771 110772 110773 110774 110775 110776 110777 110778 110779 110780 110781 110782 110783 110784 110785 110786 110787 110788 110789 110790 110791 110792 110793 110794 110795 110796 110797 110798 110799 110800 110801 110802 110803 110804 110805 110806 110807 110808 110809 110810 110811 110812 110813 110814 110815 110816 110817 110818 110819 110820 110821 110822 110823 110824 110825 110826 110827 110828 110829 110830 110831 110832 110833 110834 110835 110836 110837 110838 110839 110840 110841 110842 110843 110844 110845 110846 110847 110848 110849 110850 110851 110852 110853 110854 110855 110856 110857 110858 110859 110860 110861 110862 110863 110864 110865 110866 110867 110868 110869 110870 110871 110872 110873 110874 110875 110876 110877 110878 110879 110880 110881 110882 110883 110884 110885 110886 110887 110888 110889 110890 110891 110892 110893 110894 110895 110896 110897 110898 110899 110900 110901 110902 110903 110904 110905 110906 110907 110908 110909 110910 110911 110912 110913 110914 110915 110916 110917 110918 110919 110920 110921 110922 110923 110924 110925 110926 110927 110928 110929 110930 110931 110932 110933 110934 110935 110936 110937 110938 110939 110940 110941 110942 110943 110944 110945 110946 110947 110948 110949 110950 110951 110952 110953 110954 110955 110956 110957 110958 110959 110960 110961 110962 110963 110964 110965 110966 110967 110968 110969 110970 110971 110972 110973 110974 110975 110976 110977 110978 110979 110980 110981 110982 110983 110984 110985 110986 110987 110988 110989 110990 110991 110992 110993 110994 110995 110996 110997 110998 110999 111000 111001 111002 111003 111004 111005 111006 111007 111008 111009 111010 111011 111012 111013 111014 111015 111016 111017 111018 111019 111020 111021 111022 111023 111024 111025 111026 111027 111028 111029 111030 111031 111032 111033 111034 111035 111036 111037 111038 111039 111040 111041 111042 111043 111044 111045 111046 111047 111048 111049 111050 111051 111052 111053 111054 111055 111056 111057 111058 111059 111060 111061 111062 111063 111064 111065 111066 111067 111068 111069 111070 111071 111072 111073 111074 111075 111076 111077 111078 111079 111080 111081 111082 111083 111084 111085 111086 111087 111088 111089 111090 111091 111092 111093 111094 111095 111096 111097 111098 111099 111100 111101 111102 111103 111104 111105 111106 111107 111108 111109 111110 111111 111112 111113 111114 111115 111116 111117 111118 111119 111120 111121 111122 111123 111124 111125 111126 111127 111128 111129 111130 111131 111132 111133 111134 111135 111136 111137 111138 111139 111140 111141 111142 111143 111144 111145 111146 111147 111148 111149 111150 111151 111152 111153 111154 111155 111156 111157 111158 111159 111160 111161 111162 111163 111164 111165 111166 111167 111168 111169 111170 111171 111172 111173 111174 111175 111176 111177 111178 111179 111180 111181 111182 111183 111184 111185 111186 111187 111188 111189 111190 111191 111192 111193 111194 111195 111196 111197 111198 111199 111200 111201 111202 111203 111204 111205 111206 111207 111208 111209 111210 111211 111212 111213 111214 111215 111216 111217 111218 111219 111220 111221 111222 111223 111224 111225 111226 111227 111228 111229 111230 111231 111232 111233 111234 111235 111236 111237 111238 111239 111240 111241 111242 111243 111244 111245 111246 111247 111248 111249 111250 111251 111252 111253 111254 111255 111256 111257 111258 111259 111260 111261 111262 111263 111264 111265 111266 111267 111268 111269 111270 111271 111272 111273 111274 111275 111276 111277 111278 111279 111280 111281 111282 111283 111284 111285 111286 111287 111288 111289 111290 111291 111292 111293 111294 111295 111296 111297 111298 111299 111300 111301 111302 111303 111304 111305 111306 111307 111308 111309 111310 111311 111312 111313 111314 111315 111316 111317 111318 111319 111320 111321 111322 111323 111324 111325 111326 111327 111328 111329 111330 111331 111332 111333 111334 111335 111336 111337 111338 111339 111340 111341 111342 111343 111344 111345 111346 111347 111348 111349 111350 111351 111352 111353 111354 111355 111356 111357 111358 111359 111360 111361 111362 111363 111364 111365 111366 111367 111368 111369 111370 111371 111372 111373 111374 111375 111376 111377 111378 111379 111380 111381 111382 111383 111384 111385 111386 111387 111388 111389 111390 111391 111392 111393 111394 111395 111396 111397 111398 111399 111400 111401 111402 111403 111404 111405 111406 111407 111408 111409 111410 111411 111412 111413 111414 111415 111416 111417 111418 111419 111420 111421 111422 111423 111424 111425 111426 111427 111428 111429 111430 111431 111432 111433 111434 111435 111436 111437 111438 111439 111440 111441 111442 111443 111444 111445 111446 111447 111448 111449 111450 111451 111452 111453 111454 111455 111456 111457 111458 111459 111460 111461 111462 111463 111464 111465 111466 111467 111468 111469 111470 111471 111472 111473 111474 111475 111476 111477 111478 111479 111480 111481 111482 111483 111484 111485 111486 111487 111488 111489 111490 111491 111492 111493 111494 111495 111496 111497 111498 111499 111500 111501 111502 111503 111504 111505 111506 111507 111508 111509 111510 111511 111512 111513 111514 111515 111516 111517 111518 111519 111520 111521 111522 111523 111524 111525 111526 111527 111528 111529 111530 111531 111532 111533 111534 111535 111536 111537 111538 111539 111540 111541 111542 111543 111544 111545 111546 111547 111548 111549 111550 111551 111552 111553 111554 111555 111556 111557 111558 111559 111560 111561 111562 111563 111564 111565 111566 111567 111568 111569 111570 111571 111572 111573 111574 111575 111576 111577 111578 111579 111580 111581 111582 111583 111584 111585 111586 111587 111588 111589 111590 111591 111592 111593 111594 111595 111596 111597 111598 111599 111600 111601 111602 111603 111604 111605 111606 111607 111608 111609 111610 111611 111612 111613 111614 111615 111616 111617 111618 111619 111620 111621 111622 111623 111624 111625 111626 111627 111628 111629 111630 111631 111632 111633 111634 111635 111636 111637 111638 111639 111640 111641 111642 111643 111644 111645 111646 111647 111648 111649 111650 111651 111652 111653 111654 111655 111656 111657 111658 111659 111660 111661 111662 111663 111664 111665 111666 111667 111668 111669 111670 111671 111672 111673 111674 111675 111676 111677 111678 111679 111680 111681 111682 111683 111684 111685 111686 111687 111688 111689 111690 111691 111692 111693 111694 111695 111696 111697 111698 111699 111700 111701 111702 111703 111704 111705 111706 111707 111708 111709 111710 111711 111712 111713 111714 111715 111716 111717 111718 111719 111720 111721 111722 111723 111724 111725 111726 111727 111728 111729 111730 111731 111732 111733 111734 111735 111736 111737 111738 111739 111740 111741 111742 111743 111744 111745 111746 111747 111748 111749 111750 111751 111752 111753 111754 111755 111756 111757 111758 111759 111760 111761 111762 111763 111764 111765 111766 111767 111768 111769 111770 111771 111772 111773 111774 111775 111776 111777 111778 111779 111780 111781 111782 111783 111784 111785 111786 111787 111788 111789 111790 111791 111792 111793 111794 111795 111796 111797 111798 111799 111800 111801 111802 111803 111804 111805 111806 111807 111808 111809 111810 111811 111812 111813 111814 111815 111816 111817 111818 111819 111820 111821 111822 111823 111824 111825 111826 111827 111828 111829 111830 111831 111832 111833 111834 111835 111836 111837 111838 111839 111840 111841 111842 111843 111844 111845 111846 111847 111848 111849 111850 111851 111852 111853 111854 111855 111856 111857 111858 111859 111860 111861 111862 111863 111864 111865 111866 111867 111868 111869 111870 111871 111872 111873 111874 111875 111876 111877 111878 111879 111880 111881 111882 111883 111884 111885 111886 111887 111888 111889 111890 111891 111892 111893 111894 111895 111896 111897 111898 111899 111900 111901 111902 111903 111904 111905 111906 111907 111908 111909 111910 111911 111912 111913 111914 111915 111916 111917 111918 111919 111920 111921 111922 111923 111924 111925 111926 111927 111928 111929 111930 111931 111932 111933 111934 111935 111936 111937 111938 111939 111940 111941 111942 111943 111944 111945 111946 111947 111948 111949 111950 111951 111952 111953 111954 111955 111956 111957 111958 111959 111960 111961 111962 111963 111964 111965 111966 111967 111968 111969 111970 111971 111972 111973 111974 111975 111976 111977 111978 111979 111980 111981 111982 111983 111984 111985 111986 111987 111988 111989 111990 111991 111992 111993 111994 111995 111996 111997 111998 111999 112000 112001 112002 112003 | ; Documentation for the ACL2 Theorem Prover
; WARNING: GENERATED FILE, DO NOT HAND EDIT!
; The contents of this file are derived from ACL2 Community Book
; books/system/doc/acl2-doc.lisp.
; ACL2 Version 7.2 -- A Computational Logic for Applicative Common Lisp
; Copyright (C) 2016, Regents of the University of Texas
; This version of ACL2 is a descendent of ACL2 Version 1.9, Copyright
; (C) 1997 Computational Logic, Inc. See the documentation topic NOTE-2-0.
; This program is free software; you can redistribute it and/or modify
; it under the terms of the LICENSE file distributed with ACL2.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; LICENSE for more details.
; Here are the original authors of books/system/doc/acl2-doc.lisp.
; Additional contributions may have been made to that file by members
; of the ACL2 community.
; Written by: Matt Kaufmann and J Strother Moore
; email: Kaufmann@cs.utexas.edu and Moore@cs.utexas.edu
; Department of Computer Science
; University of Texas at Austin
; Austin, TX 78701 U.S.A.
; WARNING: This file is generated from ACL2 Community Book
; books/system/doc/acl2-doc.lisp. To edit ACL2 documentation modify
; that file, not this one! Instructions are just above the in-package
; form in that book.
(in-package "ACL2")
(defconst *acl2-system-documentation* '
((&ALLOW-OTHER-KEYS (POINTERS)
"See [macro-args].")
(&BODY (POINTERS) "See [macro-args].")
(&KEY (POINTERS) "See [macro-args].")
(&OPTIONAL (POINTERS)
"See [macro-args].")
(&REST (POINTERS) "See [macro-args].")
(&WHOLE (POINTERS) "See [macro-args].")
(*
(NUMBERS ACL2-BUILT-INS)
"Multiplication macro
* is really a macro that expands to calls of the function [binary-*].
So for example
(* x y 4 z)
represents the same term as
(binary-* x (binary-* y (binary-* 4 z))).
See [binary-*].
* is a Common Lisp function. See any Common Lisp documentation for
more information.
Subtopics
[Binary-*]
Multiplication function")
(*ACL2-EXPORTS*
(PACKAGES ACL2-BUILT-INS)
"Symbols that are often imported into new [packages] to provide easy
access to ACL2 functionality.
When you define a new package for your own work with [defpkg], you
will usually want to import many symbols from the \"ACL2\" package;
for instance you will usually want to be able to use symbols like
[defthm], [in-theory], [xargs], [state], etc., without an acl2::
prefix.
The constant *acl2-exports* lists 1368 symbols, including most
documented ACL2 system constants, functions, and macros. You will
typically also want to import many symbols from Common Lisp; see
[*common-lisp-symbols-from-main-lisp-package*].
(& &allow-other-keys &aux &body &key
&optional &rest &whole * *acl2-exports*
*common-lisp-specials-and-constants*
*common-lisp-symbols-from-main-lisp-package*
*main-lisp-package-name*
*standard-chars* *standard-ci*
*standard-co* *standard-oi*
+ - / /= 1+ 1- 32-bit-integer-listp
32-bit-integer-listp-forward-to-integer-listp
32-bit-integer-stack
32-bit-integer-stack-length
32-bit-integer-stack-length1
32-bit-integerp
32-bit-integerp-forward-to-integerp
< <-on-others <= = > >= ?-fn @ a! abort!
abs access accumulated-persistence
accumulated-persistence-oops
acl2-count acl2-input-channel-package
acl2-number-listp acl2-numberp
acl2-oracle acl2-output-channel-package
acl2-package acons active-runep
add-binop add-custom-keyword-hint
add-default-hints
add-default-hints! add-include-book-dir
add-include-book-dir!
add-invisible-fns add-ld-keyword-alias
add-ld-keyword-alias!
add-macro-alias add-macro-fn
add-match-free-override add-nth-alias
add-override-hints add-override-hints!
add-pair add-pair-preserves-all-boundp
add-raw-arity
add-timers add-to-set add-to-set-eq
add-to-set-eql add-to-set-equal
alistp alistp-forward-to-true-listp
all-boundp all-boundp-preserves-assoc
all-vars all-vars1 all-vars1-lst
allocate-fixnum-range alpha-char-p
alpha-char-p-forward-to-characterp
alphorder and and-macro
append aref-32-bit-integer-stack
aref-t-stack aref1 aref2 args
arities-okp arity array1p array1p-cons
array1p-forward array1p-linear
array2p array2p-cons array2p-forward
array2p-linear aset-32-bit-integer-stack
aset-t-stack aset1 aset2 ash assert$
assert* assert-event assign assoc
assoc-add-pair assoc-eq assoc-eq-equal
assoc-eq-equal-alistp assoc-equal
assoc-keyword assoc-string-equal assoc2
associativity-of-* associativity-of-+
assume atom atom-listp
atom-listp-forward-to-true-listp
backchain-limit
big-clock-entry big-clock-negative-p
binary-* binary-+ binary-append
bind-free bit boole$ boolean-listp
boolean-listp-cons boolean-listp-forward
boolean-listp-forward-to-symbol-listp
booleanp booleanp-characterp
booleanp-compound-recognizer
bounded-integer-alistp
bounded-integer-alistp-forward-to-eqlable-alistp
bounded-integer-alistp2 boundp-global
boundp-global1 break$ break-on-error
brr brr@ build-state1 butlast
caaaar caaadr caaar caadar caaddr
caadr caar cadaar cadadr cadar caddar
cadddr caddr cadr canonical-pathname
car car-cdr-elim car-cons case
case-list case-list-check case-match
case-split case-split-limitations
case-test cbd cdaaar cdaadr
cdaar cdadar cdaddr cdadr cdar cddaar
cddadr cddar cdddar cddddr cdddr cddr
cdr cdr-cons cdrn ceiling certify-book
certify-book! change char char-code
char-code-code-char-is-identity
char-code-linear char-downcase
char-equal char-upcase char< char<=
char> char>= character character-alistp
character-listp character-listp-append
character-listp-coerce
character-listp-forward-to-eqlable-listp
character-listp-remove-duplicates-eql
character-listp-revappend
character-listp-string-downcase-1
character-listp-string-upcase1-1
characterp characterp-char-downcase
characterp-char-upcase
characterp-nth characterp-page
characterp-rubout characterp-tab
check-invariant-risk check-vars-not-free
checkpoint-forced-goals
clause clear-memoize-statistics
clear-memoize-table clear-memoize-tables
close-input-channel close-output-channel
close-trace-file closure code-char
code-char-char-code-is-identity
code-char-type coerce coerce-inverse-1
coerce-inverse-2 coerce-object-to-state
coerce-state-to-object
community-books commutativity-of-*
commutativity-of-+ comp completion-of-*
completion-of-+ completion-of-<
completion-of-car completion-of-cdr
completion-of-char-code
completion-of-code-char
completion-of-coerce
completion-of-complex
completion-of-denominator
completion-of-imagpart
completion-of-intern-in-package-of-symbol
completion-of-numerator
completion-of-realpart
completion-of-symbol-name
completion-of-symbol-package-name
completion-of-unary-/
completion-of-unary-minus
complex complex-0
complex-definition complex-equal
complex-implies1 complex-rationalp
complex/complex-rationalp
compress1 compress11
compress2 compress21 compress211
concatenate cond cond-clausesp
cond-macro conjugate cons cons-equal
cons-subtrees consp consp-assoc-equal
corollary cpu-core-count ctx
current-package current-theory cw cw!
cw-gstack declare decrement-big-clock
defabbrev defabsstobj
defabsstobj-missing-events defattach
default default-*-1 default-*-2
default-+-1 default-+-2 default-<-1
default-<-2 default-backchain-limit
default-car default-cdr
default-char-code default-coerce-1
default-coerce-2 default-coerce-3
default-compile-fns default-complex-1
default-complex-2 default-defun-mode
default-defun-mode-from-state
default-denominator
default-hints default-imagpart
default-measure-function
default-numerator default-print-prompt
default-realpart default-ruler-extenders
default-symbol-name
default-symbol-package-name
default-total-parallelism-work-limit
default-unary-/ default-unary-minus
default-verify-guards-eagerness
default-well-founded-relation
defaxiom defchoose defcong
defconst defequiv defevaluator defexec
define-pc-atomic-macro define-pc-help
define-pc-macro define-pc-meta
define-trusted-clause-processor
deflabel deflock
defmacro defmacro-last defn defnd defpkg
defproxy defrec defrefinement defstobj
defstub deftheory deftheory-static
defthm defthm-std defthmd defttag
defun defun-inline defun-notinline
defun-nx defun-sk defun-std
defund defund-inline defund-notinline
defund-nx defuns defuns-std delete-assoc
delete-assoc-eq delete-assoc-equal
delete-include-book-dir
delete-include-book-dir!
denominator digit-char-p digit-to-char
dimensions disable disable-forcing
disable-immediate-force-modep disabledp
disassemble$ distributivity dmr-start
dmr-stop doc doc! docs double-rewrite
duplicates e/d e0-ord-< e0-ordinalp
ec-call eighth eliminate-destructors
eliminate-irrelevance
enable enable-forcing
enable-immediate-force-modep
encapsulate endp eq eql eqlable-alistp
eqlable-alistp-forward-to-alistp
eqlable-listp
eqlable-listp-forward-to-atom-listp
eqlablep eqlablep-recog
equal equal-char-code er er-progn
er-progn-fn er-progn-fn@par er-progn@par
evenp evens event evisc-tuple
executable-counterpart-theory
exists exit explode-atom
explode-nonnegative-integer expt
expt-type-prescription-non-zero-base
extend-32-bit-integer-stack
extend-pe-table extend-t-stack
extend-world extra-info f-get-global
f-put-global fast-alist-clean
fast-alist-clean! fast-alist-fork
fast-alist-fork! fast-alist-free
fast-alist-free-on-exit fast-alist-len
fast-alist-summary fc-report fertilize
fgetprop fifth file-clock file-clock-p
file-clock-p-forward-to-integerp
finalize-event-user first first-n-ac fix
fix-true-list flet floor flush-compress
flush-hons-get-hash-table-link
fms fms! fms!-to-string
fms-to-string fmt fmt! fmt!-to-string
fmt-to-comment-window fmt-to-string fmt1
fmt1! fmt1!-to-string fmt1-to-string
fncall-term forall force formula
fourth function-symbolp function-theory
gag-mode gc$ gc-strategy gc-verbose
gcs generalize get-check-invariant-risk
get-command-sequence get-event-data
get-global get-output-stream-string$
get-slow-alist-action get-timer
get-wormhole-status getenv$ getprop
getprop-default getpropc getprops
getprops1 global-table global-table-cars
global-table-cars1 global-val
good-atom-listp good-bye granularity
ground-zero gthm guard guard-obligation
guard-theorem hard-error
has-propsp has-propsp1 header help
hide hist hons hons-acons hons-acons!
hons-assoc-equal hons-clear hons-clear!
hons-copy hons-copy-persistent
hons-equal hons-equal-lite
hons-get hons-resize hons-resize-fn
hons-shrink-alist hons-shrink-alist!
hons-summary hons-wash
hons-wash! i-am-here i-close i-large
i-limited i-small id idates identity
if if* iff iff-implies-equal-implies-1
iff-implies-equal-implies-2
iff-implies-equal-not
iff-is-an-equivalence
ifix ignore illegal imagpart
imagpart-complex immediate-force-modep
implies improper-consp
in-arithmetic-theory in-package
in-tau-intervalp in-theory include-book
incompatible increment-timer
induct initialize-event-user
int= integer integer-0 integer-1
integer-abs integer-implies-rational
integer-length integer-listp
integer-listp-forward-to-rational-listp
integer-range-p
integer-step integerp intern
intern$ intern-in-package-of-symbol
intern-in-package-of-symbol-symbol-name
intersection$ intersection-eq
intersection-equal intersection-theories
intersectp intersectp-eq
intersectp-equal inverse-of-*
inverse-of-+ invisible-fns-table
keyword-package keyword-value-listp
keyword-value-listp-assoc-keyword
keyword-value-listp-forward-to-true-listp
keywordp keywordp-forward-to-symbolp
known-package-alist known-package-alistp
known-package-alistp-forward-to-true-list-listp-and-alistp
kwote
kwote-lst lambda last last-prover-steps
ld ld-error-action ld-error-triples
ld-evisc-tuple ld-keyword-aliases
ld-missing-input-ok ld-post-eval-print
ld-pre-eval-filter ld-pre-eval-print
ld-prompt ld-query-control-alist
ld-redefinition-action ld-skip-proofsp
ld-verbose legal-case-clausesp len
len-update-nth length let* lexorder list
list* list*-macro list-all-package-names
list-all-package-names-lst
list-macro listp local logand
logandc1 logandc2 logbitp logcount
logeqv logic logior lognand lognor
lognot logorc1 logorc2 logtest logxor
lower-case-p lower-case-p-char-downcase
lower-case-p-forward-to-alpha-char-p
lowest-terms lp macro-aliases macro-args
main-timer main-timer-type-prescription
make make-character-list
make-character-list-make-character-list
make-event
make-fast-alist make-fmt-bindings
make-input-channel make-list
make-list-ac make-mv-nths make-ord
make-output-channel make-tau-interval
make-var-lst make-var-lst1
make-wormhole-status makunbound-global
max maximum-length may-need-slashes
mbe mbt mbt* member member-eq
member-equal member-symbol-name
memoize memoize-summary
memsum meta-extract-contextual-fact
meta-extract-formula
meta-extract-global-fact
meta-extract-global-fact+
meta-extract-rw+-term
mfc min minimal-theory minusp
mod mod-expt monitor monitored-runes
more more! more-doc msg must-be-equal
mutual-recursion mutual-recursion-guardp
mv mv-let mv-list mv-nth
mv? mv?-let nat-listp natp needs-slashes
never-memoize newline nfix nil
nil-is-not-circular ninth no-duplicatesp
no-duplicatesp-eq no-duplicatesp-equal
non-exec nonnegative-integer-quotient
nonnegative-product nonzero-imagpart
not nqthm-to-acl2 nth nth-0-cons
nth-0-read-run-time-type-prescription
nth-add1 nth-aliases nth-update-nth
nthcdr null number-subtrees numerator
o-finp o-first-coeff o-first-expt o-infp
o-p o-rst o< o<= o> o>= observation
observation-cw oddp odds ok-if
oops open-channel-listp open-channel1
open-channel1-forward-to-true-listp-and-consp
open-channels-p open-channels-p-forward
open-input-channel
open-input-channel-any-p
open-input-channel-any-p1
open-input-channel-p
open-input-channel-p1
open-input-channels
open-output-channel open-output-channel!
open-output-channel-any-p
open-output-channel-any-p1
open-output-channel-p
open-output-channel-p1
open-output-channels open-trace-file or
or-macro oracle-apply oracle-apply-raw
oracle-funcall ordered-symbol-alistp
ordered-symbol-alistp-add-pair
ordered-symbol-alistp-add-pair-forward
ordered-symbol-alistp-delete-assoc-eq
ordered-symbol-alistp-forward-to-symbol-alistp
ordered-symbol-alistp-getprops
otherwise our-digit-char-p
override-hints p! pairlis$
pairlis2 pand pargs pbt pc pcb pcb!
pcs pe pe! peek-char$ pf pkg-imports
pkg-witness pl pl2 plet plist-worldp
plist-worldp-forward-to-assoc-eq-equal-alistp
plusp pointers pop-timer por position
position-ac position-eq position-eq-ac
position-equal position-equal-ac
positive posp power-eval pprogn pr
pr! preprocess prin1$ prin1-with-slashes
prin1-with-slashes1 princ$ print-base-p
print-gv print-object$ print-object$-ser
print-rational-as-decimal
print-timer profile
prog2$ progn progn! progn$ program
proof-tree proofs-co proper-consp
props prove pseudo-term-listp
pseudo-term-listp-forward-to-true-listp
pseudo-termp
pso pso! psof psog pspv pstack
puff puff* push-timer push-untouchable
put-assoc put-assoc-eq put-assoc-eql
put-assoc-equal put-global putprop
quick-and-dirty-subsumption-replacement-step
quit quote
quotep r-eqlable-alistp r-symbol-alistp
random$ rassoc rassoc-eq rassoc-equal
ratio rational rational-implies1
rational-implies2 rational-listp
rational-listp-forward-to-true-listp
rationalp rationalp-* rationalp-+
rationalp-expt-type-prescription
rationalp-implies-acl2-numberp
rationalp-unary--
rationalp-unary-/ read-acl2-oracle
read-acl2-oracle-preserves-state-p1
read-byte$ read-char$
read-file-into-string read-file-listp
read-file-listp-forward-to-true-list-listp
read-file-listp1
read-file-listp1-forward-to-true-listp-and-consp
read-files read-files-p
read-files-p-forward-to-read-file-listp
read-idate read-object read-run-time
read-run-time-preserves-state-p1
readable-file
readable-file-forward-to-true-listp-and-consp
readable-files readable-files-listp
readable-files-listp-forward-to-true-list-listp-and-alistp
readable-files-p
readable-files-p-forward-to-readable-files-listp
real-listp real/rationalp
realfix realpart realpart-complex
realpart-imagpart-elim rebuild
redef redef! redef+ redef- redo-flat
regenerate-tau-database rem remove
remove-binop remove-custom-keyword-hint
remove-default-hints
remove-default-hints!
remove-duplicates remove-duplicates-eq
remove-duplicates-eql
remove-duplicates-equal remove-eq
remove-equal remove-invisible-fns
remove-macro-alias remove-macro-fn
remove-nth-alias remove-override-hints
remove-override-hints!
remove-raw-arity remove-untouchable
remove1 remove1-eq remove1-equal
reset-fc-reporting reset-kill-ring
reset-ld-specials reset-prehistory
reset-print-control resize-list
rest restore-memoization-settings
retract-world
retrieve return-last return-last-table
revappend reverse rewrite-stack-limit
rfix round rw-cache satisfies
save-and-clear-memoization-settings
save-exec search second serialize-read
serialize-write set-absstobj-debug
set-accumulated-persistence
set-backchain-limit
set-body set-bogus-defun-hints-ok
set-bogus-mutual-recursion-ok
set-case-split-limitations
set-cbd set-check-invariant-risk
set-checkpoint-summary-limit
set-compile-fns
set-compiler-enabled set-debugger-enable
set-default-backchain-limit
set-default-hints set-default-hints!
set-deferred-ttag-notes set-difference$
set-difference-eq set-difference-equal
set-difference-theories
set-duplicate-keys-action
set-duplicate-keys-action!
set-enforce-redundancy
set-equalp-equal set-evisc-tuple
set-fc-criteria set-fc-report-on-the-fly
set-fmt-hard-right-margin
set-fmt-soft-right-margin
set-gag-mode set-gc-strategy
set-guard-checking set-guard-msg
set-ignore-ok set-inhibit-output-lst
set-inhibit-warnings
set-inhibit-warnings!
set-inhibited-summary-types
set-invisible-fns-table
set-iprint set-irrelevant-formals-ok
set-ld-keyword-aliases
set-ld-keyword-aliases!
set-ld-redefinition-action
set-ld-skip-proofs
set-ld-skip-proofsp set-let*-abstraction
set-let*-abstractionp
set-match-free-default
set-match-free-error
set-measure-function
set-non-linear set-non-linearp
set-override-hints set-override-hints!
set-parallel-execution
set-print-base set-print-base-radix
set-print-case set-print-circle
set-print-clause-ids set-print-escape
set-print-gv-defaults set-print-length
set-print-level set-print-lines
set-print-radix set-print-readably
set-print-right-margin
set-prover-step-limit set-raw-mode
set-raw-mode-on! set-raw-proof-format
set-raw-warning-format
set-rewrite-stack-limit
set-ruler-extenders
set-rw-cache-state set-rw-cache-state!
set-saved-output set-serialize-character
set-skip-meta-termp-checks
set-skip-meta-termp-checks!
set-slow-alist-action
set-splitter-output
set-state-ok set-tau-auto-mode set-timer
set-total-parallelism-work-limit
set-total-parallelism-work-limit-error
set-trace-evisc-tuple
set-verify-guards-eagerness
set-w set-waterfall-parallelism
set-waterfall-parallelism-hacks-enabled
set-waterfall-parallelism-hacks-enabled!
set-waterfall-printing
set-well-founded-relation
set-wormhole-data
set-wormhole-entry-code
set-write-acl2x setenv$ seventh
sgetprop show-accumulated-persistence
show-bdd show-bodies
show-custom-keyword-hint-expansion
show-fc-criteria
shrink-32-bit-integer-stack
shrink-t-stack signed-byte
signed-byte-p signum simplify
sixth skip-proofs sleep some-slashable
spec-mv-let splitter-output
stable-under-simplificationp
standard-char standard-char-listp
standard-char-listp-append
standard-char-listp-forward-to-character-listp
standard-char-p standard-char-p-nth
standard-co standard-oi
standard-part standard-string-alistp
standard-string-alistp-forward-to-alistp
standardp
start-proof-tree state state-global-let*
state-global-let*-cleanup
state-global-let*-get-globals
state-global-let*-put-globals state-p
state-p-implies-and-forward-to-state-p1
state-p1 state-p1-forward
state-p1-update-main-timer
state-p1-update-nth-2-world
step-limit stobj-let stop-proof-tree
string string-append string-append-lst
string-downcase string-downcase1
string-equal string-equal1
string-is-not-circular string-listp
string-upcase string-upcase1
string< string<-irreflexive
string<-l string<-l-asymmetric
string<-l-irreflexive
string<-l-transitive
string<-l-trichotomy
string<= string> string>= stringp
stringp-symbol-package-name strip-cars
strip-cdrs sublis subseq subseq-list
subsetp subsetp-eq subsetp-equal
subst substitute substitute-ac summary
symbol symbol-< symbol-<-asymmetric
symbol-<-irreflexive symbol-<-transitive
symbol-<-trichotomy symbol-alistp
symbol-alistp-forward-to-eqlable-alistp
symbol-doublet-listp
symbol-equality symbol-listp
symbol-listp-forward-to-true-listp
symbol-name
symbol-name-intern-in-package-of-symbol
symbol-package-name symbolp
symbolp-intern-in-package-of-symbol
synp syntaxp sys-call sys-call+
sys-call-status t t-stack t-stack-length
t-stack-length1 table table-alist take
tau-data tau-database tau-interval-dom
tau-interval-hi tau-interval-hi-rel
tau-interval-lo tau-interval-lo-rel
tau-intervalp tau-status tau-system
tenth term-list-listp term-listp
term-order termination-theorem
termp the the-check the-fixnum
the-fixnum! theory theory-invariant
third thm time$ time-tracker
time-tracker-tau timer-alistp
timer-alistp-forward-to-true-list-listp-and-symbol-alistp
toggle-pc-macro
top-level trace! trace$ trace* trans
trans! trans1 trichotomy true-list-listp
true-list-listp-forward-to-true-listp
true-list-listp-forward-to-true-listp-assoc-equal
true-listp
true-listp-cadr-assoc-eq-for-open-channels-p
true-listp-update-nth truncate
ttag ttags-seen tthm type typed-io-listp
typed-io-listp-forward-to-true-listp
typespec-check u ubt ubt! ubt-prehistory
ubt? ubu ubu! ubu? unary--
unary-/ unary-function-symbol-listp
unicity-of-0 unicity-of-1 union$
union-eq union-equal union-theories
universal-theory unmemoize
unmonitor unquote unsave unsigned-byte
unsigned-byte-p untrace$ untrans-table
untranslate update-32-bit-integer-stack
update-acl2-oracle
update-acl2-oracle-preserves-state-p1
update-big-clock-entry update-file-clock
update-global-table update-idates
update-list-all-package-names-lst
update-nth update-nth-array
update-open-input-channels
update-open-output-channels
update-read-files
update-t-stack update-user-stobj-alist
update-user-stobj-alist1
update-written-files
upper-case-p upper-case-p-char-upcase
upper-case-p-forward-to-alpha-char-p
user-stobj-alist
user-stobj-alist1 value value-triple
verbose-pstack verify verify-guards
verify-guards+ verify-guards-formula
verify-termination w walkabout warning!
waterfall-parallelism waterfall-printing
wet with-fast-alist with-guard-checking
with-guard-checking-error-triple
with-live-state with-local-state
with-local-stobj with-output
with-output-lock with-prover-step-limit
with-prover-step-limit!
with-prover-time-limit
with-serialize-character
with-stolen-alist without-evisc
wof world wormhole wormhole-data
wormhole-entry-code wormhole-eval
wormhole-p wormhole-statusp
wormhole1 writable-file-listp
writable-file-listp-forward-to-true-list-listp
writable-file-listp1
writable-file-listp1-forward-to-true-listp-and-consp
write-byte$
writeable-files writeable-files-p
writeable-files-p-forward-to-writable-file-listp
written-file
written-file-forward-to-true-listp-and-consp
written-file-listp
written-file-listp-forward-to-true-list-listp-and-alistp
written-files written-files-p
written-files-p-forward-to-written-file-listp
xargs xor xxxjoin zero zerop zip zp zpf)")
(*COMMON-LISP-SYMBOLS-FROM-MAIN-LISP-PACKAGE*
(PACKAGES ACL2-BUILT-INS)
"Symbols that are often imported into new packages to provide easy
access to Common Lisp functionality.
When you define a new package for your own work with [defpkg], you
will usually want to import many symbols from the \"COMMON-LISP\"
package so that you can access them without a common-lisp:: or
acl2:: prefix.
The constant *common-lisp-symbols-from-main-lisp-package* lists the
978 symbols of the COMMON-LISP package found in {dpAns |
http://dx.doi.org/10.1145/147135.147249}. You will typically also
want to import many symbols from ACL2; see [*ACL2-exports*].
(&allow-other-keys *print-miser-width*
&aux *print-pprint-dispatch*
&body *print-pretty*
&environment *print-radix*
&key *print-readably* &optional
*print-right-margin* &rest *query-io*
&whole *random-state* * *read-base*
** *read-default-float-format*
*** *read-eval* *break-on-signals*
*read-suppress* *compile-file-pathname*
*readtable* *compile-file-truename*
*standard-input* *compile-print*
*standard-output* *compile-verbose*
*terminal-io* *debug-io*
*trace-output* *debugger-hook*
+ *default-pathname-defaults*
++ *error-output* +++ *features*
- *gensym-counter* / *load-pathname*
// *load-print* /// *load-truename*
/= *load-verbose* 1+ *macroexpand-hook*
1- *modules* < *package*
<= *print-array* = *print-base*
> *print-case* >= *print-circle*
abort *print-escape* abs *print-gensym*
acons *print-length* acos *print-level*
acosh *print-lines* add-method adjoin
atom boundp adjust-array base-char
break adjustable-array-p base-string
broadcast-stream allocate-instance
bignum broadcast-stream-streams
alpha-char-p bit built-in-class
alphanumericp bit-and butlast
and bit-andc1 byte append bit-andc2
byte-position apply bit-eqv byte-size
apropos bit-ior caaaar apropos-list
bit-nand caaadr aref bit-nor
caaar arithmetic-error bit-not caadar
arithmetic-error-operands bit-orc1
caaddr arithmetic-error-operation
bit-orc2 caadr array bit-vector
caar array-dimension bit-vector-p
cadaar array-dimension-limit
bit-xor cadadr array-dimensions
block cadar array-displacement
boole caddar array-element-type
boole-1 cadddr array-has-fill-pointer-p
boole-2 caddr array-in-bounds-p
boole-and cadr array-rank
boole-andc1 call-arguments-limit
array-rank-limit boole-andc2 call-method
array-row-major-index boole-c1
call-next-method array-total-size
boole-c2 car array-total-size-limit
boole-clr case arrayp
boole-eqv catch ash boole-ior ccase
asin boole-nand cdaaar asinh boole-nor
cdaadr assert boole-orc1 cdaar assoc
boole-orc2 cdadar assoc-if boole-set
cdaddr assoc-if-not boole-xor cdadr
atan boolean cdar atanh both-case-p
cddaar cddadr clear-input copy-tree
cddar clear-output cos cdddar close cosh
cddddr clrhash count cdddr code-char
count-if cddr coerce count-if-not
cdr compilation-speed ctypecase
ceiling compile debug cell-error
compile-file decf cell-error-name
compile-file-pathname declaim
cerror compiled-function declaration
change-class compiled-function-p
declare char compiler-macro decode-float
char-code compiler-macro-function
decode-universal-time
char-code-limit complement defclass
char-downcase complex defconstant
char-equal complexp defgeneric
char-greaterp compute-applicable-methods
define-compiler-macro
char-int compute-restarts
define-condition char-lessp
concatenate define-method-combination
char-name concatenated-stream
define-modify-macro char-not-equal
concatenated-stream-streams
define-setf-expander char-not-greaterp
cond define-symbol-macro char-not-lessp
condition defmacro char-upcase conjugate
defmethod char/= cons defpackage
char< consp defparameter char<=
constantly defsetf char= constantp
defstruct char> continue deftype
char>= control-error defun character
copy-alist defvar characterp copy-list
delete check-type copy-pprint-dispatch
delete-duplicates cis copy-readtable
delete-file class copy-seq delete-if
class-name copy-structure delete-if-not
class-of copy-symbol delete-package
denominator eq deposit-field
eql describe equal describe-object
equalp destructuring-bind
error digit-char etypecase
digit-char-p eval directory eval-when
directory-namestring evenp disassemble
every division-by-zero exp do export
do* expt do-all-symbols extended-char
do-external-symbols fboundp do-symbols
fceiling documentation fdefinition
dolist ffloor dotimes fifth double-float
file-author double-float-epsilon
file-error double-float-negative-epsilon
file-error-pathname dpb file-length
dribble file-namestring dynamic-extent
file-position ecase file-stream
echo-stream file-string-length
echo-stream-input-stream file-write-date
echo-stream-output-stream
fill ed fill-pointer
eighth find elt find-all-symbols
encode-universal-time find-class
end-of-file find-if endp find-if-not
enough-namestring find-method
ensure-directories-exist find-package
ensure-generic-function find-restart
find-symbol get-internal-run-time
finish-output get-macro-character
first get-output-stream-string fixnum
get-properties flet get-setf-expansion
float get-universal-time float-digits
getf float-precision gethash
float-radix go float-sign graphic-char-p
floating-point-inexact handler-bind
floating-point-invalid-operation
handler-case floating-point-overflow
hash-table floating-point-underflow
hash-table-count floatp hash-table-p
floor hash-table-rehash-size fmakunbound
hash-table-rehash-threshold force-output
hash-table-size format hash-table-test
formatter host-namestring
fourth identity fresh-line
if fround ignorable ftruncate ignore
ftype ignore-errors funcall imagpart
function import function-keywords
in-package function-lambda-expression
incf functionp initialize-instance
gcd inline generic-function
input-stream-p gensym inspect
gentemp integer get integer-decode-float
get-decoded-time integer-length
get-dispatch-macro-character
integerp get-internal-real-time
interactive-stream-p
intern lisp-implementation-type
internal-time-units-per-second
lisp-implementation-version
intersection list invalid-method-error
list* invoke-debugger
list-all-packages invoke-restart
list-length invoke-restart-interactively
listen isqrt listp keyword load keywordp
load-logical-pathname-translations
labels load-time-value
lambda locally lambda-list-keywords
log lambda-parameters-limit
logand last logandc1 lcm
logandc2 ldb logbitp ldb-test logcount
ldiff logeqv least-negative-double-float
logical-pathname
least-negative-long-float
logical-pathname-translations
least-negative-normalized-double-float
logior
least-negative-normalized-long-float
lognand
least-negative-normalized-short-float
lognor
least-negative-normalized-single-float
lognot least-negative-short-float
logorc1 least-negative-single-float
logorc2 least-positive-double-float
logtest least-positive-long-float logxor
least-positive-normalized-double-float
long-float
least-positive-normalized-long-float
long-float-epsilon
least-positive-normalized-short-float
long-float-negative-epsilon
least-positive-normalized-single-float
long-site-name
least-positive-short-float loop
least-positive-single-float loop-finish
length lower-case-p let machine-instance
let* machine-type machine-version
mask-field macro-function
max macroexpand member macroexpand-1
member-if macrolet member-if-not
make-array merge make-broadcast-stream
merge-pathnames make-concatenated-stream
method make-condition method-combination
make-dispatch-macro-character
method-combination-error
make-echo-stream method-qualifiers
make-hash-table min make-instance
minusp make-instances-obsolete
mismatch make-list mod make-load-form
most-negative-double-float
make-load-form-saving-slots
most-negative-fixnum
make-method most-negative-long-float
make-package most-negative-short-float
make-pathname most-negative-single-float
make-random-state
most-positive-double-float
make-sequence most-positive-fixnum
make-string most-positive-long-float
make-string-input-stream
most-positive-short-float
make-string-output-stream
most-positive-single-float
make-symbol muffle-warning
make-synonym-stream multiple-value-bind
make-two-way-stream multiple-value-call
makunbound multiple-value-list
map multiple-value-prog1
map-into multiple-value-setq mapc
multiple-values-limit mapcan name-char
mapcar namestring mapcon nbutlast
maphash nconc mapl next-method-p
maplist nil nintersection package-error
ninth package-error-package
no-applicable-method package-name
no-next-method package-nicknames
not package-shadowing-symbols
notany package-use-list notevery
package-used-by-list notinline packagep
nreconc pairlis nreverse parse-error
nset-difference parse-integer
nset-exclusive-or parse-namestring
nstring-capitalize pathname
nstring-downcase pathname-device
nstring-upcase pathname-directory
nsublis pathname-host nsubst
pathname-match-p nsubst-if pathname-name
nsubst-if-not pathname-type nsubstitute
pathname-version nsubstitute-if
pathnamep nsubstitute-if-not
peek-char nth phase nth-value pi nthcdr
plusp null pop number position numberp
position-if numerator position-if-not
nunion pprint oddp pprint-dispatch
open pprint-exit-if-list-exhausted
open-stream-p pprint-fill
optimize pprint-indent or pprint-linear
otherwise pprint-logical-block
output-stream-p pprint-newline
package pprint-pop pprint-tab read-char
pprint-tabular read-char-no-hang
prin1 read-delimited-list
prin1-to-string read-from-string
princ read-line princ-to-string
read-preserving-whitespace
print read-sequence print-not-readable
reader-error print-not-readable-object
readtable print-object
readtable-case print-unreadable-object
readtablep probe-file
real proclaim realp prog realpart
prog* reduce prog1 reinitialize-instance
prog2 rem progn remf program-error
remhash progv remove provide
remove-duplicates psetf remove-if
psetq remove-if-not push remove-method
pushnew remprop quote rename-file
random rename-package random-state
replace random-state-p require rassoc
rest rassoc-if restart rassoc-if-not
restart-bind ratio restart-case
rational restart-name rationalize return
rationalp return-from read revappend
read-byte reverse room simple-bit-vector
rotatef simple-bit-vector-p
round simple-condition row-major-aref
simple-condition-format-arguments
rplaca simple-condition-format-control
rplacd simple-error
safety simple-string satisfies
simple-string-p sbit simple-type-error
scale-float simple-vector schar
simple-vector-p search simple-warning
second sin sequence single-float
serious-condition single-float-epsilon
set single-float-negative-epsilon
set-difference
sinh set-dispatch-macro-character
sixth set-exclusive-or
sleep set-macro-character slot-boundp
set-pprint-dispatch slot-exists-p
set-syntax-from-char slot-makunbound
setf slot-missing setq slot-unbound
seventh slot-value shadow software-type
shadowing-import software-version
shared-initialize some shiftf sort
short-float space short-float-epsilon
special short-float-negative-epsilon
special-operator-p short-site-name
speed signal sqrt signed-byte
stable-sort signum standard simple-array
standard-char simple-base-string
standard-char-p standard-class
sublis standard-generic-function subseq
standard-method subsetp standard-object
subst step subst-if storage-condition
subst-if-not store-value substitute
stream substitute-if stream-element-type
substitute-if-not stream-error
subtypep stream-error-stream
svref stream-external-format
sxhash streamp symbol
string symbol-function string-capitalize
symbol-macrolet string-downcase
symbol-name string-equal symbol-package
string-greaterp symbol-plist
string-left-trim symbol-value
string-lessp symbolp string-not-equal
synonym-stream string-not-greaterp
synonym-stream-symbol string-not-lessp t
string-right-trim tagbody string-stream
tailp string-trim tan string-upcase
tanh string/= tenth string< terpri
string<= the string= third string>
throw string>= time stringp trace
structure translate-logical-pathname
structure-class
translate-pathname structure-object
tree-equal style-warning truename
truncate values-list two-way-stream
variable two-way-stream-input-stream
vector two-way-stream-output-stream
vector-pop type vector-push type-error
vector-push-extend type-error-datum
vectorp type-error-expected-type
warn type-of warning typecase
when typep wild-pathname-p unbound-slot
with-accessors unbound-slot-instance
with-compilation-unit
unbound-variable with-condition-restarts
undefined-function
with-hash-table-iterator
unexport with-input-from-string unintern
with-open-file union with-open-stream
unless with-output-to-string unread-char
with-package-iterator unsigned-byte
with-simple-restart untrace with-slots
unuse-package with-standard-io-syntax
unwind-protect write
update-instance-for-different-class
write-byte
update-instance-for-redefined-class
write-char upgraded-array-element-type
write-line upgraded-complex-part-type
write-sequence upper-case-p
write-string use-package write-to-string
use-value y-or-n-p user-homedir-pathname
yes-or-no-p values zerop)")
(*STANDARD-CI*
(IO ACL2-BUILT-INS)
"An ACL2 character-based analogue of CLTL's *standard-input*
The value of the ACL2 constant *standard-ci* is an open character
input channel that is synonymous to Common Lisp's *standard-input*.
ACL2 character input from *standard-ci* is actually obtained by
reading [characters] from the stream named by Common Lisp's
*standard-input*. That is, by changing the setting of
*standard-input* in raw Common Lisp you can change the source from
which ACL2 reads on the channel *standard-ci*. See [*standard-co*].")
(*STANDARD-CO*
(IO ACL2-BUILT-INS)
"The ACL2 analogue of CLTL's *standard-output*
The value of the ACL2 constant *standard-co* is an open character
output channel that is synonymous to Common Lisp's
*standard-output*.
ACL2 character output to *standard-co* will go to the stream named by
Common Lisp's *standard-output*. That is, by changing the setting
of *standard-output* in raw Common Lisp you can change the actual
destination of ACL2 output on the channel named by *standard-co*.
Observe that this happens without changing the logical value of
*standard-co* (which is some channel symbol). Changing the setting
of *standard-output* in raw Common Lisp essentially just changes
the map that relates ACL2 to the physical world of terminals,
files, etc.
To see the value of this observation, consider the following. Suppose
you write an ACL2 function which does character output to the
constant channel *standard-co*. During testing you see that the
output actually goes to your terminal. Can you use the function to
output to a file? Yes, if you are willing to do a little work in
raw Common Lisp: open a stream to the file in question, set
*standard-output* to that stream, call your ACL2 function, and then
close the stream and restore *standard-output* to its nominal
value. Similar observations can be made about the two ACL2 input
channels, [*standard-oi*] and [*standard-ci*], which are analogues
of *standard-input*.
Another reason you might have for wanting to change the actual
streams associated with [*standard-oi*] and *standard-co* is to
drive the ACL2 top-level loop, [ld], on alternative input and
output streams. This end can be accomplished easily within ACL2 by
either calling [ld] on the desired channels or file names or by
resetting the ACL2 [state] global variables '[standard-oi] and
'[standard-co] which are used by [ld]. See [standard-oi] and see
[standard-co].")
(*STANDARD-OI*
(IO ACL2-BUILT-INS)
"An ACL2 object-based analogue of CLTL's *standard-input*
The value of the ACL2 constant *standard-oi* is an open object input
channel that is synonymous to Common Lisp's *standard-input*.
ACL2 object input from *standard-oi* is actually obtained by reading
from the stream named by Common Lisp's *standard-input*. That is,
by changing the setting of *standard-input* in raw Common Lisp you
can change the source from which ACL2 reads on the channel
*standard-oi*. See [*standard-co*].")
(+
(NUMBERS ACL2-BUILT-INS)
"Addition macro
+ is really a macro that expands to calls of the function [binary-+].
So for example
(+ x y 4 z)
represents the same term as
(binary-+ x (binary-+ y (binary-+ 4 z))).
See [binary-+].
Macro: <+>
(defmacro + (&rest rst)
(if rst
(if (cdr rst)
(xxxjoin 'binary-+ rst)
(cons 'binary-+
(cons 0 (cons (car rst) nil))))
0))
Subtopics
[Binary-+]
Addition function")
(-
(NUMBERS ACL2-BUILT-INS)
"Macro for subtraction and negation
See [binary-+] for addition and see [unary--] for negation.
Note that - represents subtraction as follows:
(- x y)
represents the same term as
(+ x (- y))
which is really
(binary-+ x (unary-- y)).
Also note that - represents arithmetic negation as follows:
(- x)
expands to
(unary-- x).
Macro: <->
(defmacro
- (x &optional (y 'nil binary-casep))
(if binary-casep
(let ((y (if (and (consp y)
(eq (car y) 'quote)
(consp (cdr y))
(acl2-numberp (car (cdr y)))
(eq (cdr (cdr y)) nil))
(car (cdr y))
y)))
(if (acl2-numberp y)
(cons 'binary-+
(cons (unary-- y) (cons x nil)))
(cons 'binary-+
(cons x
(cons (cons 'unary-- (cons y nil))
nil)))))
(let ((x (if (and (consp x)
(eq (car x) 'quote)
(consp (cdr x))
(acl2-numberp (car (cdr x)))
(eq (cdr (cdr x)) nil))
(car (cdr x))
x)))
(if (acl2-numberp x)
(unary-- x)
(cons 'unary-- (cons x nil))))))")
(/
(NUMBERS ACL2-BUILT-INS)
"Macro for division and reciprocal
See [binary-*] for multiplication and see [unary-/] for reciprocal.
Note that / represents division as follows:
(/ x y)
represents the same term as
(* x (/ y))
which is really
(binary-* x (unary-/ y)).
Also note that / represents reciprocal as follows:
(/ x)
expands to
(unary-/ x).
/ is a Common Lisp macro. See any Common Lisp documentation for more
information.
Macro: </>
(defmacro / (x &optional (y 'nil binary-casep))
(cond (binary-casep (list 'binary-* x (list 'unary-/ y)))
(t (list 'unary-/ x))))")
(/=
(NUMBERS ACL2-BUILT-INS)
"Test inequality of two numbers
(/= x y) is logically equivalent to (not (equal x y)).
Unlike [equal], /= has a [guard] requiring both of its arguments to
be numbers. Generally, /= is executed more efficiently than a
combination of [not] and [equal].
For a discussion of the various ways to test against 0, See
[zero-test-idioms].
/= is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: </=>
(defun /= (x y)
(declare (xargs :guard (and (acl2-numberp x)
(acl2-numberp y))))
(not (equal x y)))")
(1+
(NUMBERS ACL2-BUILT-INS)
"Increment by 1
(1+ x) is the same as (+ 1 x). See [+].
1+ is a Common Lisp function. See any Common Lisp documentation for
more information.
Macro: <1+>
(defmacro 1+ (x) (list '+ 1 x))")
(1-
(NUMBERS ACL2-BUILT-INS)
"Decrement by 1
(1- x) is the same as (- x 1). See [-].
1- is a Common Lisp function. See any Common Lisp documentation for
more information.
Macro: <1->
(defmacro 1- (x) (list '- x 1))")
(<
(NUMBERS ACL2-BUILT-INS)
"Less-than
Completion Axiom (completion-of-<):
(equal (< x y)
(if (and (rationalp x)
(rationalp y))
(< x y)
(let ((x1 (if (acl2-numberp x) x 0))
(y1 (if (acl2-numberp y) y 0)))
(or (< (realpart x1) (realpart y1))
(and (equal (realpart x1) (realpart y1))
(< (imagpart x1) (imagpart y1)))))))
[Guard] for (< x y):
(and (rationalp x) (rationalp y))
Notice that like all arithmetic functions, < treats non-numeric
inputs as 0.
This function has the usual meaning on the rational numbers, but is
extended to the complex rational numbers using the lexicographic
order: first the real parts are compared, and if they are equal,
then the imaginary parts are compared.")
(<=
(NUMBERS ACL2-BUILT-INS)
"Less-than-or-equal test
<= is a macro, and (<= x y) expands to the same thing as (not (< y
x)). See [<].
<= is a Common Lisp function. See any Common Lisp documentation for
more information.
Macro: <<=>
(defmacro <= (x y)
(list 'not (list '< y x)))")
(=
(NUMBERS EQUAL EQUALITY-VARIANTS ACL2-BUILT-INS)
"Test equality of two numbers
(= x y) is logically equivalent to (equal x y).
Unlike [equal], = has a [guard] requiring both of its arguments to be
numbers. Generally, = is executed more efficiently than [equal].
For a discussion of the various ways to test against 0, See
[zero-test-idioms].
= is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <=>
(defun = (x y)
(declare (xargs :guard (and (acl2-numberp x)
(acl2-numberp y))))
(equal x y))")
(>
(NUMBERS ACL2-BUILT-INS)
"Greater-than test
> is a macro, and (> x y) expands to the same thing as (< y x). See
[<].
> is a Common Lisp function. See any Common Lisp documentation for
more information.
Macro: <>>
(defmacro > (x y) (list '< y x))")
(>=
(NUMBERS ACL2-BUILT-INS)
"Greater-than-or-equal test
>= is a macro, and (>= x y) expands to the same thing as (not (< x
y)). See [<].
>= is a Common Lisp function. See any Common Lisp documentation for
more information.
Macro: <>=>
(defmacro >= (x y)
(list 'not (list '< x y)))")
(@
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Get the value of a global variable in [state]
Examples:
(+ (@ y) 1)
(assign a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B))
General Form:
(@ symbol)
where symbol is any symbol to which you have [assign]ed a global
value. This macro expands into (f-get-global 'symbol state), which
retrieves the stored value of the symbol.
The macro f-get-global is closely related to [@]: (@ var)
macroexpands to (f-get-global 'var state).
The macro [assign] makes it convenient to set the value of a symbol.
The :[ubt] operation has no effect on the global-table of [state].
Thus, you may use these globals to hang onto useful data structures
even though you may undo back past where you computed and saved
them.")
(A!
(LD)
"To return to the top-level of ACL2's command loop
When (a!) is evaluated inside of ACL2's command loop, the current
computation is aborted and control returns to the top of the
command loop, exactly as though the user had interrupted and
aborted the current computation. (Note: Versions of ACL2 up to
Version_3.4 provided `#.' for this purpose, but no longer; see
[sharp-dot-reader].)
If you are at an ACL2 prompt (as opposed to a raw Lisp break), then
you may type :a! in place of (a!); see [keyword-commands].
For a related feature that only pops up one level, see [p!].
Logically speaking, (a!) = nil. But imagine that it is defined in
such a way that it causes a stack overflow or other resource
exhaustion when called.")
(ABORT!
(LD)
"To return to the top-level of ACL2's command loop
This is an alias for a!; see [a!]. For a related feature that only
pops up one level, see [p!].")
(ABOUT-ACL2
(ACL2)
"General information About ACL2
This is ACL2 Version 7.2, [copyright] (C) 2016, Regents of the
University of Texas, authored by Matt Kaufmann and J Strother
Moore.
See the {ACL2 home page | http://www.cs.utexas.edu/users/moore/acl2/}
for additional information including tutorials, installation
instructions, mailing lists, related publications, ACL2 workshops
and seminars, acknowledgements, and other ACL2 releases.
See [documentation] for how to access the ACL2 User's Manual.
For statistics on ACL2 code size, see file doc/acl2-code-size.txt.
Subtopics
[Acknowledgments]
Some contributors to the well-being of ACL2
[ACL2-help]
The acl2-help mailing list
[Bibliography]
Reports about ACL2
[Building-ACL2]
How to build an ACL2 executable
[Common-lisp]
Relation to Common Lisp, including deviations from the spec
[Copyright]
ACL2 copyright, license, sponsorship
[Git-quick-start]
Git quick start guide
[Release-notes]
Pointers to what has changed
[Version]
ACL2 Version Number")
(ABOUT_MODELS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"About Models
[{IMAGE}]
ACL2 is used to construct mathematical models of computer hardware
and software (i.e., ``digital systems'').
{IMAGE}
A mathematical model is a set of mathematical formulas used to
predict the behavior of some artifact.
The use of mathematical models allows faster and cheaper delivery of
better systems.
Models need not be complete or perfectly accurate to be useful to the
trained engineer.
Click [here] for more discussion of these assertions in an
engineering context.
[{IMAGE}]")
(ABOUT_THE_ACL2_HOME_PAGE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"About the ACL2 Home Page
[{IMAGE}]
The ACL2 Home Page is integrated into the ACL2 online documentation.
Over 4 megabytes of hypertext is available here.
The vast majority of the text is user-level documentation. For
example, to find out about [rewrite] [{ICON}] rules you could click
on the link. (If you do that, remember to use your browser's Back
Button to come back here.)
The tiny warning signs [{ICON}] mark links that lead out of the
introductory-level material and into the user documentation. We
advise against following such links upon your first reading of the
documentation.
At the end of the tours you will have a chance to revisit them
quickly to explore alternative paths more fully.
Finally, every page contains two icons at the bottom. The ACL2 icon
leads you back to the ACL2 Home Page. The Index icon allows you to
browse an alphabetical listing of all the topics in ACL2's online
documentation. But both icons take you off the main route of the
tour.
[{IMAGE}]")
(ABOUT_THE_ADMISSION_OF_RECURSIVE_DEFINITIONS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"About the Admission of Recursive Definitions
You can't just add any formula as an axiom or definition and expect
the logic to stay sound! For example, if we were permitted to
define (APP X Y) so that it was equal to (NOT (APP X Y)) then we
could prove anything. The purported ``definition'' of APP must have
several properties to be admitted to the logic as a new axiom.
The key property a recursive definition must have is that the
recursion terminate. This, along with some syntactic criteria,
ensures us that there exists a function satisfying the definition.
Termination must be proved before the definition is admitted. This is
done in general by finding a measure of the arguments of the
function and a well-founded relation such that the arguments ``get
smaller'' every time a recursive branch is taken.
For app the measure is the ``size'' of the first argument, x, as
determined by the primitive function [ACL2-count] [{ICON}]. The
well-founded relation used in this example is [o-p] [{ICON}], which
is the standard ordering on the ordinals less than ``epsilon
naught.'' These particular choices for app were made
``automatically'' by ACL2. But they are in fact determined by
various ``default'' settings. The user of ACL2 can change the
defaults or specify a ``hint'' to the [defun] [{ICON}] command to
specify the measure and relation.
You should now return to [the Walking Tour].")
(ABOUT_THE_PROMPT
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"About the Prompt
The string ``ACL2 !>'' is the ACL2 prompt.
The prompt tells the user that an ACL2 [command] [{ICON}]is expected.
In addition, the prompt tells us a little about the current state
of the ACL2 command interpreter. We explain the prompt briefly
below. But first we talk about the command interpreter.
An ACL2 command is generally a Lisp expression to be evaluated. There
are some unusual commands (such as :[q] [{ICON}] for quitting ACL2)
which cause other behavior. But most commands are read, evaluated,
and then have their results printed. Thus, we call the command
interpreter a ``read-eval-print loop.'' The ACL2 command
interpreter is named [ld] [{ICON}] (after Lisp's ``load'').
When a command is read, all the symbols in it are converted to
uppercase. Thus, typing (defun app ...) is the same as typing
(DEFUN APP ...) or (defun App ...). There are ways to force
lowercase case characters into symbols but we won't discuss them
here. A consequence of Common Lisp's default uppercasing is that
you'll see a general lack of concern over the case used when
symbols are displayed in this documentation.
In addition, symbols ``belong'' to ``packages'' which give the user a
way to control namespaces. The prompt tells us which package is the
default one, namely \"ACL2\". That means when we call car, for
example, we are invoking the standard definition of that symbol. If
the packager were \"JONES\" then car would refer to the definition of
that symbol in that package (which may or may not be different
depending on what symbols were imported into that package.
A command like (defun app (x y) ...) causes ACL2 to evaluate the
[defun] [{ICON}] function on app, (x y) and .... When that command
is evaluated it prints some information to the terminal explaining
the processing of the proposed definition. It returns the symbol
APP as its value, which is printed by the command interpreter.
(Actually, defun is not a function but a [macro] [{ICON}] which
expands to a form that involves [state] [{ICON}], a necessary
precondition to printing output to the terminal and to ``changing''
the set of axioms. But we do not discuss this further here.)
The defun command is an example of a special kind of command called
an ``event.'' [Events] [{ICON}] are those commands that change the
``logical world'' by adding such things as axioms or theorems to
ACL2's database. See [world] [{ICON}]. But not every command is an
event command.
A command like (app '(1 2 3) '(4 5 6 7)) is an example of a
non-event. It is processed the same general way: the function app
is applied to the indicated arguments and the result is printed.
The function app does not print anything and does not change the
``world.''
A third kind of command is one that display information about the
current logical world or that ``roll back'' to previous versions of
the world. Such commands are called ``[history]'' [{ICON}]
commands.
What does the ACL2 prompt tell us about the read-eval-print loop? The
prompt ``ACL2 !>'' tells us that the command will be read with
[current-package] [{ICON}] set to \"ACL2\", that guard checking (see
[set-guard-checking] [{ICON}]) is on (``!''), and that we are at
the top-level (there is only one ``>''). For more about the prompt,
see [default-print-prompt] [{ICON}].
You should now return to [the Walking Tour].")
(ABOUT_TYPES
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"About Types
The universe of ACL2 objects includes objects of many different
types. For example, t is a ``symbol'' and 3 is an ``integer.''
Roughly speaking the objects of ACL2 can be partitioned into the
following types:
[Numbers] 3, -22/7, #c(3
5/2) [Characters] #\\A, #\\a,
#\\Space [Strings] \"This is a
string.\" [Symbols] 'abc,
'smith::abc [Conses (or
Ordered Pairs)] '((a . 1) (b . 2))
When proving theorems it is important to know the types of object
returned by a term. ACL2 uses a complicated heuristic algorithm,
called [type-set] [{ICON}], to determine what types of objects a
term may produce. The user can more or less program the type-set
algorithm by proving [type-prescription] [{ICON}] rules.
ACL2 is an ``untyped'' logic in the sense that the syntax is not
typed: It is legal to apply a function symbol of n arguments to any
n terms, regardless of the types of the argument terms. Thus, it is
permitted to write such odd expressions as (+ t 3) which sums the
symbol t and the integer 3. Common Lisp does not prohibit such
expressions. We like untyped languages because they are simple to
describe, though proving theorems about them can be awkward
because, unless one is careful in the way one defines or states
things, unusual cases (like (+ t 3)) can arise.
To make theorem proving easier in ACL2, the axioms actually define a
value for such terms. The value of (+ t 3) is 3; under the ACL2
axioms, non-numeric arguments to + are treated as though they were
0.
You might immediately wonder about our claim that ACL2 is Common
Lisp, since (+ t 3) is ``an error'' (and will sometimes even
``signal an error'') in Common Lisp. It is to handle this problem
that ACL2 has guards. We will discuss guards later in the Walking
Tour. However, many new users simply ignore the issue of guards
entirely and that is what we recommend for now.
You should now return to [the Walking Tour].")
(ABS
(NUMBERS ACL2-BUILT-INS)
"The absolute value of a real number
(Abs x) is -x if x is negative and is x otherwise.
The [guard] for abs requires its argument to be a rational ([real],
in ACL2(r)) number.
Abs is a Common Lisp function. See any Common Lisp documentation for
more information.
From ``Common Lisp the Language'' page 205, we must not allow complex
x as an argument to abs in ACL2, because if we did we would have to
return a number that might be a floating point number and hence not
an ACL2 object.
Function: <abs>
(defun abs (x)
(declare (xargs :guard (real/rationalp x)))
(if (minusp x) (- x) x))")
(ACCESS
(DEFREC ACL2-BUILT-INS)
"Accessor macro for [defrec] structures.
The access macro is built into ACL2, and allows you to access
particular fields from structures that have been introduced with
[defrec]. For instance:
(access employee x :name)
would return the name field from the employee x. See [defrec] for
more information.")
(ACCUMULATED-PERSISTENCE
(DEBUGGING)
"To get statistics on which [rune]s are being tried
Useful Forms:
(accumulated-persistence t) ; Activate statistics gathering.
(accumulated-persistence :all) ; As above, ``enhanced'' (see below)
(show-accumulated-persistence :frames) ; Display statistics ordered by
(show-accumulated-persistence :tries) ; frames built, times tried,
(show-accumulated-persistence :ratio) ; or their ratio.
(show-accumulated-persistence) ; Same as supplying :frames argument.
(accumulated-persistence nil) ; Deactivate.
(accumulated-persistence-oops) ; Undo the clearing effect of
; (accumulated-persistence nil).
Advanced forms:
(show-accumulated-persistence :frames-s) ; The `s', `f', and `a' suffixes
(show-accumulated-persistence :frames-f) ; stand for `success' (`useful'),
(show-accumulated-persistence :frames-a) ; `failure' (`useless'), and `all',
(show-accumulated-persistence :tries-s) ; respectively. The only effect of
(show-accumulated-persistence :tries-f) ; the `s' and `f' versions is to
(show-accumulated-persistence :tries-a) ; sort first by useful or useless
; applications, respectively (see
; below). The `a' versions avoid
; showing the useful/useless
; breakdown.
(show-accumulated-persistence :runes) ; Just show runes alphabetically.
(show-accumulated-persistence :useless) ; Just show useless runes.
(show-accumulated-persistence :useless :list)
; Just show useless runes as a list.
In summary, (accumulated-persistence t) turns on fresh statistics
gathering for rules, (accumulated-persistence nil) turns it off,
(show-accumulated-persistence) displays the statistics that were
gathered, and (accumulated-persistence-oops) restores the
statistics, if any, that were cleared by (accumulated-persistence
t) or (accumulated-persistence :all).
In general, if the optional second argument of
show-accumulated-persistence is supplied as :list, then instead of
the result being displayed a ``pretty'' human-readable format, the
result will be displayed as a correspondingg list of entries of the
form (frames tries xrune).
Note: set-accumulated-persistence is equivalent to
accumulated-persistence.
See the end of this item for a discussion of ``enhanced statistics
gathering,'' which can be useful for more fine-grained proof
debugging.
Generally speaking, the more ACL2 knows, the slower it runs. That is
because the search space grows with the number of alternative
rules. Often, the system tries to apply rules that you have
forgotten were even there, if you knew about them in the first
place! ``Accumulated-persistence'' is a statistic (originally
developed for Nqthm) that helps you identify the rules that are
causing ACL2's search space to explode.
For other proof debugging utilities, see [break-rewrite] and see
[dmr].
Accumulated persistence tracking can be turned on or off. It is
generally off. When on, proofs may take perhaps 50% more time than
otherwise! But some useful numbers are collected. When it is turned
on, by
ACL2 !>(accumulated-persistence t)
an accumulation site is initialized and henceforth data about which
rules are being tried is accumulated into that site. That
accumulated data can be displayed with
show-accumulated-persistence, as described in detail below. When
accumulated persistence is turned off, with
(accumulated-persistence nil), the accumulation site is wiped out
and the data in it is lost.
The ``accumulated persistence'' of a [rune] is the number of [rune]s
the system has attempted to apply (since accumulated persistence
was last activated) while the given [rune] was being tried.
Consider a :[rewrite] rule named [rune]. For simplicity, let us
imagine that [rune] is tried only once in the period during which
accumulated persistence is being monitored. Recall that to apply a
rewrite rule we must match the left-hand side of the conclusion to
some term we are trying to rewrite, establish the hypotheses of
[rune] by rewriting, and, if successful, then rewrite the
right-hand side of the conclusion. We say [rune] is ``being tried''
from the time we have matched its left-hand side to the time we
have either abandoned the attempt or finished rewriting its
right-hand side. (By ``match'' we mean to include any loop-stopper
requirement; see [loop-stopper].) During that period of time other
rules might be tried, e.g., to establish the hypotheses. The rules
tried while [rune] is being tried are ``billed'' to [rune] in the
sense that they are being considered here only because of the
demands of [rune]. Thus, if no other rules are tried during that
period, the accumulated persistence of [rune] is 1 --- we ``bill''
[rune] once for its own application attempt. If, on the other hand,
we tried 10 rules on behalf of that application of [rune], then
[rune]'s accumulated persistence would be 11.
One way to envision accumulated persistence is to imagine that every
time a [rune] is tried it is pushed onto a stack. The rules tried
on behalf of a given application of a [rune] are thus pushed and
popped on the stack above that [rune]. A lot of work might be done
on its behalf --- the stack above the [rune] grows and shrinks
repeatedly as the search continues for a way to use the [rune]. All
the while, the [rune] itself ``persists'' in the stack, until we
finish with the attempt to apply it, at which time we pop it off.
The accumulated persistence of a [rune] application is thus the
number of stack frames built while that [rune] was on the stack.
Note that accumulated persistence is tallied whether or not the
attempt to apply a [rune] is successful. Each of the rules tried on
its behalf might have failed and the attempt to apply the [rune]
might have also failed. The ACL2 proof script would make no mention
of the [rune] or the rules tried on its behalf because they did not
contribute to the proof. But time was spent pursuing the possible
application of the [rune] and accumulated persistence is a measure
of that time.
A high accumulated persistence might come about in two extreme ways.
One is that the rule causes a great deal of work every time it is
tried. The other is that the rule is ``cheap'' but is tried very
often. We therefore keep track of the number of times each rule is
tried as well as its persistence. The ratio between the two is the
average amount of work done on behalf of the rule each time it is
tried.
When the accumulated persistence totals are displayed by the function
show-accumulated-persistence we sort them so that the most
expensive [rune]s are shown first. We can sort according to one of
three basic keys:
:frames - the number of frames built on behalf of the rune
:tries - the number of times the rune was tried
:ratio - frames built per try
The key simply determines the order in which the information is
presented. If no argument is supplied to
show-accumulated-persistence, :frames is used.
The display breaks each total into ``useful'' and ``useless''
subtotals. A ``useful'' rule try is one that is viewed as
contributing to the progress of the proof, and the rest are
``useless'' rule applications. For example, if a :[rewrite] rule is
tried but its hypotheses are not successfully relieved, then that
rule application and all work done on behalf of those hypotheses is
``useless'' work. In general, an attempt to apply a [rune] is
viewed as ``useful'' unless the attempt fails or the attempt is on
the stack (as described above) for a [rune] application that
ultimately fails. A large number of ``useless'' :frames or :tries
along with correspondingly small ``useful'' counts may suggest
[rune]s to consider disabling (see [disable] and see [in-theory]).
Thus, here is a more complete list of the arguments that may be
supplied to show-accumulated-persistence. Suffixes ``s'', ``f'',
and ``a'' are intended to suggest ``success'' (``useful''),
``failure'' (``useless''), and ``all''.
:frames - sort by the number of frames built on behalf of the rune
:frames-s - as above, but sort by useful applications
:frames-f - as above, but sort by useless applications
:frames-a - as above, but inhibit display of ``useful'' and
``useless'' subtotals
:tries - sort by the number of times the rune was tried
:tries-s - as above, but sort by useful applications
:tries-f - as above, but sort by useless applications
:tries-a - as above, but inhibit display of ``useful'' and
``useless'' subtotals
:ratio - sort by frames built per try
:useless - show only the runes tried whose tries were all ``useless''
For a given line of the report, every frame credited to a ``useful''
(respectively, ``useless'') rule application is considered
``useful'' (respectively, ``useless''). We illustrate with the
following example.
(progn
(defstub hyp (x) t)
(defstub concl (x) t)
(defstub bad (x) t)
(defstub good (x) t)
(defaxiom good-ax
(implies (good x) (hyp x)))
(defaxiom bad-ax
(implies (bad x) (hyp x)))
(defaxiom hyp-implies-concl
(implies (hyp x) (concl x)))
)
(accumulated-persistence t)
(thm (implies (good x) (concl x)))
(show-accumulated-persistence)
To prove the [thm] form, ACL2 attempts to rewrite (concl x) to true
by applying rule hyp-implies-concl. It then attempts to establish
(hyp x) first by trying rule bad-ax, which fails, and second by
trying rule good-ax, which succeeds. As expected, the report labels
as ``useless'' the failure of the attempt to establish the
hypothesis, (bad x).
--------------------------------
1 1 ( 1.00) (:REWRITE BAD-AX)
0 0 [useful]
1 1 [useless]
--------------------------------
Now consider the top-level application of rule hyp-implies-concl.
Even though the above report shows the application of bad-ax as
``useless'', note that this rule was applied on behalf of the
successful (``useful'') application of hyp-implies-concl, and hence
is incorporated into the ``useful'' line for hyp-implies-concl, as
follows.
--------------------------------
3 1 ( 3.00) (:REWRITE HYP-IMPLIES-CONCL)
3 1 [useful]
0 0 [useless]
--------------------------------
In summary: categorization of :frames as ``useful'' or ``useless'' is
based on whether they support ``useful'' or ``useless'' :tries.
Note that a [rune] with high accumulated persistence may not actually
be the ``culprit.'' For example, suppose rune1 is reported to have
a :ratio of 101, meaning that on the average a hundred and one
frames were built each time rune1 was tried. Suppose rune2 has a
:ratio of 100. It could be that the attempt to apply rune1 resulted
in the attempted application of rune2 and no other [rune]. Thus, in
some sense, rune1 is ``cheap'' and rune2 is the ``culprit'' even
though it is reported as costing less than rune1.
If a proof is aborted, then in general,
[show-accumulated-persistence] will only display totals for runes
whose attempted application is complete: that is, if the rewriter
was in the process of relieving hypotheses for a rule, then
information for that rule will not be included in the tally. We say
``in general'' because, as indicated near the top of the output
from [show-accumulated-persistence] when such incomplete
information is omitted, you can get this information by using
argument :frames-a or :tries-a.
There are other subtleties in how rune applications are tallied,
documented elsewhere: see [accumulated-persistence-subtleties].
We conclude with a discussion of ``enhanced'' statistics gathering,
which is enabled by supplying accumulated-persistence the argument
:ALL:
(accumulated-persistence :all)
At some additional performance expense (but probably well under a
factor of 2 altogether), ACL2 then gathers additional statistics
for individual hypotheses of rules as well as their conclusions. To
understand how this works, suppose rn is a [rune]. Then we prepend
the keyword :CONC to rn to form what we call its ``conclusion
xrune'', and for its I-th hypothesis we prepend :HYP I to rn to
form its I-th ``hypothesis xrune.'' Here, ``xrune'' is pronounced
``ex rune'', and is mnemonic for ``extended rune.'' For example, if
(REWRITE FOO) is a [rune] then (:CONC REWRITE FOO) is its
conclusion xrune, and (:HYP 2 REWRITE FOO) is a hypothesis xrune
corresponding to the second hypothesis of the corresponding rewrite
rule.
With (accumulated-persistence :all), we instruct ACL2 to track not
only runes but also xrunes. Then, (show-accumulated-persistence)
will display information for all xrunes in a format that we
consider to be ``raw'', in the sense that data for xrunes are
displayed just as for runes. But a ``merged'' format is also
available. Here is a summary of display commands, followed below by
further discussion.
(show-accumulated-persistence :frames t) ; t is optional, i.e., the default
; Display enhanced statistics sorted by frames, in a ``raw'' format.
(show-accumulated-persistence :frames :merge)
; Display enhanced statistics sorted by frames, in a ``merged'' format.
(show-accumulated-persistence :frames nil)
; Display regular statistics sorted by frames
; (runes only, that is, without the enhancements).
(show-accumulated-persistence :frames :merge)
; Display a list of entries (frames tries xrune), sorted by frames
; More generally, the descriptions just above apply for any legal first
; argument:
(show-accumulated-persistence KEY t)
(show-accumulated-persistence KEY :merge)
(show-accumulated-persistence KEY nil)
(show-accumulated-persistence KEY :list)
; Note also these alternate forms, equivalent to the first of the two forms
; just above, i.e., the form with second argument of t:
(show-accumulated-persistence KEY :raw)
(show-accumulated-persistence KEY)
There is a significant difference between how runes are tracked and
how ACL2 tracks hypothesis and conclusion xrunes: unlike regular
runes, these xrunes do not contribute to the accumulated :frames
counts. Rather, they serve as accumulation sites without
contributing their :tries to any accumulation. Consider for example
the snippet below, taken from a report created with the :merge
option (to be discussed further below), i.e., by evaluating the
form (show-accumulated-persistence :frames :merge).
:frames :tries :ratio rune
--------------------------------
462 211 ( 2.18) (:REWRITE PERM-MEM)
13 6 [useful]
449 205 [useless]
.............................
251 47 ( 5.34) (:HYP 2 :REWRITE PERM-MEM)
6 6 [useful]
245 41 [useless]
.............................
0 211 ( 0.00) (:HYP 1 :REWRITE PERM-MEM)
0 6 [useful]
0 205 [useless]
.............................
0 7 ( 0.00) (:CONC :REWRITE PERM-MEM)
0 6 [useful]
0 1 [useless]
--------------------------------
Notice that while :tries are recorded for the xrune (:HYP 1 :REWRITE
PERM-MEM), no :frames are recorded. This is because no stack frames
were built for runes while this xrune was on the stack --- only for
the xrune itself, which as we explained above is not accumulated
into the total :frames counts. As it turns out, this lack of stack
frames is explained by the fact that the rewrite rule PERM-MEM has
a free variable in the first hypothesis.
ACL2 !>:pe perm-mem
18 (DEFTHM PERM-MEM
(IMPLIES (AND (PERM X Y) (MEM A X))
(MEM A Y))
:RULE-CLASSES ((:REWRITE :MATCH-FREE :ONCE)))
ACL2 !>
The second hypothesis, however, does cause additional rewriting in
order to rewrite it to true, resulting in 251 stack frames for
runes. We see that the conclusion does not lead to creation of any
rune stack frames, which might seem to suggest that only 251 stack
frames for runes were created on behalf of this rule application
--- yet, we see that 462 frames were actually created. The
difference is the 211 frames created for the rewrite rule itself.
Even if the total had been a bit more than 462, one need not be
surprised, as there could be some work recorded during application
of the rewrite rule, such as type-prescription reasoning, that is
not done during rewriting of a hypothesis or the conclusion.
Now suppose we have executed (accumulated-persistence :all) and
attempted some proofs, and now we are ready to see statistics. The
form (show-accumulated-persistence) displays statistics exactly as
described above, treating these extra xrunes just as though they
are runes; similarly for the form (show-accumulated-persistence
KEY), for any legal KEY. A second optional argument may however be
supplied to show-accumulated-persistence. The default for that
second argument is t, and a second argument of :raw is treated the
same as t; thus, these arguments provide the behavior just
described, where data for xrunes are displayed just as for runes.
You may restrict output to runes, ignoring hypothesis and
conclusion xrunes, by giving a second argument of nil. (This gives
the same behavior as if we had started with the command
(accumulated-persistence t) instead of the command
(accumulated-persistence :all).) You may give a second argument of
:merge, in which case output will be sorted and displayed as though
only runes were tracked (not the extra xrunes), but each data item
for a non-rune xrune will be merged so that it is displayed in
suitable order just below its corresponding rune, as in the
PERM-MEM example displayed above. Finally, you may give a second
argument of :list, which is equivalent to the default second
argument of t, except that the results are printe as a list of
entries (frames tries xrune).
We close by mentioning two aspects of enhanced statistics display for
:CONC xrunes that have potential to be confusing. First consider
the following example.
:frames :tries :ratio rune
--------------------------------
14 4 ( 3.50) (:REWRITE DEFAULT-+-2)
0 0 [useful]
14 4 [useless]
.............................
10 4 ( 2.50) (:HYP 1 :REWRITE DEFAULT-+-2)
0 0 [useful]
10 4 [useless]
--------------------------------
It may be surprising that no data is displayed for the corresponding
:CONC xrune. The explanation, however, is simple: the hypothesis
never rewrote to true, so the conclusion was never rewritten. This
is consistent with the marking as ``useless'' of all :frames and
:tries for the rune and the hypothesis xrune. Note by the way, once
again, that the hypothesis xrune does not contribute to any :frames
count.
Another reason not to see data displayed for a :CONC xrune is that if
a rule has no hypotheses, then no such data is collected. This
decision was made because in the case of no hypotheses, we expect
it to be very rare that information for the :CONC xrune will add
any useful insight.
On a final note: (show-accumulated-persistence :runes) may be used
simply to see a list of all [rune]s (or xrunes) displayed
alphabetically.
Users are encouraged to think about other meters we could install in
ACL2 to help diagnose performance problems.
Subtopics
[Accumulated-persistence-subtleties]
Some subtle aspects of the counting done by
[accumulated-persistence]
[Dmr]
Dynamically monitor rewrites and other prover activity")
(ACCUMULATED-PERSISTENCE-OOPS (POINTERS)
"See [accumulated-persistence].")
(ACCUMULATED-PERSISTENCE-SUBTLETIES
(ACCUMULATED-PERSISTENCE)
"Some subtle aspects of the counting done by [accumulated-persistence]
In this topic we cover the overcounting of ``useful'' and of
recursive [rune] application attempts, and we describe how
``useless'' [rune] application attempts can actually be critical
for a proof's success.
Overcounting of ``useful'' and of recursive rune application
attempts. Not every [rune] application may be necessary for a
proof's success. Consider for example:
(thm (equal (car (cons a (cdr (cons b x))))
a))
Then show-accumulated-persistence will tell us that :[rewrite] rules
car-cons and cdr-cons each had one useful application. However, the
rule cdr-cons is used to simplify (cdr (cons b x)) to x, and this
simplification is unecessary for the proof. Indeed, the proof
succeeds even when preceded by the event: (in-theory (disable
cdr-cons)). We thus see that a [rune] application labeled as
``useful'' may be simplifying a term that is not relevant to the
proof.
As of this writing, we consider every :[forward-chaining] rule
application to be ``useful'', for simplicity of the implementation.
Moreover, our counting of these rules is such that a single rule
may be counted more than once.
Next we show how recursive rule applications are overcounted.
Consider the following example.
(defun mem (a x)
(if (atom x)
nil
(or (equal a (car x)) (mem a (cdr x)))))
Now suppose we consider the sequence of theorems (mem a (list a)),
(mem a (list 1 a)), (mem a (list 1 2 a)), (mem a (list 1 2 3 a)),
and so on. We will see that the :frames reported for each increases
quadratically, even though the :tries increases linearly; so in
this case the :tries statistics are more appropriate. Each time the
definition of mem is applied, a new stack frame is pushed (see
[accumulated-persistence]), and all subsequent applications of that
definition are accumulated into the :frames count for that stack
frame. The final :frames count will be the sum of the counts for
those individual frames, which form a linear sequence whose sum is
therefore quadratic in the number of applications of the definition
of mem.
How ``useless'' attempts can be critical for a proof's success. The
command (accumulated-persistence :useless)] will list rules that
did not contribute directly to the proof (see
[accumulated-persistence], in particular the discussion of
``useless'' there). However, a ``useless'' rule can on rare
occasions be critical to the success of a proof. In the following
example, we have a ``bad'' rule that can take the proof in the
wrong direction, but a ``useless'' rule does a rewrite that
prevents the succesful relieving of a hypothesis of the ``bad''
rule. In summary:
; Assume p0. We want to prove p1.
; Key rule:
p0 -> p1 = t
; Bad rule that could ruin the proof:
p3 -> p1 = p2
; But unfortunately, we know p3:
p0 -> p3
; Important ``useless'' rule, preventing ``bad rule'' above from firing:
p3 = p4
The following event captures the rules described above.
(encapsulate
((p0 (x) t)
(p1 (x) t)
(p2 (x) t)
(p3 (x) t)
(p4 (x) t))
(local (defun p0 (x) x))
(local (defun p1 (x) x))
(local (defun p2 (x) x))
(local (defun p3 (x) x))
(local (defun p4 (x) x))
; Key rule:
(defthm p0-implies-p1
(implies (p0 x)
(p1 x)))
; Bad rule that could ruin the proof:
(defthm p3-implies-p1-is-p2
(implies (p3 x)
(equal (p1 x) (p2 x))))
; But unfortunately, we know p3:
(defthm p0-implies-p3
(implies (p0 x)
(p3 x)))
; Important ``useless'' rule, preventing p3-implies-p1-is-p2 from firing:
(defthm p3-is-p4
(equal (p3 x) (p4 x))))
Now we can see that p3-is-p4 is labeled as ``useless'', by evaluating
these commands.
(accumulated-persistence t)
(thm (implies (p0 x) (p1 x)))
(show-accumulated-persistence)
If instead we first evaluate (in-theory (disable p3-is-p4)) before
the thm above, then the proof fails, even though p3-is-p4 was
labeled as ``useless''!
Nevertheless, in general it is probably safe to disable rules
reported as ``useless'' by (show-accumulated-persistence :useless),
and doing so may speed up a proof considerably.
Remark. The example above suggests a surprising fact: on rare
occasions, a proof may fail when you give an :[in-theory] hint
consisting of exactly the [rune]s reported in a proof that
succeeds. For, imagine a rule R that is needed in part of the proof
but is ``bad'' in a second part, and that some other, ``useless''
rule prevents the application of R in that second part. The example
above suggests that disabling this ``useless'' rule can allow the
second application of R, thus preventing the proof.")
(ACKNOWLEDGMENTS
(ABOUT-ACL2)
"Some contributors to the well-being of ACL2
The development of ACL2 was initially made possible by funding from
the U. S. Department of Defense, including ARPA and ONR. We thank
all the organizations that have contributed support, including the
following (in alphabetical order).
* AMD, for providing significant time over several years for Matt
Kaufmann to carry out ACL2 research, support, and development
* Computational Logic, Inc. and its president, Don Good, where the
first eight years of ACL2 development occurred
* Centaur Technology
* DARPA
* Digital Equipment Corporation
* EDS, which provided some time for Matt Kaufmann's ACL2 work 1998-1999
* ForrestHunt and, more generally, Warren A. Hunt, Jr. (see below)
* IBM
* NSF
* ONR
* Rockwell Collins
* SRC
* Sun Microsystems
* University of Texas at Austin (in particular support to J Moore
through the Admiral B. R. Inman Chair of Computing Theory)
We are especially grateful to Warren A. Hunt, Jr. for his unrivaled
efforts in securing support for the entire ACL2 research group at
both Computational Logic, Inc., and the University of Texas at
Austin. Without his efforts, we would have spent less time working
on the system and fewer students would have been funded to apply
it.
ACL2 was started in August, 1989 by Boyer and Moore working together.
They co-authored the first versions of axioms.lisp and basis.lisp,
with Boyer taking the lead in the formalization of ``[state]'' and
the most primitive [io] functions. Boyer also had a significant
hand in the development of the early versions of the files
interface-raw.lisp and translate.lisp. For several years, Moore
alone was responsible for developing the ACL2 system code, though
he consulted often with both Boyer and Kaufmann. In August, 1993,
Kaufmann became jointly responsible with Moore for developing the
system. Boyer has continued to provide valuable consulting on an
informal basis.
Bishop Brock was the heaviest early user of ACL2, and provided many
suggestions for improvements. In particular, the :cases and
:restrict [hints] were his idea; he developed an early version of
congruence-based reasoning for Nqthm; and he helped in the
development of some early [books] about arithmetic. In a
demonstration of his courage and faith in us, he pushed for
Computational Logic, Inc., to agree to the Motorola CAP contract --
which required formalizing a commercial DSP in the untested ACL2 --
and moved to Scottsdale, AZ, to do the work with the Motorola
design team. His demonstration of ACL2's utility was an
inspiration, even to those of us designing ACL2.
John Cowles also helped in the development of some early [books]
about arithmetic, and also provided valuable feedback and bug
reports.
Other early users of ACL2 at Computational Logic, Inc. helped
influence its development. In particular, Warren Hunt helped with
the port to Macintosh Common Lisp, and Art Flatau and Mike Smith
provided useful general feedback.
Mike Smith helped develop the Emacs portion of the implementation of
proof trees.
Bill Schelter made some enhancements to akcl (now gcl) that helped to
enhance ACL2 performance in that Common Lisp implementation, and
more generally, responded helpfully to our bug reports. Camm
Maguire has since provided wonderful gcl support, and has created a
Debian package for ACL2 built on GCL. We are also grateful to
developers of other Common Lisp implementations.
Kent Pitman helped in our interaction with the ANSI Common Lisp
standardization committee, X3J13.
John Cowles helped with the port to Windows (98) by answering
questions and running tests.
Ruben Gamboa created a modification of ACL2 to allow reasoning about
the real numbers using non-standard analysis. His work has been
incorporated into the ACL2 distribution; see [real].
Rob Sumners has made numerous useful suggestions. In particular, he
has designed and implemented improvements for [stobj]s and been key
in our development of locally-bound stobjs; see [note-2-6].
Robert Krug has designed and implemented many changes in the vicinity
of the linear arithmetic package and its connection to type-set and
rewrite. He was also instrumental in the development of
[extended-metafunctions].
Pete Manolios has made numerous useful suggestions. In particular,
Pete helped us to organize the first workshop and was a wonderful
equal partner with the two of us (Kaufmann and Moore) in producing
the books that arose from that workshop. Pete and his student,
Daron Vroon, provided the current implementation of [ordinals].
Jared Davis, Sol Swords, and David Rager have our gratitude for
starting the {ACL2+Books repository |
https://github.com/acl2/acl2/}.
We thank David L. Rager for contributing an initial version of the
support for [parallelism] in an experimental extension of ACL2.
Bob Boyer and Warren A. Hunt, Jr. developed a canonical
representation for ACL2 data objects, applicative hash tables, and
a function memoization mechanism to facilitate reuse of previously
computed results. Subsequently, Jared Davis and Sol Swords made
further contributions. We thank them all for this work, most of
which has been incorporated into ACL2; see [hons-and-memoization].
We also thank the contributors to the ACL2 workshops for some
suggested improvements and for the extensive collection of publicly
distributed benchmark problems. And we thank participants at the
ACL2 seminar at the University of Texas for useful feedback. More
generally, we thank the ACL2 community for feedback, contributed
[books] (see [community-books]), and their interest in the ACL2
project.
Regarding the documentation:
Bill Young wrote significant portions of the original acl2-tutorial
section of the ACL2 documentation, including what is now called
[alternative-introduction]. This was an especially important
task in the early years when there was no guide for how to use
ACL2 and we are very grateful. He, Bishop Brock, Rich Cohen,
and Noah Friedman read over considerable amounts of the
documentation, and made many useful comments. Others,
particularly Bill Bevier and John Cowles, have also made useful
comments on the [documentation].
Art Flatau helped develop the ACL2 markup language in which ACL2
[documentation] was originally developed, along with
translators from that language to Texinfo and HTML. Michael
``Bogo'' Bogomolny created a search engine, beginning with
Version 2.6, and for that purpose modified the HTML translator
to create one file per topic (a good idea in any case).
Laura Lawless provided many hours of help in marking up appropriate
parts of the [documentation] in typewriter font.
Noah Friedman developed an Emacs tool that helped us insert
``invisible links'' into the [documentation], which improve the
usability of that documentation under HTML readers such as
Mosaic.
Richard Stallman contributed a texinfo patch, to be found in the file
doc/texinfo.tex.
Jared Davis created the [xdoc] system that is now the basis not only
for the ACL2 system [documentation] (file
books/system/doc/acl2-doc.lisp), but also for the
[community-books] documentation.
We thank Blake Grugett for designing the current version of the ACL2
logo (which for example appears on the ACL2 home page), based on an
original design created in the 1990s by Computational Logic, Inc.")
(ACL2
NIL
"ACL2 documentation (system only, not including the community books)
This is the ACL2 documentation. For the ACL2+Books Manual, which that
includes both the ACL2 documentation and the ACL2
[community-books], see the {ACL2+Books Manual |
http://www.cs.utexas.edu/users/moore/acl2/v7-2/combined-manual/index.html}.
Subtopics
[About-ACL2]
General information About ACL2
[ACL2-tutorial]
Tutorial introduction to ACL2
[Bdd]
Ordered binary decision diagrams with rewriting
[Books]
Books are files of ACL2 [events]---they are the main way to split up
large ACL2 developments into separate modules.
[Debugging]
Tools for debugging failed or slow proofs, or misbehaving functions.
[Documentation]
Information about options for downloading and viewing the ACL2
documentation, contributing documentation, and the available
tools for documenting your own books.
[Events]
Functions that extend the logic
[History]
Functions that display or change history
[Hons-and-memoization]
Hash cons, function memoization, and applicative hash tables
[Interfacing-tools]
Libraries and tools for doing basic [file i/o], using raw [Common
Lisp libraries], working with the [operating system], and
interfacing with [other programs].
[Macros]
Macros allow you to extend the syntax of ACL2.
[Miscellaneous]
A miscellany of documented functions and concepts (often cited in
more accessible [documentation])
[Parallelism]
Experimental extension for parallel execution and proofs
[Programming]
Programming in ACL2
[Proof-checker]
An interactive tool for controlling ACL2's proof processes.
[Prover-output]
Methods for controlling the output produced by ACL2 during proofs
and in other situations.
[Real]
ACL2(r) support for real numbers
[Rule-classes]
Adding rules to the database
[Theories]
Sets of [rune]s to [enable]/[disable] in concert")
(ACL2-AS-STANDALONE-PROGRAM
(ACL2-TUTORIAL)
"Calling ACL2 from another program
ACL2 is intended for interactive use. It is generally unrealistic to
expect it to prove theorems fully automatically; see [the-method],
and see [introduction-to-the-theorem-prover] for a more detailed
tutorial.
Nevertheless, here we describe an approach for how to call the ACL2
theorem prover noninteractively. These steps can of course be
modified according to your needs. Here, we illustrate how to call
ACL2 from another Lisp program (or an arbitrary program) to attempt
to prove an arithmetic theorem.
See also [interfacing-tools]. In particular, if you want to make a
command-line tool to ACL2 with options, you may be interested in
[oslib::argv], [getopt], and especially [getopt-demo::demo2].
Alternately, if you want to develop a server application on top of
ACL2, you might consider [bridge].
Step 1
Build a suitable ACL2 image by starting ACL2 and then executing the
following forms. In particular, these define a macro, try-thm, that
causes ACL2 to exit with with an exit status indicating success or
failure of a proof attempt.
(include-book \"arithmetic-5/top\" :dir :system)
(defmacro try-thm (&rest args)
`(mv-let (erp val state)
(with-prover-time-limit 3 (thm ,@args))
(declare (ignore val))
(prog2$ (if erp (exit 1) (exit 0)) state))))
(reset-prehistory) ; optional
:q
(save-exec \"arith-acl2\" \"Included arithmetic-4/top\")
If you prefer, above you can replace 3 by some other number of
seconds as a time limit for the prover. Also, you can replace
(with-prover-time-limit 3 (thm ,@args))
by
(with-output :off :all (with-prover-time-limit 3 (thm ,@args)))
if you want to turn off output. It may be best to leave the output
on, instead eliminating it in the calling program (see Step 3
below).
Step 2
Try a little test. In that same directory try this:
echo '(try-thm (equal x x))' | ./arith-acl2
echo $?
The exit status should be 0, indicating success. Now try this:
echo '(try-thm (not (equal x x)))' | ./arith-acl2
echo $?
The exit status should be 1, indicating failure.
Step 3
Create a shell script that automates Step 2, for example:
#!/bin/sh
(echo \"(try-thm $1)\" | ./arith-acl2) >& /dev/null
exit $?
Step 4
Try your script from a Lisp program, if you like. Here is how you can
do it in SBCL, for example. (Different Lisps have different ways to
do this, as summarized in function system-call in ACL2 source file
acl2-init.lisp.)
(defun provable? (x)
(let ((status
(process-exit-code
(sb-ext:run-program \"./try-thm.sh\" (list (format nil \"~s\" x))
:output t :search t))))
(eql status 0)))
Then here is a log:
* (provable? '(equal x y))
NIL
* (provable? '(equal x x))
T
*
Certainly refinements are possible -- for example the above doesn't
distinguish between unprovable and ill-formed input. But it's a
start.")
(ACL2-BUILT-INS
(PROGRAMMING)
"''Catch-all'' topic for built-in ACL2 functions
This [documentation] topic is a parent topic under which we include
documentation for built-in functions, macros, and special forms
that are typically used in [programming]. For others, including
those typically used as top-level commands or those that create
[events] ([defun], [defmacro], [defthm], and so on), documentation
may be found as a subtopic of some other parent topic. We do not
document some of the more obscure functions provided by ACL2 that
do not correspond to functions of Common Lisp.
See any documentation for Common Lisp for more details on many of
these functions.
Subtopics
[*]
Multiplication macro
[*ACL2-exports*]
Symbols that are often imported into new [packages] to provide easy
access to ACL2 functionality.
[*common-lisp-symbols-from-main-lisp-package*]
Symbols that are often imported into new packages to provide easy
access to Common Lisp functionality.
[*standard-ci*]
An ACL2 character-based analogue of CLTL's *standard-input*
[*standard-co*]
The ACL2 analogue of CLTL's *standard-output*
[*standard-oi*]
An ACL2 object-based analogue of CLTL's *standard-input*
[+]
Addition macro
[-]
Macro for subtraction and negation
[/]
Macro for division and reciprocal
[/=]
Test inequality of two numbers
[1+]
Increment by 1
[1-]
Decrement by 1
[<]
Less-than
[<=]
Less-than-or-equal test
[=]
Test equality of two numbers
[>]
Greater-than test
[>=]
Greater-than-or-equal test
[@]
Get the value of a global variable in [state]
[Abs]
The absolute value of a real number
[Access]
Accessor macro for [defrec] structures.
[ACL2-count]
A commonly used measure for justifying recursion
[ACL2-number-listp]
Recognizer for a true list of numbers
[ACL2-numberp]
Recognizer for numbers
[Acons]
Constructor for association lists
[Add-to-set]
Add a symbol to a list
[Alistp]
Recognizer for association lists
[Allocate-fixnum-range]
Set aside fixnums in GCL
[Alpha-char-p]
Recognizer for alphabetic characters
[Alphorder]
Total order on atoms
[And]
Conjunction
[Append]
[concatenate] zero or more lists
[Aref1]
Access the elements of a 1-dimensional array
[Aref2]
Access the elements of a 2-dimensional array
[Arities-okp]
check the arities of given function symbols
[Arity]
number of arguments of a function symbol
[Array1p]
Recognize a 1-dimensional array
[Array2p]
Recognize a 2-dimensional array
[Aset1]
Set the elements of a 1-dimensional array
[Aset2]
Set the elements of a 2-dimensional array
[Ash]
Arithmetic shift operation
[Assert$]
Cause a hard error if the given test is false
[Assert*]
Create a [guard] proof obligation that given test holds
[Assign]
Assign to a global variable in [state]
[Assoc]
Look up key in association list
[Assoc-keyword]
Look up key in a [keyword-value-listp]
[Assoc-string-equal]
Look up key, a string, in association list
[Atom]
Recognizer for atoms
[Atom-listp]
Recognizer for a true list of [atom]s
[Binary-*]
Multiplication function
[Binary-+]
Addition function
[Binary-append]
[concatenate] two lists
[Boole$]
Perform a bit-wise logical operation on 2 two's complement integers
[Boolean-listp]
Recognizer for a true list of booleans
[Booleanp]
Recognizer for booleans
[Break$]
Cause an immediate Lisp break
[Break-on-error]
Break when encountering a hard or soft error caused by ACL2
[Butlast]
All but a final segment of a list
[Caaaar]
[car] of the [caaar]
[Caaadr]
[car] of the [caadr]
[Caaar]
[car] of the [caar]
[Caadar]
[car] of the [cadar]
[Caaddr]
[car] of the [caddr]
[Caadr]
[car] of the [cadr]
[Caar]
[car] of the [car]
[Cadaar]
[car] of the [cdaar]
[Cadadr]
[car] of the [cdadr]
[Cadar]
[car] of the [cdar]
[Caddar]
[car] of the [cddar]
[Cadddr]
[car] of the [cdddr]
[Caddr]
[car] of the [cddr]
[Cadr]
[car] of the [cdr]
[Canonical-pathname]
The true absolute filename, with soft links resolved
[Car]
Returns the first element of a non-empty list, else nil
[Case]
Conditional based on if-then-else using [eql]
[Case-match]
Pattern matching or destructuring
[Cbd]
Connected book directory string
[Cdaaar]
[cdr] of the [caaar]
[Cdaadr]
[cdr] of the [caadr]
[Cdaar]
[cdr] of the [caar]
[Cdadar]
[cdr] of the [cadar]
[Cdaddr]
[cdr] of the [caddr]
[Cdadr]
[cdr] of the [cadr]
[Cdar]
[cdr] of the [car]
[Cddaar]
[cdr] of the [cdaar]
[Cddadr]
[cdr] of the [cdadr]
[Cddar]
[cdr] of the [cdar]
[Cdddar]
[cdr] of the [cddar]
[Cddddr]
[cdr] of the [cdddr]
[Cdddr]
[cdr] of the [cddr]
[Cddr]
[cdr] of the [cdr]
[Cdr]
Returns the second element of a [cons] pair, else nil
[Ceiling]
Division returning an integer by truncating toward positive infinity
[Change]
Mutator macro for [defrec] structures.
[Char]
The [nth] element (zero-based) of a string
[Char-code]
The numeric code for a given character
[Char-downcase]
Turn upper-case [characters] into lower-case [characters]
[Char-equal]
Character equality without regard to case
[Char-upcase]
Turn lower-case [characters] into upper-case [characters]
[Char<]
Less-than test for [characters]
[Char<=]
Less-than-or-equal test for [characters]
[Char>]
Greater-than test for [characters]
[Char>=]
Greater-than-or-equal test for [characters]
[Character-alistp]
Recognizer for association lists with characters as keys
[Character-listp]
Recognizer for a true list of characters
[Characterp]
Recognizer for [characters]
[Code-char]
The character corresponding to a given numeric code
[Coerce]
Coerce a character list to a string and a string to a list
[Comp]
Compile some ACL2 functions
[Comp-gcl]
Compile some ACL2 functions leaving .c and .h files
[Complex]
Create an ACL2 number
[Complex-rationalp]
Recognizes complex rational numbers
[Complex/complex-rationalp]
Recognizer for complex numbers
[Compress1]
Remove irrelevant pairs from a 1-dimensional array
[Compress2]
Remove irrelevant pairs from a 2-dimensional array
[Concatenate]
Concatenate lists or strings together
[Cond]
Conditional based on if-then-else
[Conjugate]
Complex number conjugate
[Cons]
Pair and list constructor
[Cons-subtrees]
Build a fast alist whose keys are the subtrees of X
[Consp]
Recognizer for [cons] pairs
[Count]
Count the number of occurrences of an item in a string or true-list
[Cpu-core-count]
The number of cpu cores
[Cw]
Print to the comment window
[Cw!]
Print to the comment window
[Declare]
Extra declarations that can occur in function definitions, [let]
bindings, and so forth.
[Default]
Return the :default from the [header] of a 1- or 2-dimensional array
[Delete-assoc]
Remove the first pair from an association list for a given key
[Denominator]
Divisor of a ratio in lowest terms
[Digit-char-p]
The number, if any, corresponding to a given character
[Digit-to-char]
Map a digit to a character
[Dimensions]
Return the :dimensions from the [header] of a 1- or 2-dimensional
array
[Ec-call]
Execute a call in the ACL2 logic instead of raw Lisp
[Eighth]
Eighth member of the list
[Endp]
Recognizer for empty lists
[Eq]
Equality of symbols
[Eql]
Test equality (of two numbers, symbols, or [characters])
[Eqlable-alistp]
Recognizer for a true list of pairs whose [car]s are suitable for
[eql]
[Eqlable-listp]
Recognizer for a true list of objects each suitable for [eql]
[Eqlablep]
The [guard] for the function [eql]
[Equal]
True equality
[Er]
Print an error message and ``cause an error''
[Er-progn]
Perform a sequence of state-changing ``error triples''
[Error1]
Print an error message and cause a ``soft error''
[Evenp]
Test whether an integer is even
[Explode-atom]
Convert any [atom] into a [character-listp] that contains its
printed representation, rendering numbers in your choice of
print base.
[Explode-nonnegative-integer]
The list of [characters] in the radix-r form of a number
[Expt]
Exponential function
[F-get-global]
Get the value of a global variable in [state]
[F-put-global]
Assign to a global variable in [state]
[Fast-alist-clean]
([fast-alist-clean] alist) can be used to eliminate \"shadowed pairs\"
from a fast alist.
[Fast-alist-clean!]
([fast-alist-clean!] alist) is an alternative to [fast-alist-clean]
that produces a [normed] result.
[Fast-alist-fork]
([fast-alist-fork] alist ans) can be used to eliminate \"shadowed
pairs\" from an alist or to copy [fast-alists].
[Fast-alist-fork!]
([fast-alist-fork!] alist ans) is an alternative to
[fast-alist-fork] that produces a [normed] result.
[Fast-alist-free]
([fast-alist-free] alist) throws away the hash table associated with
a fast alist.
[Fast-alist-free-on-exit]
Free a fast alist after the completion of some form.
[Fast-alist-len]
([fast-alist-len] alist) counts the number of unique keys in a fast
alist.
[Fast-alist-summary]
([fast-alist-summary]) prints some basic statistics about any
current fast alists.
[Fifth]
Fifth member of the list
[First]
First member of the list
[Fix]
Coerce to a number
[Fix-true-list]
Coerce to a true list
[Flet]
Local binding of function symbols
[Floor]
Division returning an integer by truncating toward negative infinity
[Flush-compress]
Flush the under-the-hood array for the given name
[Flush-hons-get-hash-table-link]
Deprecated feature
[Fms]
([fms] str alist co-channel state evisc) => state
[Fms!]
([fms!] str alist co-channel state evisc) => state
[Fmt]
Formatted printing
[Fmt!]
([fmt!] str alist co-channel state evisc) => state
[Fmt-to-comment-window]
Print to the comment window
[Fmt1]
([fmt1] str alist col co-channel state evisc) => ([mv] col state)
[Fmt1!]
([fmt1!] str alist col channel state evisc) => ([mv] col state)
[Formula]
The formula of a name or [rune]
[Fourth]
Fourth member of the list
[Gc$]
Invoke the garbage collector
[Gc-strategy]
The garbage collection strategy
[Get-internal-time]
Runtime vs. realtime in ACL2 timings
[Getenv$]
Read an environment variable
[Getprop]
Access fast property lists
[Getpropc]
Access fast property lists
[Good-atom-listp]
Recognizer for a true list of ``good'' [atom]s
[Good-bye]
Quit entirely out of Lisp
[Hard-error]
Print an error message and stop execution
[Header]
Return the header of a 1- or 2-dimensional array
[Hons]
([hons] x y) returns a [normed] object equal to ([cons] x y).
[Hons-acons]
([hons-acons] key val alist) is the main way to create or extend
[fast-alists].
[Hons-acons!]
([hons-acons!] key val alist) is an alternative to [hons-acons] that
produces [normed], fast alists.
[Hons-assoc-equal]
([hons-assoc-equal] key alist) is not fast; it serves as the logical
definition for [hons-get].
[Hons-clear]
([hons-clear] gc) is a drastic garbage collection mechanism that
clears out the underlying Hons Space.
[Hons-clear!]
A version of [hons-clear] for [parallel] execution
[Hons-copy]
([hons-copy] x) returns a [normed] object that is equal to X.
[Hons-copy-persistent]
([hons-copy-persistent] x) returns a [normed] object that is equal
to X and which will be re-normed after any calls to
[hons-clear].
[Hons-equal]
([hons-equal] x y) is a recursive equality check that optimizes when
parts of its arguments are [normed].
[Hons-get]
([hons-get] key alist) is the efficient lookup operation for
[fast-alists].
[Hons-resize]
([hons-resize] ...) can be used to manually adjust the sizes of the
hash tables that govern which ACL2 Objects are considered
[normed].
[Hons-shrink-alist]
Deprecated feature
[Hons-shrink-alist!]
Deprecated feature
[Hons-summary]
([hons-summary]) prints basic information about the sizes of the
tables in the current Hons Space.
[Hons-wash]
([hons-wash]) is like [gc$] but can also garbage collect [normed]
objects (CCL and GCL Only).
[Hons-wash!]
A version of [hons-wash] for [parallel] execution
[Identity]
The identity function
[If]
If-then-else function
[Iff]
Logical ``if and only if''
[Ifix]
Coerce to an integer
[Illegal]
Print an error message and stop execution
[Imagpart]
Imaginary part of a complex number
[Implies]
Logical implication
[Improper-consp]
Recognizer for improper (non-null-terminated) non-empty lists
[In-package]
Select current package
[In-tau-intervalp]
Boolean membership in a tau interval
[Int=]
Test equality of two integers
[Integer-length]
Number of bits in two's complement integer representation
[Integer-listp]
Recognizer for a true list of integers
[Integer-range-p]
Recognizer for integers between two bounds.
[Integerp]
Recognizer for whole numbers
[Intern]
Create a new symbol in a given package
[Intern$]
Create a new symbol in a given package
[Intern-in-package-of-symbol]
Create a symbol with a given name
[Intersection$]
Elements of one list that are not elements of another
[Intersectp]
Test whether two lists intersect
[Keyword-value-listp]
Recognizer for true lists whose even-position elements are keywords
[Keywordp]
Recognizer for keywords
[Kwote]
Quote an arbitrary object
[Kwote-lst]
Quote an arbitrary true list of objects
[Last]
The last [cons] (not element) of a list
[Last-prover-steps]
The number of prover steps most recently taken
[Len]
Length of a list
[Length]
Length of a string or proper list
[Let]
Binding of lexically scoped (local) variables
[Let*]
Binding of lexically scoped (local) variables
[Lexorder]
Total order on ACL2 objects
[List]
Build a list
[List*]
Build a list
[Listp]
Recognizer for (not necessarily proper) lists
[Logand]
Bitwise logical `and' of zero or more integers
[Logandc1]
Bitwise logical `and' of two ints, complementing the first
[Logandc2]
Bitwise logical `and' of two ints, complementing the second
[Logbitp]
The ith bit of an integer
[Logcount]
Number of ``on'' bits in a two's complement number
[Logeqv]
Bitwise logical equivalence of zero or more integers
[Logior]
Bitwise logical inclusive or of zero or more integers
[Lognand]
Bitwise logical `nand' of two integers
[Lognor]
Bitwise logical `nor' of two integers
[Lognot]
Bitwise not of a two's complement number
[Logorc1]
Bitwise logical inclusive or of two ints, complementing the first
[Logorc2]
Bitwise logical inclusive or of two ints, complementing the second
[Logtest]
Test if two integers share a `1' bit
[Logxor]
Bitwise logical exclusive or of zero or more integers
[Lower-case-p]
Recognizer for lower case characters
[Make]
Constructor macro for [defrec] structures.
[Make-character-list]
[coerce] to a list of characters
[Make-fast-alist]
([make-fast-alist] alist) creates a fast-alist from the input alist,
returning alist itself or, in some cases, a new object equal to
it.
[Make-list]
Make a list of a given size
[Make-ord]
A constructor for ordinals.
[Make-tau-interval]
Make a tau interval
[Max]
The larger of two numbers
[Maximum-length]
Return the :maximum-length from the [header] of an array
[Mbe]
Attach code for execution
[Mbe1]
Attach code for execution
[Mbt]
Introduce a test into the logic that, however, evaluates to t
[Mbt*]
Introduce a guard proof obligation
[Member]
Membership predicate
[Min]
The smaller of two numbers
[Minusp]
Test whether a number is negative
[Mod]
Remainder using [floor]
[Mod-expt]
Exponential function
[Msg]
Construct a ``message'' suitable for the ~@ directive of [fmt]
[Must-be-equal]
Attach code for execution
[Mv]
Returning a multiple value
[Mv-let]
Calling multi-valued ACL2 functions
[Mv-list]
Converting multiple-valued result to a single-valued list
[Mv-nth]
The mv-nth element (zero-based) of a list
[Mv?]
Return one or more values
[Mv?-let]
Calling possibly multi-valued ACL2 functions
[Nat-listp]
Recognizer for a true list of natural numbers
[Natp]
A recognizer for the natural numbers
[Nfix]
Coerce to a natural number
[Ninth]
Ninth member of the list
[No-duplicatesp]
Check for duplicates in a list
[Non-exec]
Mark code as non-executable
[Nonnegative-integer-quotient]
Natural number division function
[Not]
Logical negation
[Nth]
The nth element (zero-based) of a list
[Nthcdr]
Final segment of a list
[Null]
Recognizer for the empty list
[Number-subtrees]
([number-subtrees] x) returns the number of distinct subtrees of X,
in the sense of [equal]
[Numerator]
Dividend of a ratio in lowest terms
[O-finp]
Recognizes if an ordinal is finite
[O-first-coeff]
Returns the first coefficient of an ordinal
[O-first-expt]
The first exponent of an ordinal
[O-infp]
Recognizes if an ordinal is infinite
[O-p]
A recognizer for the ordinals up to epsilon-0
[O-rst]
Returns the rest of an infinite ordinal
[O<]
The well-founded less-than relation on ordinals up to epsilon-0
[O<=]
The less-than-or-equal relation for the ordinals
[O>]
The greater-than relation for the ordinals
[O>=]
The greater-than-or-equal relation for the ordinals
[Observation]
Print an observation
[Oddp]
Test whether an integer is odd
[Open-output-channel!]
When trust tags are needed to open output channels
[Or]
Disjunction
[Oracle-apply]
Call a function argument on the given list of arguments
[Oracle-apply-raw]
Call a function argument on the given list of arguments, no
restrictions
[Oracle-funcall]
Call a function argument on the remaining arguments
[Pairlis$]
Zipper together two lists
[Pand]
Parallel, Boolean version of [and]
[Pargs]
Parallel evaluation of arguments in a function call
[Pkg-witness]
Return a specific symbol in the indicated package
[Plet]
Parallel version of [let]
[Plusp]
Test whether a number is positive
[Por]
Parallel, Boolean version of [or]
[Position]
Position of an item in a string or a list
[Posp]
A recognizer for the positive integers
[Pprogn]
Evaluate a sequence of forms that return [state]
[Primitive]
Primitive functions built into ACL2 without definitions
[Princ$]
Print an atom
[Print-base-p]
Recognizer for print bases that are understood by functions such as
[explode-nonnegative-integer] and [explode-atom].
[Prog2$]
Execute two forms and return the value of the second one
[Progn$]
Execute a sequence of forms and return the value of the last one
[Proofs-co]
The proofs character output channel
[Proper-consp]
Recognizer for proper (null-terminated) non-empty lists
[Pseudo-termp]
A predicate for recognizing term-like s-expressions
[Put-assoc]
Modify an association list by associating a value with a key
[Putprop]
Update fast property lists
[Quote]
Create a constant
[R-eqlable-alistp]
Recognizer for a true list of pairs whose [cdr]s are suitable for
[eql]
[R-symbol-alistp]
Recognizer for association lists with symbols as values
[Random$]
Obtain a random value
[Rassoc]
Look up value in association list
[Rational-listp]
Recognizer for a true list of rational numbers
[Rationalp]
Recognizer for rational numbers (ratios and integers)
[Read-ACL2-oracle]
Pop the oracle field of the state
[Read-run-time]
Read elapsed runtime
[Real-listp]
ACL2(r) recognizer for a true list of real numbers
[Real/rationalp]
Recognizer for rational numbers (including real number in ACL2(r))
[Realfix]
Coerce to a real number
[Realpart]
Real part of a complex number
[Rem]
Remainder using [truncate]
[Remove]
Remove all occurrences
[Remove-duplicates]
Remove duplicates from a string or a list
[Remove1]
Remove first occurrences, testing using [eql]
[Resize-list]
List resizer in support of stobjs
[Rest]
Rest ([cdr]) of the list
[Return-last]
Return the last argument, perhaps with side effects
[Revappend]
Concatentate the [reverse] of one list to another
[Reverse]
Reverse a list or string
[Rfix]
Coerce to a rational number
[Round]
Division returning an integer by rounding off
[Search]
Search for a string or list in another string or list
[Second]
Second member of the list
[Serialize-read]
Read a serialized ACL2 object from a file
[Serialize-write]
Write an ACL2 object into a file
[Set-difference$]
Elements of one list that are not elements of another
[Set-fmt-hard-right-margin]
Set the right margin for formatted output
[Set-fmt-soft-right-margin]
Set the soft right margin for formatted output
[Set-gc-strategy]
Set the garbage collection strategy (CCL only)
[Set-print-base]
Control radix in which numbers are printed
[Set-print-base-radix]
Control radix in which numbers are printed and printing of the radix
[Set-print-case]
Control whether symbols are printed in upper case or in lower case
[Set-print-radix]
Control printing of the radix for numbers
[Setenv$]
Set an environment variable
[Seventh]
Seventh member of the list
[Signed-byte-p]
Recognizer for signed integers that fit in a specified bit width
[Signum]
Indicator for positive, negative, or zero
[Sixth]
Sixth member of the list
[Spec-mv-let]
Modification of [mv-let] supporting speculative and parallel
execution
[Standard-char-listp]
Recognizer for a true list of standard characters
[Standard-char-p]
Recognizer for standard characters
[Standard-co]
The character output channel to which [ld] prints
[Standard-oi]
The standard object input ``channel''
[Standard-string-alistp]
Recognizer for association lists with standard strings as keys
[State-global-let*]
Bind [state] global variables
[String]
[coerce] to a string
[String-append]
[concatenate] two strings
[String-downcase]
In a given string, turn upper-case [characters] into lower-case
[String-equal]
String equality without regard to case
[String-listp]
Recognizer for a true list of strings
[String-upcase]
In a given string, turn lower-case [characters] into upper-case
[String<]
Less-than test for strings
[String<=]
Less-than-or-equal test for strings
[String>]
Greater-than test for strings
[String>=]
Less-than-or-equal test for strings
[Stringp]
Recognizer for strings
[Strip-cars]
Collect up all first components of pairs in a list
[Strip-cdrs]
Collect up all second components of pairs in a list
[Sublis]
Substitute an alist into a tree
[Subseq]
Subsequence of a string or list
[Subsetp]
Test if every [member] of one list is a [member] of the other
[Subst]
A single substitution into a tree
[Substitute]
Substitute into a string or a list, using [eql] as test
[Symbol-<]
Less-than test for symbols
[Symbol-alistp]
Recognizer for association lists with symbols as keys
[Symbol-listp]
Recognizer for a true list of symbols
[Symbol-name]
The name of a symbol (a string)
[Symbol-package-name]
The name of the package of a symbol (a string)
[Symbolp]
Recognizer for symbols
[Sys-call]
Make a system call to the host operating system
[Sys-call+]
Make a system call to the host OS, returning status and output
[Sys-call-status]
Exit status from the preceding system call
[Take]
Initial segment (first n elements) of a list
[Tenth]
Tenth member of the list
[Term-list-listp]
recognizer for a list of clauses
[Term-listp]
recognizer for a list of quotations of terms and of clauses
[Term-order]
The ordering relation on terms used by ACL2
[Termp]
recognizer for the quotation of a term
[The]
The is a special form that can be used to optimize the execution
efficiency of [guard]-verified ACL2 definitions, or (less
frequently) to carry out a low-level run-time type checks.
(Advanced)
[Third]
Third member of the list
[Time$]
Time an evaluation
[Time-tracker]
Display time spent during specified evaluation
[True-list-listp]
Recognizer for true (proper) lists of true lists
[True-listp]
Recognizer for proper (null-terminated) lists
[Truncate]
Division returning an integer by truncating toward 0
[Unary--]
Arithmetic negation function
[Unary-/]
Reciprocal function
[Union$]
Elements of one list that are not elements of another
[Unquote]
Obtain the object being quoted
[Unsigned-byte-p]
Recognizer for natural numbers that fit in a specified bit width
[Update-nth]
Modify a list by putting the given value at the given position
[Update-nth-array]
Update a stobj array
[Upper-case-p]
Recognizer for upper case characters
[Value-triple]
Compute a value, optionally checking that it is not nil
[With-fast-alist]
([with-fast-alist] name form) causes name to be a fast alist for the
execution of form.
[With-guard-checking]
Suppressing or enable guard-checking for a form
[With-guard-checking-error-triple]
Suppressing or enable guard-checking for a form
[With-live-state]
Allow a reference to state in raw Lisp
[With-local-state]
Locally bind state
[With-local-stobj]
Locally bind a single-threaded object
[With-output-lock]
Provides a mutual-exclusion mechanism for performing output in
parallel
[With-serialize-character]
Control output mode for print-object$
[With-stolen-alist]
([with-stolen-alist] name form) ensures that name is a fast alist at
the start of the execution of form. At the end of execution, it
ensures that name is a fast alist if and only if it was
originally. That is, if name was not a fast alist originally,
its hash table link is freed, and if it was a fast alist
originally but its table was modified during the execution of
form, that table is restored. Note that any extended table
created from the original fast alist during form must be
manually freed.
[Without-evisc]
Print output in full
[Xor]
Logical ``exclusive or''
[Zerop]
Test an acl2-number against 0
[Zip]
Testing an ``integer'' against 0
[Zp]
Testing a ``natural'' against 0
[Zpf]
Testing a nonnegative fixnum against 0")
(ACL2-COUNT
(BASICS ACL2-BUILT-INS)
"A commonly used measure for justifying recursion
(Acl2-count x) returns a nonnegative integer that indicates the
``size'' of its argument x.
All [characters] and symbols have acl2-count 0. The acl2-count of a
string is the number of [characters] in it, i.e., its length. The
acl2-count of a [cons] is one greater than the sum of the
acl2-counts of the [car] and [cdr]. The acl2-count of an integer is
its absolute value. The acl2-count of a rational is the sum of the
acl2-counts of the numerator and denominator. The acl2-count of a
complex rational is one greater than the sum of the acl2-counts of
the real and imaginary parts.
Function: <acl2-count>
(defun acl2-count (x)
(declare (xargs :guard t))
(if (consp x)
(+ 1 (acl2-count (car x))
(acl2-count (cdr x)))
(if (rationalp x)
(if (integerp x)
(integer-abs x)
(+ (integer-abs (numerator x))
(denominator x)))
(if (complex/complex-rationalp x)
(+ 1 (acl2-count (realpart x))
(acl2-count (imagpart x)))
(if (stringp x) (length x) 0)))))")
(ACL2-CUSTOMIZATION
(MISCELLANEOUS)
"File of initial commands for ACL2 to run at [startup]
ACL2 provides a mechanism to load automatically a so-called ``ACL2
customization file,'' via [ld], the first time [lp] is called in an
ACL2 session. ACL2 looks for this file as follows.
1. If the host Lisp reads a non-empty value for the system's environment
variable ACL2_CUSTOMIZATION, then that string value is used for
the customization file name. In this case, if the file does not
exist or if the string is \"NONE\" then there is no customization
file. Notes:
* If the customization file name is a relative pathname (see
[pathname]), then the pathname is considered relative to
the connected book directory (see [cbd]).
* If this variable is not already defined, then its value is set to
NONE when books are certified using [build::cert.pl] or
other, legacy Make-based certification tools.
2. Otherwise (empty environment variable value), file
\"acl2-customization.lsp\" or \"acl2-customization.lisp\" on the
connected book directory (see [cbd]), generally the current
directory, is the customization file (in that order) if either
exists.
3. Otherwise file \"acl2-customization.lsp\" or \"acl2-customization.lisp\"
on your home directory is the customization file (in that
order), if either exists (except, this case is skipped on
Windows operating systems.
Except for the fact that this [ld] command is not typed explicitly by
you, it is a standard [ld] command, with one exception: any
settings of [ld] specials are remembered once this call of [ld] has
completed. For example, suppose that you start your customization
file with (set-ld-skip-proofsp t state), so that proofs are skipped
as it is loaded with [ld]. Then the [ld] special [ld-skip-proofsp]
will remain t after the [ld] has completed, causing proofs to be
skipped in your ACL2 session, unless your customization file sets
this variable back to nil, say with (set-ld-skip-proofsp nil
state).
If the customization file exists, it is loaded with [ld] using the
usual default values for the [ld] specials (see [ld]). Thus, if an
error is encountered, no subsequent forms in the file will be
evaluated.
To create a customization file it is recommended that you first give
it a name other than \"acl2-customization.lsp\" or
\"acl2-customization.lisp\" so that ACL2 does not try to include it
prematurely when you next enter [lp]. Then, while in the
uncustomized [lp], explicitly invoke [ld] on your evolving (but
renamed) customization file until all forms are successfully
evaluated. The same procedure is recommended if for some reason
ACL2 cannot successfully evaluate all forms in your customization
file: temporarily rename your customization file so that ACL2 does
not try to [ld] it automatically and then debug the new file by
explicit calls to [ld].
WARNING! If you certify a book after the (automatic) loading of a
customization file, the forms in that file will be part of the
[portcullis] of the [books] you certify! That is, the forms in your
customization file at certification time will be loaded whenever
anybody uses the [books] you are certifying. Since customization
files generally contain idiosyncratic [command]s, you may not want
yours to be part of the [books] you create for others. Thus, if you
have a customization file then you may want to invoke :[ubt] 1
before certifying any [books]; alternatively, see [certify-book!]
for automatic invocation of [ubt].
On the other hand, if you wish to prevent undoing commands from the
customization file, see [reset-prehistory].
Finally, we note that except on Windows-based systems, if there is a
file acl2-init.lsp in your home directory, then it will be loaded
into raw Lisp when ACL2 is invoked.")
(ACL2-DEFAULTS-TABLE
(TABLE)
"A [table] specifying certain defaults, e.g., the default [defun-mode]
Example Forms:
(table acl2-defaults-table :defun-mode) ; current default defun-mode
(table acl2-defaults-table :defun-mode :program)
; set default defun-mode to :program
See [table] for a discussion of tables in general. The legal keys for
this [table] are shown below. They may be accessed and changed via
the general mechanisms provided by [table]s. However, there are
often more convenient ways to access and/or change the defaults.
(See also the note below.)
:defun-mode
the default [defun-mode], which must be :[program] or :[logic]. See
[defun-mode] for a general discussion of [defun-mode]s. The
:[defun-mode] key may be conveniently set by keyword commands
naming the new [defun-mode], :[program] and :[logic]. See [program]
and see [logic].
:enforce-redundancy
if t, cause ACL2 to insist that most events are redundant (see
[redundant-events]); if :warn, cause a warning instead of an error
for such non-redundant events; else, nil. See
[set-enforce-redundancy].
:verify-guards-eagerness
an integer between 0 and 2 indicating how eager the system is to
verify the [guard]s of a [defun] event. See
[set-verify-guards-eagerness].
:compile-fns
When this key's value is t, functions are compiled when they are
[defun]'d; otherwise, the value is nil. (Except, this key's value
is ignored when explicit compilation is suppressed; see
[compilation].) To set the flag, see [set-compile-fns].
:measure-function
the default measure function used by [defun] when no :measure is
supplied in [xargs]. The default measure function must be a
function symbol of one argument. Let mfn be the default measure
function and suppose no :measure is supplied with some recursive
function definition. Then [defun] finds the first formal, var, that
is tested along every branch and changed in each recursive call.
The system then ``guesses'' that (mfn var) is the :measure for that
[defun].
:well-founded-relation
the default well-founded relation used by [defun] when no
:[well-founded-relation] is supplied in [xargs]. The default
well-founded relation must be a function symbol, rel, of two
arguments about which a :[well-founded-relation] rule has been
proved. See [well-founded-relation].
:bogus-defun-hints-ok
When this key's value is t, ACL2 allows :hints for nonrecursive
function definitions. Otherwise, the value is the nil (the default)
or :warn (which makes the check but merely warns when the check
fails). See [set-bogus-defun-hints-ok].
:bogus-mutual-recursion-ok
When this key's value is t, ACL2 skips the check that every function
in a [mutual-recursion] (or [defuns]) ``clique'' calls at least one
other function in that ``clique.'' Otherwise, the value is nil (the
default) or :warn (which makes the check but merely warns when the
check fails). See [set-bogus-mutual-recursion-ok].
:irrelevant-formals-ok
When this key's value is t, the check for irrelevant formals is
bypassed; otherwise, the value is the keyword nil (the default) or
:warn (which makes the check but merely warns when the check
fails). See [irrelevant-formals] and see
[set-irrelevant-formals-ok].
:ignore-ok
When this key's value is t, the check for ignored variables is
bypassed; otherwise, the value is the keyword nil (the default) or
:warn (which makes the check but merely warns when the check
fails). See [set-ignore-ok].
:bdd-constructors
This key's value is a list of function symbols used to define the
notion of ``BDD normal form.'' See [bdd-algorithm] and see [hints].
:ttag
This key's value, when non-nil, allows certain operations that extend
the trusted code base beyond what is provided by ACL2. See
[defttag]. See [defttag].
:state-ok
This key's value is either t or nil and indicates whether the user is
aware of the syntactic restrictions on the variable symbol STATE.
See [set-state-ok].
:backchain-limit
This key's value is a list of two ``numbers.'' Either ``number'' may
optionally be nil, which is treated like positive infinity. The
numbers control backchaining through hypotheses during type-set
reasoning and rewriting. See [backchain-limit].
:default-backchain-limit
This key's value is a list of two ``numbers.'' Either ``number'' may
optionally be nil, which is treated like positive infinity. The
numbers are used respectively to set the backchain limit of a rule
if one has not been specified. See [backchain-limit].
:step-limit
This key's value is either nil or a natural number not exceeding the
value of *default-step-limit*. If the value is nil or the value of
*default-step-limit*, there is no limit on the number of ``steps''
that ACL2 counts during a proof: currently, the number of top-level
rewriting calls. Otherwise, the value is the maximum number of such
calls allowed during evaluation of any event. See
[set-prover-step-limit].
:rewrite-stack-limit
This key's value is a nonnegative integer less than (expt 2 28). It
is used to limit the depth of calls of ACL2 rewriter functions. See
[rewrite-stack-limit].
:let*-abstractionp
This key affects how the system displays subgoals. The value is
either t or nil. When t, let* expressions are introduced before
printing to eliminate common subexpressions. The actual goal being
worked on is unchanged.
:case-split-limitations
This key's value is a list of two ``numbers.'' Either ``number'' may
optionally be nil, which is treated like positive infinity. The
numbers control how the system handles case splits in the
simplifier. See [set-case-split-limitations].
:include-book-dir-alist
This key's value is used by [include-book]'s :DIR argument to
associate a directory with a keyword. An exception is the keyword
:SYSTEM for the books/ directory; see [include-book], in particular
the section on ``Books Directory.'' Also see [add-include-book-dir]
and [add-include-book-dir!].
:match-free-default
This key's value is either :all, :once, or nil. See
[set-match-free-default].
:match-free-override
This key's value is a list of runes. See [add-match-free-override].
:match-free-override-nume
This key's value is an integer used in the implementation of
[add-match-free-override], so that only existing runes are affected
by that event.
:non-linearp
This key's value is either t or nil and indicates whether the user
wishes ACL2 to extend the linear arithmetic decision procedure to
include non-linear reasoning. See [non-linear-arithmetic].
:tau-auto-modep
This key's value is either t or nil and indicates whether the user
wishes ACL2 to look for opportunities to create :[tau-system] rules
from all suitable defuns and from all suitable defthms (with
non-nil :[rule-classes]). See [set-tau-auto-mode].
:ruler-extenders
This key's value may be a list of symbols, indicating those function
symbols that are not to block the collection of rulers; see
[defun]. Otherwise the value is :all to indicate all function
symbols, i.e., so that no function symbol blocks the collection of
rulers. If a list is specified (rather than :all), then it may
contain the keyword :lambdas, which has the special role of
specifying all lambda applications. No other keyword is permitted
in the list. See [ruler-extenders].
:memoize-ideal-okp
This key's value must be either t, nil, or :warn. If the value is nil
or not present, then it is illegal by default to [memoize] a
:[logic] mode function that has not been [guard]-verified (see
[verify-guards]), sometimes called an ``ideal-mode'' function. This
illegality is the default because such calls of such functions in
the ACL2 loop are generally evaluated in the logic (using so-called
``executable counterpart'' definitions), rather than directly by
executing calls of the corresponding (memoized) raw Lisp function.
However, such a raw Lisp call can be made when the function is
called by a :[program] mode function, so we allow you to override
the default behavior by associating the value t or :warn with the
key :memoize-ideal-okp, where with :warn you get a suitable
warning. Note that you can also allow memoization of ideal-mode
functions by supplying argument :ideal-okp to your memoization
event (see [memoize]), in which case the value of
:memoize-ideal-okp in the acl2-defaults-table is irrelevant.
:check-invariant-risk
For an explanation of this key, see [set-check-invariant-risk].
Note: Unlike all other [table]s, acl2-defaults-table can affect the
soundness of the system. The [table] mechanism therefore enforces
on it a restriction not imposed on other [table]s: when [table] is
used to update the acl2-defaults-table, the key and value must be
variable-free forms. Thus, while
(table acl2-defaults-table :defun-mode :program),
(table acl2-defaults-table :defun-mode ':program), and
(table acl2-defaults-table :defun-mode (compute-mode *my-data*))
are all examples of legal [events] (assuming compute-mode is a
function of one non-[state] argument that produces a [defun-mode]
as its single value),
(table acl2-defaults-table :defun-mode (compute-mode (w state)))
is not legal because the value form is [state]-sensitive.
Consider for example the following three [events] which one might
make into the text of a book.
(in-package \"ACL2\")
(table acl2-defaults-table
:defun-mode
(if (ld-skip-proofsp state) :logic :program))
(defun crash-and-burn (x) (car x))
The second event is illegal because its value form is
[state]-sensitive. If it were not illegal, then it would set the
:[defun-mode] to :[program] when the book was being certified but
would set the [defun-mode] to :[logic] when the book was being
loaded by [include-book]. That is because during certification,
[ld-skip-proofsp] is nil (proof obligations are generated and
proved), but during book inclusion [ld-skip-proofsp] is non-nil
(those obligations are assumed to have been satisfied.) Thus, the
above book, when loaded, would create a function in :[logic] mode
that does not actually meet the conditions for such status.
For similar reasons, [table] [events] affecting acl2-defaults-table
are illegal within the scope of [local] forms. That is, the text
(in-package \"ACL2\")
(local (table acl2-defaults-table :defun-mode :program))
(defun crash-and-burn (x) (car x))
is illegal because acl2-defaults-table is changed locally. If this
text were acceptable as a book, then when the book was certified,
crash-and-burn would be processed in :[program] mode, but when the
certified book was included later, crash-and-burn would have
:[logic] mode because the [local] event would be skipped.
The text
(in-package \"ACL2\")
(program) ;which is (table acl2-defaults-table :defun-mode :program)
(defun crash-and-burn (x) (car x))
is acceptable and defines crash-and-burn in :[program] mode, both
during certification and subsequent inclusion.
We conclude with an important observation about the relation between
acl2-defaults-table and [include-book], [certify-book], and
[encapsulate]. Including or certifying a book never has an effect
on the acl2-defaults-table, nor does executing an [encapsulate]
event; we always restore the value of this [table] as a final act.
(Also see [include-book], see [encapsulate], and see
[certify-book].) That is, no matter how a book fiddles with the
acl2-defaults-table, its value immediately after including that
book is the same as immediately before including that book. If you
want to set the acl2-defaults-table in a way that persists, you
need to do so using [command]s that are not inside [books]. It may
be useful to set your favorite defaults in your
[ACL2-customization] file; see [ACL2-customization].")
(ACL2-DOC
(DOCUMENTATION)
"A custom Emacs browser for reading ACL2 [documentation]
As discussed elsewhere (see [documentation]), the web-based
{ACL2+Books Manual |
http://www.cs.utexas.edu/users/moore/acl2/v7-2/combined-manual/index.html}
provides a way to browse the combined documentation for the ACL2
system and community books. This documentation can also be read at
the terminal using the :[doc] command, though documentation for
[books] will only be included for those books that have been
included in the session. In this topic we describe how to browse
the documentation using ACL2-Doc, a browser for reading ACL2 and
books documentation inside Emacs.
While ACL2-Doc is much like Emacs Info, it is a separate system that
provides some additional functionality. In order to use ACL2-Doc,
load the distributed file emacs/acl2-doc.el into Emacs. This will
happen automatically if you load emacs/emacs-acl2.el, which will
happen automatically if you put the following form in your ~/.emacs
file, replacing DIR by a path to your ACL2 installation.
(load \"DIR/emacs/emacs-acl2.el\")
Then to start the browser at the top-level topic, either execute the
Emacs command
meta-x acl2-doc
or else type:
Control-t g
By default you will browse the ACL2+Books Manual, though if you are
using a git version between ACL2 releases then you may be queried;
more on that below. You can enter the ACL2-Doc browser at a
specific documentation topic as follows (in analogy to Emacs
command Meta-.):
Control-t .
In each of the cases above, you will now be in a buffer called
\"acl2-doc\", which will be displaying the top-level ACL2 topic in a
special mode, the ACL2-Doc major mode. That mode provides the
following key bindings; you can also see these by typing Control-h
m while in that buffer.
<Return> acl2-doc-go!
g acl2-doc-go
h acl2-doc-help
i acl2-doc-index
, acl2-doc-index-next
< acl2-doc-index-previous
l acl2-doc-last
n acl2-doc-search-next
p acl2-doc-search-previous
q acl2-doc-quit
r acl2-doc-return
s acl2-doc-search
S acl2-doc-re-search
t acl2-doc-top
u acl2-doc-up
w acl2-doc-where
SPC scroll-up
TAB acl2-doc-tab
Control-TAB acl2-doc-tab-back
D acl2-doc-rendered-combined-download
H acl2-doc-history
I acl2-doc-initialize
You can see the documentation for each of these in the usual way,
using Control-h k {key} or Control-h f {command}. Here is what you
will find in each case if you do that.
<Return> acl2-doc-go!
Go to the topic occurring at the cursor position.
g acl2-doc-go
Go to the specified topic; performs completion.
h acl2-doc-help
Go to the ACL2-DOC topic to read about how to use the ACL2-Doc browser.
i acl2-doc-index
Go to the specified topic or else one containing it as a substring;
performs completion. If the empty string is supplied, then go to the
index buffer. Otherwise, with prefix argument, consider only descendents
of the topic supplied in response to a prompt. Note that the index buffer
is in ACL2-Doc mode; thus, in particular, you can type <RETURN> while
standing on a topic in order to go directly to that topic.
, acl2-doc-index-next
Find the next topic containing, as a substring, the topic of the most
recent i command. Note: if this is the first \",\" or \"<\" after an
exact match from \"i\", then start the topic search alphabetically from
the beginning, but avoid a second hit on the original topic.
< acl2-doc-index-previous
Find the previous topic containing, as a substring, the topic of the
most recent i command. Note: if this is the first \",\" or \"<\" after an
exact match from \"i\", then start the topic search alphabetically
(backwards) from that exact match.
l acl2-doc-last
Go to the last topic visited.
n acl2-doc-search-next
Find the next occurrence for the most recent search or regular expression
search.
p acl2-doc-search-previous
Find the previous occurrence for the most recent search or regular
expression search. Note: as for \"n\", the cursor will end up at the end
of the match.
q acl2-doc-quit
Quit the ACL2-Doc browser.
r acl2-doc-return
Return to the last topic visited, popping the stack of such topics.
s acl2-doc-search
Search forward from the top of the manual for the input string. If the
search succeeds, then go to that topic with the cursor put immediately
after the found text, with the topic name displayed in the minibuffer.
With prefix argument, consider (also for subsequent \"n\" and \"p\"
commands) only descendents of the topic supplied in response to a prompt.
S acl2-doc-re-search
Perform a regular expression search, forward from the top of the manual,
for the input string. If the search succeeds, then go to that topic with
the cursor put immediately after the found text, with the topic name
displayed in the minibuffer. With prefix argument, consider (also for
subsequent \"n\" and \"p\" commands) only descendents of the topic
supplied in response to a prompt.
t acl2-doc-top
Go to the top topic.
u acl2-doc-up
Go to the parent of the current topic.
w acl2-doc-where
Display the topic name in the minibuffer, together with the manual name
(ACL2+Books Manual or ACL2 User's Manual)
SPC scroll-up
Scroll up (same as Control-v)
TAB acl2-doc-tab
Visit the next link after the cursor on the current page, searching from
the top if no link is below the cursor.
Control-TAB acl2-doc-tab-back
Visit the previous link before the cursor on the current page, searching
from the bottom if no link is below the cursor.
D
Download the ``bleeding edge'' ACL2+Books Manual from the web; then
restart the ACL2-Doc browser to view that manual.
H acl2-doc-history
Visit a buffer that displays the names of all visited topics in order,
newest at the bottom. That buffer is in acl2-doc mode; thus the usual
acl2-doc commands may be used. In particular, you can visit a displayed
topic name by putting your cursor on it and typing <RETURN>.
I acl2-doc-initialize
Restart the ACL2-Doc browser, clearing its state. With prefix argument,
toggle between the ACL2 User's Manual (the default) and the ACL2+Books
Manual. For the latter, it will be necessary first to create file
books/system/doc/rendered-doc-combined.lsp; see :DOC acl2-doc.
Color
By default, links in square brackets will be shown in blue. You can
customize this behavior by setting (e.g., in your .emacs file) the
Emacs variable *acl2-doc-link-color* to the desired link color, or
to nil if you don't want the links to be in color. For example:
(setq *acl2-doc-link-color* \"#FF0000\") ; red
(setq *acl2-doc-link-color* \"Green\") ; green
(setq *acl2-doc-link-color* nil) ; no special color for links
The Two Manuals
ACL2-Doc can display the ACL2 User's Manual, which includes
documentation for the ACL2 system but not for the
[community-books]. But by default, ACL2-Doc will display the
ACL2+Books Manual, which includes documentation for those books as
well. To change which of these two manuals you display, just give a
prefix argument to the \"I\" command, as indicated above.
If you are using a git version of ACL2 and the books, between
releases, then you may need to download an extra file in order to
browse the ACL2+Books Manual. Most likely you will just answer y
when queried about downloading the file when first using ACL2-Doc.
If you want more details, see the last of the Notes below.
Notes
* You might find that when you attempt to follow [some-broken-link],
you find yourself at the [broken-link] topic. If you are using
the ACL2 User's Manual rather than the ACL2+Books Manual, the
reason might be that some-broken-link is documented in a book,
not in the ACL2 system. In that case, the broken-link page will
show you where to find that book; but if you want to read the
documentation for some-broken-link in the ACL2-Doc browser, you
can do so by switching to the ACL2+Books Manual. See the I
command, documented above.
* Files with names ending in .acl2-doc will come up in ACL2-Doc mode.
Thus, you may wish to save a file with that extension, for
example bookmarks.acl2-doc, that contains your favorite
bookmarks. You may wish to use the history command (H) to
obtain a list of names of visited topics, in order to create an
initial such file.
* Many commands offer defaults, and many offer completion. The default
is determined by cursor position: if the cursor is sitting on a
letter of a documentation topic name, or on a space character
immediately after it, then that name will be offered as the
default.
* Square brackets indicate documentation topic names, for example:
[acl2-doc]. The square brackets are really there, for example
when you are searching using \"s\", \"S\", or \"n\". However, for
purposes of determining the default name (see above), the only
effect of the enclosing square brackets is to extend the region
in which the default is offered. For example, consider the
string \"[acl2-doc]\": the default name of \"acl2-doc\" is offered
if the cursor is on either square bracket. But links have some
idiosyncrasies.
1. Topic names, including links `[..]' to topic names, are printed
relative to the ACL2 package. Especially in the case of the
ACL2+Books Manual, you may therefore see links that include
package prefixes. Here, for example, is a sentence from the
documentation for [gl] in the ACL2+Books Manual.
We call these structures [gl::symbolic-objects].
The \"gl\" package prefix allows commands to pick up
\"gl::symbolic-objects\" as the name to use as a default, so
that for example, hitting <Return> will take you to that
topic. But when reading the sentence, for best results you
should ignore package prefixes. So for example, you would
read the sentence above as follows.
We call these structures symbolic-objects.
2. Topic names that originally contained spaces now have underscores in
place of the spaces. So for example, the topic
[build::cert.pl] in the ACL2+Books Manual contains a link
to the topic originally named as follows.
1. Certifying Simple Books
This link shows up in the ACL2-Doc browser (and in output from the
:[doc] command at the terminal) as:
[1._Certifying_Simple_Books]. When you see a potential link
that does include whitespace, then it will not work,
probably because the original markup specified English text
that differs from the topic name. For example, consider the
following passage from the documentation for [gl].
GL requires ACL2(h) because it makes extensive use of
[hons-and-memoization]. Some optional parts of GL also require
[trust tags].
The first link will take you to the topic, [hons-and-memoization].
But the second link was actually written to be a link to
the documentation for [defttag]. The <Return> command will
not work on that second link; unfortunately, the
alternative is to use the g command and specify defttag in
the minibuffer.
Of course, the web-based browser avoids these idiosyncrasies (see
[xdoc::save]), hence may be more appropriate for those who have
no particular preference for using Emacs to browse the
documentation.
* Searching using the \"s\" or \"S\" command is carried out by searching
top-to-bottom in a hidden Emacs buffer that contains all of the
documentation. The topics are listed in the following order
according to topic name:
1. All topics whose names reside in the \"ACL2\" package;
2. All topics whose names reside in the \"ACL2-PC\" package; and, for the
ACL2+Books Manual,
3. All other topics, sorted by [symbol-name] and then by
[symbol-package-name].
* You may be queried, regarding whether you want to browse the
ACL2+Books Manual, which is preferred, or the ACL2 User's
Manual, which omits documentation for the books. Both of these
manuals are based on files that you will have if you are using
a released version of ACL2 (after Version 6.3). But if you are
using a {git version | https://github.com/acl2/acl2/}, then to
use the ACL2+Books Manual you will need an extra file. You can
build this file yourself, as described below but you may prefer
to download it: for example, when you start ACL2-Doc, you may
be given the option of downloading {a tarball for the latest
``bleeding edge'' copy |
http://www.cs.utexas.edu/users/moore/acl2/manuals/current/rendered-doc-combined.lsp.gz}
and extracting into directory system/doc/ of your community
books directory. Indeed, the system will do all this for you if
you answer y to that query. Alternatively, you can insist on a
download of a ``bleeding edge'' version by using the `D'
command. However, if you prefer to browse the ACL2 User's
Manual (without the books), you can put the following form into
your ~/.emacs file, above the form that loads the code for
ACL2-Doc (see above).
(defvar *acl2-doc-top-default* 'TOP)
If you prefer to build rendered-doc-combined.lsp yourself, you can
do so as follows.
1. Build ACL2:
make large
2. Build the manual, optionally supplying your \"make\" command with a
\"-j\" argument. If \"acl2\" invokes the ACL2 executable that
you just built, then you may omit \"ACL2=acl2\" below;
otherwise replace \"acl2\" by a suitable executable.
cd books
make all USE_QUICKLISP=1 ACL2_BOOK_CERTS=doc/top.cert ACL2=acl2
3. Build the file books/system/doc/rendered-doc-combined.lsp as follows,
still standing in the books directory, perhaps modifying
\"ACL2=acl2\" as discussed above.
cd books
make doc/top.cert USE_QUICKLISP=1 ACL2=acl2")
(ACL2-HELP
(ABOUT-ACL2)
"The acl2-help mailing list
You can email questions about ACL2 usage to the acl2-help mailing
list: acl2-help@utlists.utexas.edu. If you have more general
questions about ACL2, for example, about projects completed using
ACL2, you may prefer the acl2 mailing list,
acl2@utlists.utexas.edu, which tends to have wider distribution.")
(ACL2-NUMBER-LISTP
(NUMBERS LISTS ACL2-BUILT-INS)
"Recognizer for a true list of numbers
The predicate acl2-number-listp tests whether its argument is a true
list of numbers.
Function: <acl2-number-listp>
(defun acl2-number-listp (l)
(declare (xargs :guard t))
(cond ((atom l) (eq l nil))
(t (and (acl2-numberp (car l))
(acl2-number-listp (cdr l))))))")
(ACL2-NUMBERP
(NUMBERS ACL2-BUILT-INS)
"Recognizer for numbers
(acl2-numberp x) is true if and only if x is a number, i.e., a
rational or complex rational number.")
(ACL2-SEDAN
(ACL2-TUTORIAL)
"ACL2 Sedan interface
Many successful ACL2 users run in an shell under Emacs; see [emacs].
However, those not familiar with Emacs may prefer to start with an
Eclipse-based interface initiallly developed by Peter Dillinger and
Pete Manolios called the {ACL2 Sedan |
http://acl2s.ccs.neu.edu/acl2s/doc/} or ``ACL2s''.
ACL2 sessions in the ACL2 Sedan can utilize non-standard extensions
and enhancements, especially geared toward new users, termination
reasoning, and attaching rich user interfaces. These extensions are
{generally available |
http://acl2s.ccs.neu.edu/acl2s/src/acl2-extensions} as certifiable
ACL2 books. (Some code originating from this project has been
migrated to the ACL2 community books, but only after it was quite
stable.) Thanks to Peter Dillinger, Pete Manolios, Daron Vroon, and
Harsh Raju Chamarthi for their work on the ACL2 Sedan and for
making their books available to ACL2 users.")
(ACL2-TUTORIAL
(ACL2)
"Tutorial introduction to ACL2
To learn about ACL2, read at least the following two links.
* [Industrial Applications of ACL2] (10 minutes) to help you understand
what sophisticated users can do;
* [A Flying Tour] (10 minutes) to get an overview of the system and
what skills the user must have.
If you want to learn how to use ACL2, we recommend that you read a
selection of the materials referenced below, depending on your
learning style, and do suggested exercises.
* [A Walking Tour] (1 hour) provides an overview of the theorem prover.
* The {Try ACL2 | http://tryacl2.org} web site provides interactive
lessons to get you started using ACL2.
* See [introduction-to-the-theorem-prover] (10-40 hours) for
instruction on how to interact with the system. Unlike the
three documents above, this document expects you to think! It
cites the necessary background pages on programming in ACL2 and
on the logic and then instructs you in [the-method], which is
how expert users use ACL2. It concludes with some challenge
problems for the ACL2 beginner (including solutions) and an
FAQ. Most users will spend several hours a day for several days
working through this material.
* The book {Computer-Aided Reasoning: An Approach |
http://www.cs.utexas.edu/users/moore/publications/acl2-books/car/index.html}
is worth a careful read, as you work exercises and learn
[the-method].
* [Annotated ACL2 Scripts and Demos] contains relatively elementary
proof scripts that have been annotated to help train the
newcomer.
* Many files (``books'') in the ACL2 community books (see
[community-books]) are extensively annotated.
* An [Alternative Introduction] document, while largely subsumed by the
[Introduction to the Theorem Prover] mentioned above, still
might be useful because it covers much of the tutorial material
in a different way.
At this point you are probably ready to use ACL2 on your own small
projects. A common mistake for beginners is to browse the
documentation and then try to do something that is too big! Think
of a very small project and then simplify it!
Note that ACL2 has a very supportive user network. See the link to
``Mailing Lists'' on the {ACL2 home page |
http://www.cs.utexas.edu/users/moore/acl2}.
The topics listed below are a hodge podge, developed over time.
Although some of these are not mentioned above, you might find some
to be useful as well.
Subtopics
[ACL2-as-standalone-program]
Calling ACL2 from another program
[ACL2-sedan]
ACL2 Sedan interface
[Advanced-features]
Some advanced features of ACL2
[Alternative-introduction]
Introduction to ACL2
[Annotated-ACL2-scripts]
Examples of ACL2 scripts
[Emacs]
Emacs support for ACL2
[Interesting-applications]
Some industrial examples of ACL2 use
[Introduction-to-the-theorem-prover]
How the theorem prover works -- level 0
[Nqthm-to-ACL2]
ACL2 analogues of Nqthm functions and commands
[Pages_Written_Especially_for_the_Tours]
Pages Written Especially for the Tours
[Startup]
How to start using ACL2; the ACL2 [command] loop
[The-method]
How to find proofs
[Tidbits]
Some basic hints for using ACL2
[Tips]
Some hints for using the ACL2 prover")
(ACL2-USER
(PACKAGES)
"A package the ACL2 user may prefer
This package imports the standard Common Lisp symbols that ACL2
supports and also a few symbols from package \"ACL2\" that are
commonly used when interacting with ACL2. You may prefer to select
this as your current package so as to avoid colliding with ACL2
system names.
This package imports the symbols listed in
*common-lisp-symbols-from-main-lisp-package*, which contains
hundreds of CLTL function and macro names including those supported
by ACL2 such as [cons], [car], and [cdr]. It also imports the
symbols in *acl2-exports*, which contains a few symbols that are
frequently used while interacting with the ACL2 system, such as
[implies], [defthm], and [rewrite]. It imports nothing else.
Thus, names such as [alistp], [member-equal], and [type-set], which
are defined in the \"ACL2\" package are not present here. If you find
yourself frequently colliding with names that are defined in \"ACL2\"
you might consider selecting \"ACL2-USER\" as your current package
(see [in-package]). If you select \"ACL2-USER\" as the current
package, you may then simply type [member-equal] to refer to
acl2-user::member-equal, which you may define as you see fit. Of
course, should you desire to refer to the \"ACL2\" version of
[member-equal], you will have to use the \"ACL2::\" prefix, e.g.,
acl2::member-equal.
If, while using \"ACL2-USER\" as the current package, you find that
there are symbols from \"ACL2\" that you wish we had imported into it
(because they are frequently used in interaction), please bring
those symbols to our attention. For example, should
[union-theories] and [universal-theory] be imported? Except for
stabilizing on the ``frequently used'' names from \"ACL2\", we intend
never to define a symbol whose [symbol-package-name] is
\"ACL2-USER\".")
(ACL2P-KEY-CHECKPOINTS
(PARALLEL-PROOF)
"Key checkpoints in ACL2(p)
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
For printing output, the parallel version of the waterfall follows
the precedent of [gag-mode]. The idea behind gag mode is to print
only the subgoals most relevant to debugging a failed proof
attempt. These subgoals are called 'key checkpoints' (see
[set-gag-mode] for the definition of ``key'' and ``checkpoint''),
and we restrict the default output mode for the parallel version of
the waterfall to printing checkpoints similar to these key
checkpoints.
As of this writing, we are aware of exactly one discrepancy between
gag mode's key checkpoints and the parallel version of the
waterfall's checkpoints. This discrepancy occurs when using ``by''
hints (see [hints]). As an example, take the following form, which
attempts to prove a non-theorem:
(thm (equal (append x y z) (append z (append y x)))
:hints ((\"Subgoal *1/2'''\" :by nil)))
With waterfall parallelism enabled, Subgoal *1/2'' will be printed as
a key checkpoint. This is different from using [gag-mode] while
running the serial version of the waterfall, which skips printing
the subgoal as a checkpoint.
For those familiar with the ACL2 waterfall, we note that that the
parallel version of the waterfall prints key checkpoints that are
unproved in the following sense: a subgoal is a key checkpoint if
it leads, in the current call of the waterfall, to a goal that is
pushed for induction.")
(ACL2S (POINTERS) "See [ACL2-sedan].")
(ACL2_AS_AN_INTERACTIVE_THEOREM_PROVER
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"ACL2 as an Interactive Theorem Prover
The ACL2 theorem prover finds proofs in the ACL2 logic. It can be
automatic. But most often the user must help it.
{IMAGE}
The user usually guides ACL2 by suggesting that it first prove key
lemmas. Lemmas are just theorems used in the proofs of other
theorems.")
(ACL2_AS_AN_INTERACTIVE_THEOREM_PROVER_{CONT}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"ACL2 as an Interactive Theorem Prover (cont)
[{IMAGE}]
When ACL2 proves a lemma, it is converted into one or more rules and
stored in a database. The theorem prover is rule-driven. By proving
lemmas you can configure ACL2 to behave in certain ways when it is
trying to prove formulas in a certain problem domain. The expert
user can make ACL2 do amazingly ``smart'' looking things.
But it would be wrong to think that ACL2 knows the mathematical
content of a formula just because it has proved it. What ACL2 knows
--- all ACL2 knows --- is what is encoded in its rules. There are
many types of rules (see [rule-classes] [{ICON}]).
Many formulas can be effectively coded as rules. But by the same
token, it is possible to encode a formula as a rule that is so
ineffective it cannot even prove itself!
The way a formula is stored as a rule is entirely up to the user.
That is, you determine how ACL2 should use each formula that it
proves.
The most common kind of rule is the rewrite rule. It is so common
that if you don't tell ACL2 how to store a formula, it stores it as
a rewrite rule.
[{IMAGE}]")
(ACL2_CHARACTERS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"ACL2 Characters
ACL2 accepts 256 distinct characters, which are the characters
obtained by applying the function [code-char] [{ICON}] to each
integer from 0 to 255. Among these, Common Lisp designates certain
ones as *standard-characters*, namely those of the form (code-char
n) where n is from 33 to 126, together with #\\Newline and #\\Space.
The actual standard characters may be viewed by evaluating the
constant expression *standard-chars*.
The standard character constants are written by writing a hash mark
followed by a backslash (#\\) followed by the character.
The function [characterp] [{ICON}] recognizes characters. For more
details, See [characters] [{ICON}].")
(ACL2_CONSES_OR_ORDERED_PAIRS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"ACL2 Conses or Ordered Pairs
The function [cons] [{ICON}] creates an ordered pair. [Car] [{ICON}]
and [cdr] [{ICON}] return the first and second components,
respectively, of an ordered pair. The function [consp] [{ICON}]
recognizes ordered pairs.
Ordered pairs are used to represent lists and trees. See any Common
Lisp documentation for a discussion of how list constants are
written and for the many list processing functions available. Also,
see [programming] [{ICON}] where we list all the ACL2 primitive
functions.
Here are some examples of list constants to suggest their syntax.
'(a . b) ; a pair whose car is 'a and cdr is 'b
'(a . nil) ; a pair whose car is 'a and cdr is nil
'(a) ; another way to write the same thing
'(a b) ; a pair whose car is 'a and cdr is '(b)
'(a b c) ; a pair whose car is 'a and cdr is '(b c)
; i.e., a list of three symbols, a, b, and c.
'((a . 1) (b . 2)) ; a list of two pairs
It is useful to distinguish ``proper'' conses from ``improper'' ones,
the former being those cons trees whose right-most branch
terminates with nil. A ``true list'' (see [true-listp] [{ICON}]) is
either nil or a proper cons. (A b c . 7) is an improper cons and
hence not a true list.")
(ACL2_IS_AN_UNTYPED_LANGUAGE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"ACL2 is an Untyped Language
The example
ACL2 !>(app '(a b c) 27)
(A B C . 27)
illustrates the fact that ACL2's logic is untyped (click [here] for a
brief discussion of the typed versus untyped nature of the logic).
The definition of app makes no restriction of the arguments to lists.
The definition says that if the first argument satisfies [endp]
[{ICON}] then return the second argument. In this example, when app
has recursed three times down the cdr of its first argument, '(a b
c), it reaches the final nil, which satisfies endp, and so 27 is
returned. It is naturally consed into the emerging list as the
function returns from successive recursive calls (since cons does
not require its arguments to be lists, either). The result is an
``improper'' list, (a b c . 27).
You can think of (app x y) as building a binary tree by replacing the
right-most tip of the tree x with the tree y.")
(ACL2_STRINGS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"ACL2 Strings
Strings of ACL2 [characters] are written as sequences of characters
delimited by ``double quotation marks'' (\"). To put a double
quotation mark in a string (or, any other character such as
backslash or newline that seems to cause problems), escape it by
preceding it with a backslash (\\).
The function [stringp] [{ICON}] recognizes strings and [char]
[{ICON}] will fetch the nth character of a string. There are many
other primitives for handling strings, such as [string<] [{ICON}]
for comparing two strings lexicographically. We suggest you See
[programming] [{ICON}] where we list all of the primitive ACL2
functions. Alternatively, see any Common Lisp language
documentation.")
(ACL2_SYMBOLS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"ACL2 Symbols
Common Lisp's symbols are a data type representing words. They are
frequently regarded as atomic objects in the sense that they are
not frequently broken down into their constituents. Often the only
important properties of symbols is that they are not numbers,
characters, strings, or lists and that two symbols are not equal if
they look different (!). Examples of symbols include PLUS and
SMITH::ABC. All function and variable names in ACL2 are symbols.
When symbols are used as constants they must be quoted, as in
'PLUS.
The symbol T is commonly used as the Boolean ``true.'' The symbol NIL
is commonly used both as the Boolean ``false'' and as the ``empty
list.'' Despite sometimes being called the ``empty list'' NIL is a
symbol not an ``empty cons.'' Unlike other symbols, T and NIL may
be used as constants without quoting them.
Usually, symbols are written as sequences of alphanumeric characters
other than those denoting numbers. Thus, A12, +1A and 1+ are
symbols but +12 is a number. Roughly speaking, when symbols are
read lower case characters are converted to upper case, so we
frequently do not distinguish ABC from Abc or abc. Click [here] for
information about case conversion when symbols are read. However,
any character can be used in a symbol, but some characters must be
``escaped'' to allow the Lisp reader to parse the sequence as a
symbol. For example, |Abc| is a symbol whose first character is
capitalized and whose remaining characters are in lower case. |An
odd duck| is a symbol containing two #\\Space characters. See any
Common Lisp documentation for the syntactic rules for symbols.
Technically, a symbol is a special kind of pair consisting of a
package name (which is a string) and a symbol name (which is also a
string). (See [symbol-package-name] [{ICON}] and see [symbol-name]
[{ICON}].) The symbol SMITH::ABC is said to be in package \"SMITH\"
and to have the symbol name \"ABC\". The symbol ABC in package
\"SMITH\" is generally not equal to the symbol ABC in package
\"JONES\". However, it is possible to ``import'' symbols from one
package into another one, but in ACL2 this can only be done when
the package is created. (See [defpkg] [{ICON}].) If the
[current-package] [{ICON}] is \"SMITH\" then SMITH::ABC may be more
briefly written as just ABC. [Intern] [{ICON}] ``creates'' a symbol
of a given name in a given package.")
(ACL2_SYSTEM_ARCHITECTURE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"ACL2 System Architecture
[{IMAGE}]
{IMAGE}
The user interacts with the theorem prover by giving it definitions,
theorems and advice. Most often the advice is about how to store
each proved theorem as a rule. Sometimes the advice is about how to
prove a specific theorem.
The database consists of all the rules ACL2 ``knows.'' It is possible
to include in the database all of the rules in some certified file
of other events. Such certified files are called [books] [{ICON}].
Interesting proofs are usually built on top of many books, some of
which are written especially for that problem domain and others of
which are about oft-used domains, like arithmetic or list
processing. ACL2's distribution includes many books written by
users. See the ``books'' link under the Lemma Libraries and
Utilities [{ICON}] link of the ACL2 home page.
[{IMAGE}]")
(ACONS
(ALISTS ACL2-BUILT-INS)
"Constructor for association lists
(Acons key datum alist) equals the result of consing the pair (cons
key datum) to the front of the association list alist.
(Acons key datum alist) has a [guard] of (alistp alist). Acons is a
Common Lisp function. See any Common Lisp documentation for more
information.
Function: <acons>
(defun acons (key datum alist)
(declare (xargs :guard (alistp alist)))
(cons (cons key datum) alist))")
(ACTIVE-RUNEP
(THEORIES)
"Check that a [rune] exists and is [enable]d
Example:
(active-runep '(:rewrite left-to-right))
General Form:
(active-runep rune)
where rune has the shape of a [rune]. This macro expands to an
expression using the variables ens and state, and returns non-nil
when the given rune exists and is [enable]d (according to the given
``enabled structure,'' ens, and the current logical [world] of the
given [state]). See [theory-invariant] for how this macro can be of
use.")
(ADD-BINOP
(MACROS)
"Associate a function name with a macro name
The form (add-binop macro macro-fn) is an abbreviation for the form
(add-macro-fn macro macro-fn t). See [add-macro-fn].")
(ADD-CUSTOM-KEYWORD-HINT
(EVENTS)
"Add a new custom keyword hint
Examples:
(add-custom-keyword-hint :my-hint (my-hint-fn val ...))
(add-custom-keyword-hint :my-hint
(my-hint-fn val ...)
:checker (my-hint-checker-fn val ...))
General Form:
(add-custom-keyword-hint :key term1 :checker term2)
where :key is a [keywordp] not among the primitive keyword hints
listed in *hint-keywords*, the :checker argument is optional, and
term1 and (if supplied) term2 are terms with certain free-variable
and signature restrictions described below. Henceforth, :key is
treated as a custom keyword hint, e.g., the user can employ :key in
hints to [defthm], such as:
(defthm name ...
:hints ((\"Subgoal *1/1'\" ... :key val ...))).
Custom keyword hints are complicated. To use them you must understand
[state], multiple values (e.g., [mv] and [mv-let]), ACL2's notion
of error triples (see [programming-with-state]), how to generate
``soft'' errors with [er], how to use [fmt]-strings to control
output, how to use computed hints (see [computed-hints]) and some
aspects of ACL2's internal event processing. Furthermore, it is
possible to implement a custom keyword hint that can make an event
non-reproducible! So we recommend that these hints be developed by
ACL2 experts. Basically the custom keyword feature allows the
implementors and other experts to extend the hint facility without
modifying the ACL2 sources.
Term1 is called the ``generator'' term and term2 is called the
``checker'' term of the custom keyword hint :key. Together they
specify the semantics of the new custom keyword hint :key. Roughly
speaking, when a custom keyword hint is supplied by the user, as in
(defthm name ...
:hints ((\"Subgoal *1/1'\" ... :my-hint val ...))).
the checker term is evaluated on val to check that val is of the
expected shape. Provided val passes the check, the generator term
is used to compute a standard hint. Like computed hints, the
generator of a custom keyword hint is allowed to inspect the actual
clause on which it is being fired. Indeed, it is allowed to inspect
the entire list of hints (standard and custom) supplied for that
clause. Thus, in the most general case, a custom keyword hint is
just a very special kind of computed hint.
The generator, term1, must have no free variables other than:
(val keyword-alist
id clause world stable-under-simplificationp
hist pspv ctx state).
Moreover, either term1 must evaluate to a single non-[stobj] value,
or else it must be single-threaded in state and have the standard
[error-triple] output signature, (mv * * state).
The restrictions on the checker, term2, are that it be
single-threaded in state, have the standard [error-triple] output
signature, (mv * * state), and have no free variables other than:
(val world ctx state).
For examples, see the community books directory books/hints/, in
particular basic-tests.lisp.
To delete a previously added custom keyword hint, see
[remove-custom-keyword-hint].
The community book hints/merge-hint.lisp can be useful in writing
custom keyword hints. See the examples near the of the file.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.")
(ADD-DEFAULT-HINTS
(DEFAULT-HINTS)
"Add to the default hints
Examples:
(add-default-hints '((computed-hint-1 clause)
(computed-hint-2 clause
stable-under-simplificationp)))
(add-default-hints '((computed-hint-3 id clause world))
:at-end t)
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It is [local] to the book or [encapsulate] form in which it occurs
(see [add-default-hints!] for a corresponding non-[local] event).
General Forms:
(add-default-hints lst)
(add-default-hints lst :at-end flg)
where lst is a list. Generally speaking, the elements of lst should
be suitable for use as [computed-hints].
This event is completely analogous to [set-default-hints], the
difference being that add-default-hints appends the indicated hints
to the front of the list of default hints, so that they are tried
first --- or, if flg is supplied and evaluates to other than nil,
at the end of the list, so that they are tried last --- rather than
replacing the default hints with the indicated hints. Each new hint
is thus considered after each existing hints when both are applied
to the same goal. Also See [set-default-hints], see
[remove-default-hints], and see [default-hints].
Finally, note that the effects of set-default-hints,
[add-default-hints], and [remove-default-hints] are [local] to the
book in which they appear. Thus, users who include a book with such
forms will not have their default hints affected by such forms. In
order to export the effect of setting the default hints, use
[set-default-hints!], [add-default-hints!], or
[remove-default-hints!].
For a related feature, which however is only for advanced system
builders, see [override-hints].")
(ADD-DEFAULT-HINTS!
(DEFAULT-HINTS)
"Add to the default hints non-[local]ly
Please see [add-default-hints], which is the same as
add-default-hints! except that the latter is not [local] to the
[encapsulate] or the book in which it occurs. Probably
[add-default-hints] is to be preferred unless you have a good
reason for wanting to export the effect of this event outside the
enclosing [encapsulate] or book.")
(ADD-DIVE-INTO-MACRO
(DIVE-INTO-MACROS-TABLE)
"Associate [proof-checker] diving function with macro name
Examples:
(add-dive-into-macro cat expand-address-cat)
This feature is used so that the [proof-checker]'s DV command and
numeric diving commands (e.g., 3) will dive properly into subterms.
Please see [dive-into-macros-table].")
(ADD-INCLUDE-BOOK-DIR
(BOOKS-REFERENCE)
"Link keyword for :dir argument of [ld] and [include-book]
Example Forms:
; For (include-book \"foo\" :dir :smith), prepend \"/u/smith/\" to \"foo\".
(add-include-book-dir :smith \"/u/smith/\")
; For (include-book \"bar\" :dir :util), prepend absolute directory pathname
; corresponding to the relative pathname, \"utilities/\".
(add-include-book-dir :util \"utilities\")
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It is [local] to the book or [encapsulate] form in which it occurs.
See [add-include-book-dir!] for a corresponding non-[local] event.
General Form:
(add-include-book-dir kwd dir)
where kwd is a [keywordp] and dir is a relative or absolute
[pathname] for a directory, optionally using the syntax (:system .
filename) described in [full-book-name]. If the final '/' is
missing for the resulting directory, ACL2 will add it for you. The
effect of this event is to modify the meaning of the :dir keyword
argument of [include-book] or [ld] as indicated by the examples
above, that is, by associating the indicated directory with the
indicated keyword for purposes of the :dir argument. By the
``indicated directory'' we mean, in the case that the pathname is a
relative pathname, the directory relative to the current connected
book directory; see [cbd]. See [delete-include-book-dir] for how to
undo this effect.
For a keyword already associated with a directory string by a
previous invocation of add-include-book-dir or
[add-include-book-dir!], it is illegal to associate a different
directory string until removing the existing association; see
[delete-include-book-dir] (and see [delete-include-book-dir!] if
the existing association was made by [add-include-book-dir!]. If
however the new directory string is identical with the existing
one, which was already assigned by add-include-book-dir, then the
new call of add-include-book-dir will be redundant (see
[redundant-events]).
The keyword :system can never be redefined. It will always point to
the absolute pathname of the system books directory, which by
default is immediately under the directory where the ACL2
executable was originally built (see [include-book], in particular
the discussion there of ``books directory'').
This macro generates a [table] event that updates the table
include-book-dir!-table, which associates keywords with absolute
pathnames. However, as with [add-include-book-dir], direct table
updates are disallowed; you must use add-include-book-dir! to add
to the table and [delete-include-book-dir!] to remove from the
table.
It is illegal to call add-include-book-dir! in a [local] context. (If
you are tempted to do that, consider using [add-include-book-dir]
instead.) To understand this restriction, imagine a book that
contains the following sequence of [events].
(add-include-book-dir! :my-dir \"path/to/BAD/dir\")
(local (delete-include-book-dir! :my-dir))
(local (add-include-book-dir! :my-dir \"path/to/GOOD/dir\"))
(include-book \"foo\" :dir :my-dir)
(defthm f-def
(equal (f x) x))
During the first (proof) pass of [certify-book], the book
path/to/GOOD/dir/foo.lisp will be included. But on the second pass,
the book path/to/BAD/dir/foo.lisp will be included. Now imagine
that the ``good'' version contains the event (defun f (x) x) but
the ``bad'' version instead contains the event (defun f (x) (not
x)). Then we can easily prove nil from the theorem f-def! Although
it is likely that checksums will catch this error at [include-book]
time, we prefer not to rely on checksums for soundness.")
(ADD-INCLUDE-BOOK-DIR!
(BOOKS-REFERENCE)
"Non-[local]ly link keyword for :dir argument of [ld] and
[include-book]
Please see [add-include-book-dir], which has completely analogous
syntax and semantics, except that add-include-book-dir! is not
[local] to the [encapsulate] or the book in which it occurs.
Probably [add-include-book-dir] is to be preferred unless you have
a good reason for wanting to export the effect of this event
outside the enclosing [encapsulate] or book.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
This macro is essentially a [table] event that updates the table
include-book-dir!-table, which associates keywords with absolute
pathnames. However, as with [add-include-book-dir], direct table
updates are disallowed; you must use add-include-book-dir! to add
to the table and [delete-include-book-dir!] to remove from the
table.
It is illegal to call add-include-book-dir! in a [local] context. (If
you are tempted to do that, consider using [add-include-book-dir]
instead.) To understand this restriction, imagine a book that
contains the following sequence of [events].
(add-include-book-dir! :my-dir \"path/to/BAD/dir\")
(local (delete-include-book-dir! :my-dir))
(local (add-include-book-dir! :my-dir \"path/to/GOOD/dir\"))
(include-book \"foo\" :dir :my-dir)
(defthm f-def
(equal (f x) x))
During the first (proof) pass of [certify-book], the book
path/to/GOOD/dir/foo.lisp will be included. But on the second pass,
the book path/to/BAD/dir/foo.lisp will be included. Now imagine
that the ``good'' version contains the event (defun f (x) x) but
the ``bad'' version instead contains the event (defun f (x) (not
x)). Then we can easily prove nil from the theorem f-def! Although
it is likely that checksums will catch this error at [include-book]
time, we prefer not to rely on checksums for soundness.")
(ADD-INVISIBLE-FNS
(LOOP-STOPPER)
"Make some unary functions invisible to the [loop-stopper] algorithm
Examples:
(add-invisible-fns binary-+ unary-- foo)
(add-invisible-fns + unary-- foo)
Each of the [events] above makes unary functions [unary--] and foo
``invisible'' for the purposes of applying permutative :[rewrite]
rules to [binary-+] trees. Thus, arg and (unary-- arg) will be
given the same weight and will be permuted so as to be adjacent.
General Form:
(add-invisible-fns top-fn unary-fn1 ... unary-fnk)
where top-fn is a function symbol and the unary-fni are unary
function symbols, or more generally, these are all macro aliases
for function symbols (see [macro-aliases-table]).
For more information see [invisible-fns-table]. Also see
[set-invisible-fns-table], which explains how to set the entire
table in a single event, and see [remove-invisible-fns].")
(ADD-LD-KEYWORD-ALIAS (POINTERS)
"See [ld-keyword-aliases].")
(ADD-LD-KEYWORD-ALIAS! (POINTERS)
"See [ld-keyword-aliases].")
(ADD-MACRO-ALIAS
(MACROS)
"Associate a function name with a macro name
Example:
(add-macro-alias append binary-append)
This example associates the function symbol [binary-append] with the
macro name [append]. As a result, the name [append] may be used as
a runic designator (see [theories]) by the various theory
functions. See [macro-aliases-table] for more details. Also see
[add-macro-fn] for an extension of this utility that also affects
printing.
General Form:
(add-macro-alias macro-name function-name)
This is a convenient way to add an entry to [macro-aliases-table].
See [macro-aliases-table] and also see [remove-macro-alias].")
(ADD-MACRO-FN
(MACROS)
"Associate a function name with a macro name
Examples:
(add-macro-fn append binary-append)
(add-macro-fn append binary-append t)
These examples each associate the function symbol [binary-append]
with the macro name [append]. As a result, theory functions will
understand that append refers to binary-append --- see
[add-macro-alias] --- and moreover, proof output will be printed
using append rather than binary-append. In the first case, (append
x (append y z)) is printed rather than (append x y z). In the
second case, right-associated arguments are printed flat: (append x
y z). Such right-association is considered only for binary function
symbols; otherwise the optional third argument is ignored.
General Forms:
(add-macro-fn macro-name function-name)
(add-macro-fn macro-name function-name nil) ; same as above
(add-macro-fn macro-name function-name t)
This is a convenient way to add an entry to [macro-aliases-table] and
at the same time extend the [untrans-table]. As suggested by the
example above, calls of a function in this table will be printed as
corresponding calls of macros, with right-associated arguments
printed flat in the case of a binary function symbol if the
optional third argument is t. In that case, for a binary function
symbol fn associated with macro name mac, then a call (fn arg1 (fn
arg2 (... (fn argk arg)))) will be displayed to the user as though
the ``term'' were (mac arg1 arg2 ... argk arg). For a call (f a1
... ak) of a function symbol that is not binary, or the optional
argument is not supplied as t, then the effect is simply to replace
f by the corresponding macro symbol. See [add-macro-alias], which
is invoked on the first two arguments. Also see
[remove-macro-alias], see [untrans-table], and see
[remove-macro-fn].")
(ADD-MATCH-FREE-OVERRIDE
(FREE-VARIABLES)
"Set :match-free value to :once or :all in existing rules
Example Forms:
(add-match-free-override :once t)
; Try only the first binding of free variables when relieving hypotheses
; of any rule of class :rewrite, :linear, or :forward-chaining.
(add-match-free-override :all (:rewrite foo) (:rewrite bar))
; For rewrite rules foo and bar, try all bindings of free variables when
; relieving hypotheses.
(add-match-free-override :clear)
; Restore :match-free to what was originally stored for each rule (either
; :all or :once).
As described elsewhere (see [free-variables]), a [rewrite], [linear],
or [forward-chaining] rule may have free variables in its
hypotheses, and ACL2 can be directed either to try all bindings
(``:all'') or just the first (``:once'') when relieving a
hypothesis, as a basis for relieving subsequent hypotheses. This
direction is generally provided by specifying either :match-free
:once or :match-free :all in the :[rule-classes] of the rule, or by
using the most recent [set-match-free-default] event. Also see
[rule-classes].
However, if a proof is going slowly, you may want to modify the
behavior of some such rules so that they use only the first match
for free variables in a hypothesis when relieving subsequent
hypotheses, rather than backtracking and trying additional matches
as necessary. (But note: add-match-free-override is not relevant
for [type-prescription] rules.) The event (add-match-free-override
:once t) has that effect. Or at the other extreme, perhaps you want
to specify all rules as :all rules except for a some specific
exceptions. Then you can execute (add-match-free-override :all t)
followed by, say, (add-match-free-override :once (:rewrite foo)
(:linear bar)).
General Forms:
(add-match-free-override :clear)
(add-match-free-override flg t)
(add-match-free-override flg rune1 rune2 ... runek)
where flg is :once or :all and the runei are [rune]s. If :clear is
specified then all rules will have the :all/:once behavior from
when they were first stored. The second general form causes all
[rewrite] [linear], and [forward-chaining] rules to have the
behavior specified by flg (:all or :once). Finally, the last of
these, where runes are specified, is additive in the sense that
only the indicated rules are affected; all others keep the behavior
they had just before this event was executed (possible because of
earlier add-match-free-override events).
At the conclusion of this event, ACL2 prints out the list of all
:[linear], :[rewrite], and :[forward-chaining] runes whose rules
contain free variables in hypotheses that are to be bound :once,
except that if there are no overrides (value :clear was used), then
:clear is printed.
This event only affects rules that exist at the time it is executed.
Future rules are not affected by the override.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It uses the [ACL2-defaults-table], and hence its effect is [local]
to the book or [encapsulate] form in which it occurs.
Remarks
Lists of the :[rewrite], :[linear], and :[forward-chaining] [rune]s
whose behavior was originally :once or :all are returned by the
following forms, respectively.
(free-var-runes :once (w state))
(free-var-runes :all (w state))
The form
(match-free-override (w state))
evaluates to a pair, whose [car] is a number used by ACL2 to
determine whether a [rune] is sufficiently old to be affected by
the override, and whose [cdr] is the list of [rune]s whose behavior
is specified as :once by add-match-free-override; except, if no
runes have been overridden, then the keyword :clear is returned.")
(ADD-NTH-ALIAS
(NTH-ALIASES-TABLE)
"Associate one symbol with another for printing of [nth]/[update-nth]
terms
Example:
(add-nth-alias st0 st)
This example associates the symbol st0 with the symbol st for
purposes of printing certain terms of the form (nth n st0) and
(update-nth n val st0).
General Form:
(add-nth-alias alias-name name)
This is a convenient way to add an entry to [nth-aliases-table]. See
[nth-aliases-table] and also see [remove-nth-alias].")
(ADD-OVERRIDE-HINTS
(OVERRIDE-HINTS)
"Add to the [override-hints]
See [override-hints] for a discussion of override-hints. Here we
describe how to extend the list of override-hints. Note that the
effects of add-override-hints [events] are [local] to the [books]
or encapsulate [events] in which they reside; see
[add-override-hints!] to avoid that restriction. Also see
[set-override-hints] to set a new list of override-hints to it,
ignoring the present list rather than adding to it.
General Forms:
(add-override-hints form)
(add-override-hints form :at-end t)
(add-override-hints form :at-end nil) ; default for :at-end
where form evaluates to a list of computed hint forms. The effect of
this event is to extend the current list of [override-hints] by
appending the result of that evaluation. The default is to append
the evaluation result to the front of the current list of
override-hints, but if :at-end t is specified, then the evaluation
result is appended to the end of the current list.")
(ADD-OVERRIDE-HINTS!
(OVERRIDE-HINTS)
"Add non-[local]ly to the [override-hints]
Add-override-hints! is the same as [add-override-hints], except that
the former is not [local] to [books] or [encapsulate] [events] in
which it occurs. See [add-override-hints]; also see
[set-override-hints].")
(ADD-RAW-ARITY
(SET-RAW-MODE)
"Add arity information for raw mode
Technical note: This macro is a no-op, and is not necessary, when
ACL2 is built with #-acl2-mv-as-values.
Users of raw mode (see [set-raw-mode]) can use arbitrary raw Lisp
functions that are not known inside the usual ACL2 loop. In such
cases, ACL2 may not know how to display a multiple value returned
by ACL2's [mv] macro. The following example should make this clear.
ACL2 P>(defun foo (x y) (mv y x))
FOO
ACL2 P>(foo 3 4)
Note: Unable to compute number of values returned by this evaluation
because function FOO is not known in the ACL2 logical world. Presumably
it was defined in raw Lisp or in raw mode. Returning the first (perhaps
only) value for calls of FOO.
4
ACL2 P>(add-raw-arity foo 2)
RAW-ARITY-ALIST
ACL2 P>(foo 3 4)
(4 3)
ACL2 P>
The first argument of add-raw-arity should be a symbol, representing
the name of a function, macro, or special form, and the second
argument should either be a non-negative integer (denoting the
number of values returned by ACL2) or else the symbol :LAST,
meaning that the number of values returned by the call is the
number of values returned by the last argument.
The current arity assignments can be seen by evaluating (@
raw-arity-alist). See [remove-raw-arity] for how to undo a call of
add-raw-arity.")
(ADD-TO-SET
(LISTS SYMBOLS ACL2-BUILT-INS)
"Add a symbol to a list
General Forms:
(add-to-set x lst)
(add-to-set x lst :test 'eql) ; same as above (eql as equality test)
(add-to-set x lst :test 'eq) ; same, but eq is equality test
(add-to-set x lst :test 'equal) ; same, but equal is equality test
For a symbol x and an object lst, (add-to-set-eq x lst) is the result
of [cons]ing x on to the front of lst, unless x is already a
[member] of lst, in which case the result is lst. The optional
keyword, :TEST, has no effect logically, but provides the test
(default [eql]) used for comparing x with successive elements of
lst.
The [guard] for a call of add-to-set depends on the test. In all
cases, the second argument must satisfy [true-listp]. If the test
is [eql], then either the first argument must be suitable for [eql]
(see [eqlablep]) or the second argument must satisfy
[eqlable-listp]. If the test is [eq], then either the first
argument must be a symbol or the second argument must satisfy
[symbol-listp].
See [equality-variants] for a discussion of the relation between
add-to-set and its variants:
(add-to-set-eq x lst) is equivalent to (add-to-set x lst :test 'eq);
(add-to-set-equal x lst) is equivalent to (add-to-set x lst :test
'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function add-to-set-equal.")
(ADD-TO-SET-EQ (POINTERS)
"See [add-to-set].")
(ADD-TO-SET-EQL (POINTERS)
"See [add-to-set].")
(ADD-TO-SET-EQUAL (POINTERS)
"See [add-to-set].")
(ADVANCED-FEATURES
(ACL2-TUTORIAL)
"Some advanced features of ACL2
Maybe you've been using ACL2 for awhile, and you wonder if there are
lesser-known features that you might find useful. Then this topic
is for you. We present below a ``laundry list'' of some such
features, with brief descriptions and links to [documentation]
topics.
Although the list below is long, it is not intended to be complete,
and indeed some topics have been deliberately excluded. Some have
fallen out of use, perhaps for good reason, such as [obdd]. Others
are already likely to be discovered when needed, such as [getenv$]
and perhaps [double-rewrite]. Some topics are referenced by
documentation for others in the list, such as [mbt], which is
referenced by [mbe]. Some utilities such as [pstack] and
[verbose-pstack] seem too low-level to be worthy of inclusion
below.
For an extensive introduction to using the prover, which may include
some aspects new to you, see [introduction-to-the-theorem-prover].
A shorter topic contains highlights for efficient prover usage: see
[tips]. Also see [ACL2-sedan] for an extension of ACL2 (written by
others), ACL2s, that includes an Eclipse-based interface, more
powerful and automatic termination reasoning, and other features.
We now move on to the list.
Top-level commands and utilities:
* See [a!] and see [p!] to abort or pop.
* See [ACL2-customization] for initial commands to run at startup.
* See [keyword-commands] for how keyword commands are processed.
* See [ld] for many ways to control the top-level loop.
* See [compilation] for a discussion of set-compiler-enabled and other
compiler-related utilities.
* For useful reader macros `#!', `#.', and `#u', see
[sharp-bang-reader], see [sharp-dot-reader], and see
[sharp-u-reader].
* To save and use an ACL2 executable, see [ACL2-as-standalone-program]
and see [save-exec].
* For utilities related to timing, see [time$], see
[with-prover-time-limit], see [with-prover-step-limit], and see
[set-prover-step-limit].
* To query and manage the database, see [history] (which discusses many
useful utilities, such as :[pbt] and :[pl]), and see
[dead-events].
* See [add-include-book-dir] for linking keyword for :dir argument of
[ld] and [include-book].
* See [rebuild] for a fast way to load a file without waiting for
proofs.
* For parallel certification, see [books-certification] for use of the
-j option of `make'; also see [provisional-certification].
Some relatively less common events
* See [reset-prehistory] to reset the prehistory.
* See [assert-event] to assert that a given form returns a non-nil
value.
* See [defattach] to execute constrained functions using corresponding
attached functions.
* See [defun-sk] to define a function whose body has an outermost
quantifier.
* See [defchoose] to define a Skolem (witnessing) function.
* For efficiency consider using defconst-fast; see [defconst].
* See [set-verify-guards-eagerness] to specify when [guard]
verification is tried by default.
Output and its control (see [io] for additional information)
* See [with-output] to suppress or turn on specified output for an
event.
* See [evisc-table] for support for abbreviated output.
* See [nth-aliases-table] for a table used to associate names for
[nth]/[update-nth] printing.
* See [output-to-file] to redirect output to a file.
* See [print-control] to control ACL2 printing.
* See [set-evisc-tuple] to control suppression of details when
printing.
* See [set-inhibit-output-lst] to control output by type.
* See [set-iprint] to allow abbreviated output to be read back in.
* See [set-print-base-radix] (also [set-print-base] and
[set-print-radix]) to control the radix in which numbers are
printed.
* See [set-print-case] to control whether symbols are printed in upper
case or in lower case.
On proving termination for definitions:
* See [ordinals] for a discussion of ordinals in ACL2.
* See [ruler-extenders] for a control on ACL2's termination and
induction analyses.
* See [set-well-founded-relation] to set the default well-founded
relation for termination analysis.
* See [ACL2-sedan] for a related tool that provides extra automation
for termination proofs.
Proof debugging and output control:
* See [accumulated-persistence] to get statistics on which runes are
being tried.
* See [add-macro-fn] and see [add-macro-alias] to associate a function
name with a macro name.
* See [break-rewrite] for how to monitor rewrite rules.
* See [dmr] for dynamic monitoring of rewriting and other prover
activity.
* See [forward-chaining-reports] to see reports about the forward
chaining process.
* See [guard-debug] and [measure-debug] to generate markers to indicate
sources of [guard] and termination proof obligations.
* See [proof-checker] for support for low-level interaction.
* See [redo-flat] for redo on failure of a [progn], [encapsulate], or
[certify-book].
* See [set-gag-mode] and see [pso] to abbreviate or restore proof
output.
* See [set-inhibit-output-lst], see [set-inhibit-warnings], and see
[set-inhibited-summary-types] to inhibit various types of
output.
* See [set-raw-proof-format] to make proof output display lists of
[rune]s.
* See [set-raw-warning-format] to make some warnings display in a
``raw'' s-expression format.
* See [skip-proofs] to skip proofs for a given form.
Program debugging:
* See [break$] to cause an immediate Lisp break.
* See [break-on-error] to break when encountering a hard or soft error
caused by ACL2.
* See [disassemble$] to disassemble a function.
* See [print-gv] to print a form whose evaluation caused a guard
violation.
* See [profile] to turn on profiling for one function.
* See [trace$] and see [open-trace-file] to [trace] function
evaluations, possibly sending trace output to a file.
* See [wet] to evaluate a form and print a subsequent error trace.
Programming and evaluation idioms, support, utilities
(also see [programming] for more utilities, e.g., [random$]).
* See [arrays] and See [defstobj] for introductions to ACL2 arrays and
single-threaded objects (stobjs), respectively, each of which
provides efficient destructive operations in an applicative
setting. Also see [with-local-stobj] for a way to create local
stobjs.
* See [assert$] to cause a hard error if the given test is false.
* See [canonical-pathname] to obtain the true absolute filename, with
soft links resolved.
* See [case-match] for a utility providing pattern matching and
destructuring.
* See [defpun] to define a tail-recursive function symbol.
* See [ec-call] to execute a call in the ACL2 logic instead of raw
Lisp.
* See [er] to print an error message and ``cause an error''.
* See [flet] to provide local binding of function symbols.
* See [gc$] to invoke the garbage collector.
* See [mbe] to attach code for execution.
* See [mv-list] to convert a multiple-valued result to a single-valued
list.
* See [mv?] to return one or more values.
* For non-executable code, see [defun-nx] and see [non-exec].
* See [prog2$] and see [progn$] to execute two or more forms and return
the value of the last one.
* See [programming-with-state] for how to program using the von
Neumannesque ACL2 [state] object.
* See [top-level] to evaluate a top-level form as a function body.
* See [with-guard-checking] to suppress or enable guard-checking for a
form.
* For ways to fake access to the state see [wormhole], see
[with-local-state], see [cw], see [cw!], see
[printing-to-strings], see [observation-cw], and (dangerous!)
see [with-live-state].
Connecting with the underlying host Lisp, and doing other evil:
* See [defttag] to introduce a trust tag (ttag).
* See [defmacro-last] to define a macro that returns its last argument,
but with side effects.
* See [progn!] to evaluate forms that are not necessarily [events].
* See [return-last] to return the last argument, perhaps with side
effects.
* See [set-raw-mode] to enter or exit ``raw mode,'' a raw Lisp
environment.
* See [sys-call] and [sys-call+] to make a system call to the host
operating system.
Macros and related utilities:
* See [defabbrev] for a convenient form of macro definition for simple
expansions.
* See [macro-args] for the formals list of a macro definition (see
[defmacro]).
* See [make-event] for a sort of extension of [defmacro] that allows
access to the [state], by evaluating (expanding) a given form
and then evaluate the result of that expansion.
* See [trans], see [trans!], and see [trans1] to print the
macroexpansion of a form.
Additional capabilities:
* See [hons-and-memoization] for a discussion of the [hons-enabled]
features providing hash cons, function memoization, and
applicative hash tables. In particular, see [memoize] for
efficient function memoization and see [profile] for profiling.
* See [real] for ACL2(r), which supports the real numbers.
* See [parallelism] for ACL2(p), which supports parallel evaluation and
proof.
Database control and query:
* See [disabledp] to determine whether a given name or rune is
disabled.
* For redefinition support see [redef], see [redef!], see [redef+], see
[redef-], and see [redefined-names].
* See [table] for user-managed tables.
* See [verify-guards-formula] to view a guard proof obligation without
doing the proof.
Prover control
* For congruence-based reasoning see [defcong], see [congruence], see
[equivalence], see [defequiv], and see [defrefinement].
* For meta rules and clause processors see [meta], see [defevaluator],
see [clause-processor], see [define-trusted-clause-processor]
(for connecting with external tools, such as SAT solvers), and
See [extended-metafunctions] (for [state] and context-sensitive
metafunctions).
* For theory control, see [theories] for detailed information, but in
particular see [deftheory], see [theory-functions], see
[in-arithmetic-theory] (and see [non-linear-arithmetic]), and
see [theory-invariant].
* See [hints] for a complete list of prover hints, including some of
the more obscure ones such as :restrict, :[clause-processor],
:nonlinearp, :backchain-limit-rw, :reorder, and :backtrack.
Also see [hints-and-the-waterfall] for an explanation of how
hints interact with the ACL2 proof process. For other topics
related to hints, see [override-hints], see
[add-custom-keyword-hint], see [default-hints], and see
[computed-hints] and [using-computed-hints].
* See [bind-free] to bind [free-variables] of a [rewrite] or [linear]
rule.
* See [case-split] for a utility like [force] that immediately splits
the top-level goal on the indicated hypothesis.
* See [case-split-limitations] for a way to the number of cases
produced at once
* See [default-backchain-limit] to specify the backchain limit for a
rule.
* See [force] for an identity function used to force a hypothesis.
* See [otf-flg] for a way to push more than one initial subgoal for
induction.
* See [rule-classes] to add various kinds of rules to the database,
including more unusual sorts such as :[built-in-clause] rules
and :[induction] rules.
* See [set-backchain-limit] to set the backchain-limit used by the
type-set and rewriting mechanisms.
* See [set-body] to set an alternate definition body for :expand
[hints].
* See [set-rewrite-stack-limit] to set the [rewrite] stack depth used
by the rewriter.
* See [syntaxp] to attach a heuristic filter on a :[rewrite], :[meta],
or :[linear] rule.
Subtopics
[Program-wrapper]
Avoiding expensive guard checks using [program]-mode functions
[Set-check-invariant-risk]
Potential slowdown for [program]-mode updates to [stobj]s or
[arrays]
[Set-duplicate-keys-action]
Control action for macro calls with duplicate keyword arguments")
(ALISTP
(ALISTS ACL2-BUILT-INS)
"Recognizer for association lists
(alistp x) is true if and only if x is a list of [cons] pairs.
(alistp x) has a [guard] of t.
Function: <alistp>
(defun alistp (l)
(declare (xargs :guard t))
(cond ((atom l) (eq l nil))
(t (and (consp (car l))
(alistp (cdr l))))))")
(ALISTS
(PROGRAMMING)
"Operations on association lists, which bind keys to values.
Subtopics
[Acons]
Constructor for association lists
[Alistp]
Recognizer for association lists
[Assoc]
Look up key in association list
[Assoc-string-equal]
Look up key, a string, in association list
[Character-alistp]
Recognizer for association lists with characters as keys
[Delete-assoc]
Remove the first pair from an association list for a given key
[Eqlable-alistp]
Recognizer for a true list of pairs whose [car]s are suitable for
[eql]
[Fast-alists]
Alists with hidden hash tables for faster execution
[Pairlis]
See [pairlis$]
[Pairlis$]
Zipper together two lists
[Put-assoc]
Modify an association list by associating a value with a key
[R-eqlable-alistp]
Recognizer for a true list of pairs whose [cdr]s are suitable for
[eql]
[R-symbol-alistp]
Recognizer for association lists with symbols as values
[Rassoc]
Look up value in association list
[Standard-string-alistp]
Recognizer for association lists with standard strings as keys
[Strip-cars]
Collect up all first components of pairs in a list
[Strip-cdrs]
Collect up all second components of pairs in a list
[Sublis]
Substitute an alist into a tree
[Symbol-alistp]
Recognizer for association lists with symbols as keys")
(ALLOCATE-FIXNUM-RANGE
(NUMBERS ACL2-BUILT-INS)
"Set aside fixnums in GCL
(Allocate-fixnum-range fixnum-lo fixnum-hi) causes Gnu Common Lisp
(GCL) to create a persistent table for the integers between
fixnum-lo and fixnum-hi (both bounds inclusive). This table is
referenced first when any integer is boxed and the existing box in
the table is used if the integer is in bounds. This can speed up
GCL considerably by avoiding wasteful fixnum boxing. Here,
fixnum-lo and fixnum-hi should be fixnums. On 32-bit machines it
would be good for them to be of type (signed-byte 30), with
fixnum-lo <= fixnum-hi.
When this function is executed in a Lisp implementation other than
GCL, it has no side effect. This function always returns nil.")
(ALPHA-CHAR-P
(CHARACTERS ACL2-BUILT-INS)
"Recognizer for alphabetic characters
(Alpha-char-p x) is true for a standard character x if and only if x
is alphabetic, i.e., one of the [characters] #\\a, #\\b, ..., #\\z,
#\\A, #\\B, ..., #\\Z.
The [guard] for alpha-char-p requires its argument to be a standard
character (see [standard-char-p]).
Alpha-char-p is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <alpha-char-p>
(defun alpha-char-p (x)
(declare (xargs :guard (and (characterp x)
(standard-char-p x))))
(and (member x
'(#\\a #\\b #\\c
#\\d #\\e #\\f #\\g #\\h #\\i #\\j #\\k #\\l #\\m
#\\n #\\o #\\p #\\q #\\r #\\s #\\t #\\u #\\v #\\w
#\\x #\\y #\\z #\\A #\\B #\\C #\\D #\\E #\\F #\\G
#\\H #\\I #\\J #\\K #\\L #\\M #\\N #\\O #\\P #\\Q
#\\R #\\S #\\T #\\U #\\V #\\W #\\X #\\Y #\\Z))
t))")
(ALPHORDER
(<< ACL2-BUILT-INS)
"Total order on atoms
Alphorder is a non-strict total order, a ``less than or equal,'' on
atoms. By ``non-strict total order'' we mean a function that always
returns t or nil and satisfies the following properties.
* Antisymmetry: XrY & YrX -> X=Y
* Transitivity: XrY & YrZ -> XrZ
* Trichotomy: XrY v YrX
Also see [lexorder], which extends alphorder to all objects.
(Alphorder x y) has a guard of (and (atom x) (atom y)).
Within a single type: rationals are compared arithmetically, complex
rationals are compared lexicographically, characters are compared
via their char-codes, and strings and symbols are compared with
alphabetic ordering. Across types, rationals come before complexes,
complexes come before characters, characters before strings, and
strings before symbols. We also allow for ``bad atoms,'' i.e.,
atoms that are not legal Lisp objects but make sense in the ACL2
logic; these come at the end, after symbols.
Function: <alphorder>
(defun alphorder (x y)
(declare (xargs :guard (and (atom x) (atom y))))
(cond ((real/rationalp x)
(cond ((real/rationalp y) (<= x y))
(t t)))
((real/rationalp y) nil)
((complex/complex-rationalp x)
(cond ((complex/complex-rationalp y)
(or (< (realpart x) (realpart y))
(and (= (realpart x) (realpart y))
(<= (imagpart x) (imagpart y)))))
(t t)))
((complex/complex-rationalp y) nil)
((characterp x)
(cond ((characterp y)
(<= (char-code x) (char-code y)))
(t t)))
((characterp y) nil)
((stringp x)
(cond ((stringp y) (and (string<= x y) t))
(t t)))
((stringp y) nil)
(t (cond ((symbolp x)
(cond ((symbolp y) (not (symbol-< y x)))
(t t)))
((symbolp y) nil)
(t (bad-atom<= x y))))))")
(ALTERNATIVE-INTRODUCTION
(ACL2-TUTORIAL)
"Introduction to ACL2
This section contains introductory material on ACL2 including what
ACL2 is, how to get started using the system, how to read the
output, and other introductory topics. It was written almost
entirely by Bill Young of Computational Logic, Inc.
You might also find CLI Technical Report 101 helpful, especially if
you are familiar with Nqthm. If you would like more familiarity
with Nqthm, we suggest CLI Technical Report 100.
OVERVIEW
ACL2 is an automated reasoning system developed (for the first 9
years) at Computational Logic, Inc. and (from January, 1997) at the
University of Texas at Austin. It is the successor to the Nqthm (or
Boyer-Moore) logic and proof system and its Pc-Nqthm interactive
enhancement. The acronym ACL2 actually stands for ``A Computational
Logic for Applicative Common Lisp''. This title suggests several
distinct but related aspects of ACL2.
We assume that readers of the ACL2 [documentation] have at least a
very slight familiarity with some Lisp-like language. We will
address the issue of prerequisites further, in ``ABOUT THIS
TUTORIAL'' below.
As a logic, ACL2 is a formal system with rigorously defined syntax
and semantics. In mathematical parlance, the ACL2 logic is a
first-order logic of total recursive functions providing
mathematical induction on the ordinals up to epsilon-0 and two
extension principles: one for recursive definition and one for
constrained introduction of new function symbols, here called
encapsulation. The syntax of ACL2 is that of Common Lisp; ACL2
specifications are ``also'' Common Lisp programs in a way that we
will make clear later. In less formal language, the ACL2 logic is
an integrated collection of rules for defining (or axiomatizing)
recursive functions, stating properties of those functions, and
rigorously establishing those properties. Each of these activities
is mechanically supported.
As a specification language, ACL2 supports modeling of systems of
various kinds. An ACL2 function can equally be used to express
purely formal relationships among mathematical entities, to
describe algorithms, or to capture the intended behavior of digital
systems. For digital systems, an ACL2 specification is a
mathematical model that is intended to formalize relevant aspects
of system behavior. Just as physics allows us to model the behavior
of continuous physical systems, ACL2 allows us to model digital
systems, including many with physical realizations such as computer
hardware. As early as the 1930's Church, Kleene, Turing and others
established that recursive functions provide an expressive
formalism for modeling digital computation. Digital computation
should be understood in a broad sense, covering a wide variety of
activities including almost any systematic or algorithmic activity,
or activity that can be reasonably approximated in that way. This
ranges from the behavior of a digital circuit to the behavior of a
programming language compiler to the behavior of a controller for a
physical system (as long as the system can be adequately modeled
discretely). All of these have been modeled using ACL2 or its
predecessor Nqthm.
ACL2 is a computational logic in at least three distinct senses.
First, the theory of recursive functions is often considered the
mathematics of computation. Church conjectured that any ``effective
computation'' can be modeled as a recursive function. Thus, ACL2
provides an expressive language for modeling digital systems.
Second, many ACL2 specifications are executable. In fact, recursive
functions written in ACL2 are Common Lisp functions that can be
submitted to any compliant Common Lisp compiler and executed (in an
environment where suitable ACL2-specific macros and functions are
defined). Third, ACL2 is computational in the sense that
calculation is heavily integrated into the reasoning process. Thus,
an expression with explicit constant values but no free variables
can be simplified by calculation rather than by complex logical
manipulations.
ACL2 is a powerful, automated theorem prover or proof checker. This
means that a competent user can utilize the ACL2 system to discover
proofs of theorems stated in the ACL2 logic or to check previously
discovered proofs. The basic deductive steps in an ACL2-checked
proof are often quite large, due to the sophisticated combination
of decision procedures, conditional rewriting, mathematical and
structural induction, propositional simplification, and complex
heuristics to orchestrate the interactions of these capabilities.
Unlike some automated proof systems, ACL2 does not produce a formal
proof. However, we believe that if ACL2 certifies the
``theoremhood'' of a given conjecture, then such a formal proof
exists and, therefore, the theorem is valid. The ultimate result of
an ACL2 proof session is a collection of ``[events],'' possibly
grouped into ``[books],'' that can be replayed in ACL2. Therefore,
a proof can be independently validated by any ACL2 user.
ACL2 may be used in purely automated mode in the shallow sense that
conjectures are submitted to the prover and the user does not
interact with the proof attempt (except possibly to stop it) until
the proof succeeds or fails. However, any non-trivial proof attempt
is actually interactive, since successful proof ``[events]''
influence the subsequent behavior of the prover. For example,
proving a lemma may introduce a rule that subsequently is used
automatically by the prover. Thus, any realistic proof attempt,
even in ``automatic'' mode, is really an interactive dialogue with
the prover to craft a sequence of [events] building an appropriate
theory and proof rules leading up to the proof of the desired
result. Also, ACL2 supports annotating a theorem with ``[hints]''
designed to guide the proof attempt. By supplying appropriate
[hints], the user can suggest proof strategies that the prover
would not discover automatically. There is a ``[proof-tree]''
facility (see [proof-tree]) that allows the user to [monitor] the
progress and structure of a proof attempt in real-time. Exploring
failed proof attempts is actually where heavy-duty ACL2 users spend
most of their time.
ACL2 can also be used in a more explicitly interactive mode. The
``[proof-checker]'' subsystem of ACL2 allows exploration of a proof
on a fairly low level including expanding calls of selected
function symbols, invoking specific [rewrite] rules, and
selectively navigating around the proof. This facility can be used
to gain sufficient insight into the proof to construct an automatic
version, or to generate a detailed interactive-style proof that can
be replayed in batch mode.
Because ACL2 is all of these things --- computational logic,
specification language, [programming] system, and theorem prover
--- it is more than the sum of its parts. The careful integration
of these diverse aspects has produced a versatile automated
reasoning system suitable for building highly reliable digital
systems. In the remainder of this tutorial, we will illustrate some
simple uses of this automated reasoning system.
ABOUT THIS TUTORIAL
ACL2 is a complex system with a vast array of features, bells and
whistles. However, it is possible to perform productive work with
the system using only a small portion of the available
functionality. The goals of this tutorial are to:
familiarize the new user with the most basic features of and modes of
interaction with ACL2;
familiarize her with the form of output of the system; and
work through a graduated series of examples.
The more knowledge the user brings to this system, the easier it will
be to become proficient. On one extreme: the ideal user of ACL2 is
an expert Common Lisp programmer, has deep understanding of
automated reasoning, and is intimately familiar with the earlier
Nqthm system. Such ideal users are unlikely to need this tutorial.
However, without some background knowledge, the beginning user is
likely to become extremely confused and frustrated by this system.
We suggest that a new user of ACL2 should:
(a) have a little familiarity with Lisp, including basic Lisp
programming and prefix notation (a Lisp reference manual such
as Guy Steele's ``Common Lisp: The Language'' is also helpful);
(b) be convinced of the utility of formal modeling; and
(c) be willing to gain familiarity with basic automated theorem
proving topics such as rewriting and algebraic simplification.
We will not assume any deep familiarity with Nqthm (the so-called
``Boyer-Moore Theorem Prover''), though the book ``A Computational
Logic Handbook'' by Boyer and Moore (Academic Press, 1988) is an
extremely useful reference for many of the topics required to
become a competent ACL2 user. We'll refer to it as ACLH below.
As we said in the introduction, ACL2 has various facets. For example,
it can be used as a Common Lisp [programming] system to construct
application programs. In fact, the ACL2 system itself is a large
Common Lisp program constructed almost entirely within ACL2.
Another use of ACL2 is as a specification and modeling tool. That
is the aspect we will concentrate on in the remainder of this
tutorial.
GETTING STARTED
This section is an abridged version of what's available elsewhere;
feel free to see [startup] for more details.
How you start ACL2 will be system dependent, but you'll probably type
something like ``acl2'' at your operating system prompt. Consult
your system administrator for details.
When you start up ACL2, you'll probably find yourself inside the ACL2
[command] loop, as indicated by the following [prompt].
ACL2 !>
If not, you should type (LP). See [lp], which has a lot more
information about the ACL2 [command] loop.
There are two ``modes'' for using ACL2, :[logic] and :[program]. When
you begin ACL2, you will ordinarily be in the :[logic] mode. This
means that any new function defined is not only executable but also
is axiomatically defined in the ACL2 logic. (See [defun-mode] and
see [default-defun-mode].) Roughly speaking, :[program] mode is
available for using ACL2 as a [programming] language without some
of the logical burdens necessary for formal reasoning. In this
tutorial we will assume that we always remain in :[logic] mode and
that our purpose is to write formal models of digital systems and
to reason about them.
Now, within the ACL2 [command] loop you can carry out various kinds
of activities, including the folllowing. (We'll see examples later
of many of these.)
define new functions (see [defun]);
execute functions on concrete data;
pose and attempt to prove conjectures about previously defined
functions (see [defthm]);
query the ACL2 ``[world]'' or database (e.g., see [pe]); and
numerous other things.
In addition, there is extensive on-line [documentation], of which
this tutorial introduction is a part.
INTERACTING WITH ACL2
The standard means of interacting with ACL2 is to submit a sequence
of forms for processing by the ACL2 system. These forms are checked
for syntactic and semantic acceptability and appropriately
processed by the system. These forms can be typed directly at the
ACL2 [prompt]. However, most successful ACL2 users prefer to do
their work using the Emacs text editor, maintaining an Emacs
``working'' buffer in which forms are edited. Those forms are then
copied to the ACL2 interaction buffer, which is often the \"*shell*\"
buffer.
In some cases, processing succeeds and makes some change to the ACL2
``logical [world],'' which affects the processing of subsequent
forms. How can this processing fail? For example, a proposed
theorem will be rejected unless all function symbols mentioned have
been previously defined. Also the ability of ACL2 to discover the
proof of a theorem may depend on the user previously having proved
other theorems. Thus, the order in which forms are submitted to
ACL2 is quite important. Maintaining forms in an appropriate order
in your working buffer will be helpful for re-playing the proof
later.
One of the most common [events] in constructing a model is
introducing new functions. New functions are usually introduced
using the [defun] form; we'll encounter some exceptions later.
Proposed function definitions are checked to make sure that they
are syntactically and semantically acceptable (e.g., that all
mentioned functions have been previously defined) and, for
recursive functions, that their recursive calls terminate. A
recursive function definition is guaranteed to terminate if there
is some some ``measure'' of the arguments and a ``well-founded''
ordering such that the arguments to the function get smaller in
each recursive call. See [well-founded-relation].
For example, suppose that we need a function that will append two
lists together. (We already have one in the ACL2 [append] function;
but suppose perversely that we decide to define our own.) Suppose
we submit the following definition (you should do so as well and
study the system output):
(defun my-app (x y)
(if (atom x)
y
(cons (car x) (my-app x y))))
The system responds with the following message:
ACL2 Error in ( DEFUN MY-APP ...): No :MEASURE was supplied with
the definition of MY-APP. Our heuristics for guessing one have not
made any suggestions. No argument of the function is tested along
every branch and occurs as a proper subterm at the same argument
position in every recursive call. You must specify a :MEASURE. See
:DOC defun.
This means that the system could not find an expression involving the
formal parameters x and y that decreases under some well-founded
order in every recursive call (there is only one such call). It
should be clear that there is no such measure in this case because
the only recursive call doesn't change the arguments at all. The
definition is obviously flawed; if it were accepted and executed it
would loop forever. Notice that a definition that is rejected is
not stored in the system database; there is no need to take any
action to have it ``thrown away.'' Let's try again with the correct
definition. The interaction now looks like (we're also putting in
the ACL2 [prompt]; you don't type that):
ACL2 !>(defun my-app (x y)
(if (atom x)
y
(cons (car x) (my-app (cdr x) y))))
The admission of MY-APP is trivial, using the relation O<
(which is known to be well-founded on the domain recognized by
O-P) and the measure (ACL2-COUNT X). We observe that the
type of MY-APP is described by the theorem
(OR (CONSP (MY-APP X Y)) (EQUAL (MY-APP X Y) Y)).
We used primitive type reasoning.
Summary
Form: ( DEFUN MY-APP ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: None
Time: 0.07 seconds (prove: 0.00, print: 0.00, other: 0.07)
MY-APP
Notice that this time the function definition was accepted. We didn't
have to supply a measure explicitly; the system inferred one from
the form of the definition. On complex functions it may be
necessary to supply a measure explicitly. (See [xargs].)
The system output provides several pieces of information.
The revised definition is acceptable. The system realized that there
is a particular measure (namely, (acl2-count x)) and a
well-founded relation (o<) under which the arguments of my-app
get smaller in recursion. Actually, the theorem prover proved
several theorems to admit my-app. The main one was that when
(atom x) is false the acl2-count of (cdr x) is less than (in
the o< sense) the acl2-count of x. [Acl2-count] is the most
commonly used measure of the ``size`` of an ACL2 object. [o<]
is the ordering relation on ordinals less than epsilon-0. On
the natural numbers it is just ordinary ``<''.
The observation printed about ``the type of MY-APP'' means that calls
of the function my-app will always return a value that is
either a [cons] pair or is equal to the second parameter.
The summary provides information about which previously introduced
definitions and lemmas were used in this proof, about some
notable things to watch out for (the Warnings), and about how
long this event took to process.
Usually, it's not important to read this information. However, it is
a good habit to scan it briefly to see if the type information is
surprising to you or if there are Warnings. We'll see an example of
them later.
After a function is accepted, it is stored in the database and
available for use in other function definitions or lemmas. To see
the definition of any function use the :[pe] command (see [pe]).
For example,
ACL2 !>:pe my-app
L 73:x(DEFUN MY-APP (X Y)
(IF (ATOM X)
Y (CONS (CAR X) (MY-APP (CDR X) Y))))
This displays the definition along with some other relevant
information. In this case, we know that this definition was
processed in :[logic] mode (the ``L'') and was the 73rd [command]
processed in the current session.
We can also try out our newly defined function on some sample data.
To do that, just submit a form to be evaluated to ACL2. For
example,
ACL2 !>(my-app '(0 1 2) '(3 4 5))
(0 1 2 3 4 5)
ACL2 !>(my-app nil nil)
NIL
ACL2 !>
Now suppose we want to prove something about the function just
introduced. We conjecture, for example, that the length of the
[append] of two lists is the sum of their lengths. We can formulate
this conjecture in the form of the following ACL2 [defthm] form.
(defthm my-app-length
(equal (len (my-app x y))
(+ (len x) (len y))))
First of all, how did we know about the functions len and [+], etc.?
The answer to that is somewhat unsatisfying --- we know them from
our past experience in using Common Lisp and ACL2. It's hard to
know that a function such as len exists without first knowing some
Common Lisp. If we'd guessed that the appropriate function was
called [length] (say, from our knowledge of Lisp) and tried :pe
length, we would have seen that [length] is defined in terms of
len, and we could have explored from there. Luckily, you can write
a lot of ACL2 functions without knowing too many of the primitive
functions.
Secondly, why don't we need some ``type'' hypotheses? Does it make
sense to append things that are not lists? Well, yes. ACL2 and Lisp
are both quite weakly typed. For example, inspection of the
definition of my-app shows that if x is not a [cons] pair, then
(my-app x y) always returns y, no matter what y is.
Thirdly, would it matter if we rewrote the lemma with the equality
reversed, as follows?
(defthm my-app-length2
(equal (+ (len x) (len y))
(len (my-app x y)))).
The two are logically equivalent, but...yes, it would make a big
difference. Recall our remark that a lemma is not only a ``fact''
to be proved; it also is used by the system to prove other later
lemmas. The current lemma would be stored as a [rewrite] rule. (See
[rule-classes].) For a [rewrite] rule, a conclusion of the form
(EQUAL LHS RHS) means to replace instances of the LHS by the
appropriate instance of the RHS. Presumably, it's better to
[rewrite] (len (my-app x y)) to (+ (len x) (len y)) than the other
way around. The reason is that the system ``knows'' more about [+]
than it does about the new function symbol my-app.
So let's see if we can prove this lemma. Submitting our preferred
[defthm] to ACL2 (do it!), we get the following interaction:
--------------------------------------------------
ACL2 !>(defthm my-app-length
(equal (len (my-app x y))
(+ (len x) (len y))))
Name the formula above *1.
Perhaps we can prove *1 by induction. Three induction schemes are
suggested by this conjecture. These merge into two derived
induction schemes. However, one of these is flawed and so we are
left with one viable candidate.
We will induct according to a scheme suggested by (LEN X), but
modified to accommodate (MY-APP X Y). If we let (:P X Y) denote *1
above then the induction scheme we'll use is
(AND (IMPLIES (NOT (CONSP X)) (:P X Y))
(IMPLIES (AND (CONSP X) (:P (CDR X) Y))
(:P X Y))).
This induction is justified by the same argument used to admit LEN,
namely, the measure (ACL2-COUNT X) is decreasing according to the
relation O< (which is known to be well-founded on the domain
recognized by O-P). When applied to the goal at hand the
above induction scheme produces the following two nontautological
subgoals.
Subgoal *1/2
(IMPLIES (NOT (CONSP X))
(EQUAL (LEN (MY-APP X Y))
(+ (LEN X) (LEN Y)))).
But simplification reduces this to T, using the :definitions of FIX,
LEN and MY-APP, the :type-prescription rule LEN, the :rewrite rule
UNICITY-OF-0 and primitive type reasoning.
Subgoal *1/1
(IMPLIES (AND (CONSP X)
(EQUAL (LEN (MY-APP (CDR X) Y))
(+ (LEN (CDR X)) (LEN Y))))
(EQUAL (LEN (MY-APP X Y))
(+ (LEN X) (LEN Y)))).
This simplifies, using the :definitions of LEN and MY-APP, primitive
type reasoning and the :rewrite rules COMMUTATIVITY-OF-+ and
CDR-CONS, to
Subgoal *1/1'
(IMPLIES (AND (CONSP X)
(EQUAL (LEN (MY-APP (CDR X) Y))
(+ (LEN Y) (LEN (CDR X)))))
(EQUAL (+ 1 (LEN (MY-APP (CDR X) Y)))
(+ (LEN Y) 1 (LEN (CDR X))))).
But simplification reduces this to T, using linear arithmetic,
primitive type reasoning and the :type-prescription rule LEN.
That completes the proof of *1.
Q.E.D.
Summary
Form: ( DEFTHM MY-APP-LENGTH ...)
Rules: ((:REWRITE UNICITY-OF-0)
(:DEFINITION FIX)
(:REWRITE COMMUTATIVITY-OF-+)
(:DEFINITION LEN)
(:REWRITE CDR-CONS)
(:DEFINITION MY-APP)
(:TYPE-PRESCRIPTION LEN)
(:FAKE-RUNE-FOR-TYPE-SET NIL)
(:FAKE-RUNE-FOR-LINEAR NIL))
Warnings: None
Time: 0.30 seconds (prove: 0.13, print: 0.05, other: 0.12)
MY-APP-LENGTH
--------------------------------------------------
Wow, it worked! In brief, the system first tried to [rewrite] and
simplify as much as possible. Nothing changed; we know that because
it said ``Name the formula above *1.'' Whenever the system decides
to name a formula in this way, we know that it has run out of
techniques to use other than proof by induction.
The induction performed by ACL2 is structural or ``Noetherian''
induction. You don't need to know much about that except that it is
induction based on the structure of some object. The heuristics
infer the structure of the object from the way the object is
recursively decomposed by the functions used in the conjecture. The
heuristics of ACL2 are reasonably good at selecting an induction
scheme in simple cases. It is possible to override the heuristic
choice by providing an :induction hint (see [hints]). In the case
of the theorem above, the system inducts on the structure of x as
suggested by the decomposition of x in both (my-app x y) and (len
x). In the base case, we assume that x is not a [consp]. In the
inductive case, we assume that it is a [consp] and assume that the
conjecture holds for (cdr x).
There is a close connection between the analysis that goes on when a
function like my-app is accepted and when we try to prove something
inductively about it. That connection is spelled out well in Boyer
and Moore's book ``A Computational Logic,'' if you'd like to look
it up. But it's pretty intuitive. We accepted my-app because the
``size'' of the first argument x decreases in the recursive call.
That tells us that when we need to prove something inductively
about my-app, it's a good idea to try an induction on the size of
the first argument. Of course, when you have a theorem involving
several functions, it may be necessary to concoct a more
complicated [induction] schema, taking several of them into
account. That's what's meant by ``merging'' the induction schemas.
The proof involves two cases: the base case, and the inductive case.
You'll notice that the subgoal numbers go down rather than up, so
you always know how many subgoals are left to process. The base
case (Subgoal *1/2) is handled by opening up the function
definitions, simplifying, doing a little rewriting, and performing
some reasoning based on the types of the arguments. You'll often
encounter references to system defined lemmas (like unicity-of-0).
You can always look at those with :[pe]; but, in general, assume
that there's a lot of simplification power under the hood that's
not too important to understand fully.
The inductive case (Subgoal *1/1) is also dispatched pretty easily.
Here we assume the conjecture true for the [cdr] of the list and
try to prove it for the entire list. Notice that the prover does
some simplification and then prints out an updated version of the
goal (Subgoal *1/1'). Examining these gives you a pretty good idea
of what's going on in the proof.
Sometimes one goal is split into a number of subgoals, as happened
with the induction above. Sometimes after some initial processing
the prover decides it needs to prove a subgoal by induction; this
subgoal is given a name and pushed onto a stack of goals. Some
steps, like generalization (see ACLH), are not necessarily validity
preserving; that is, the system may adopt a false subgoal while
trying to prove a true one. (Note that this is ok in the sense that
it is not ``unsound.'' The system will fail in its attempt to
establish the false subgoal and the main proof attempt will fail.)
As you gain facility with using the prover, you'll get pretty good
at recognizing what to look for when reading a proof script. The
prover's [proof-tree] utility helps with monitoring an ongoing
proof and jumping to designated locations in the proof (see
[proof-tree]). See [tips] for a number of useful pointers on using
the theorem prover effectively.
When the prover has successfully proved all subgoals, the proof is
finished. As with a [defun], a summary of the proof is printed.
This was an extremely simple proof, needing no additional guidance.
More realistic examples typically require the user to look
carefully at the failed proof log to find ways to influence the
prover to do better on its next attempt. This means either: proving
some rules that will then be available to the prover, changing the
global state in ways that will affect the proof, or providing some
[hints] locally that will influence the prover's behavior. Proving
this lemma (my-app-length) is an example of the first. Since this
is a [rewrite] rule, whenever in a later proof an instance of the
form (LEN (MY-APP X Y)) is encountered, it will be rewritten to the
corresponding instance of (+ (LEN X) (LEN Y)). Disabling the rule
by executing the [command]
(in-theory (disable my-app-length)),
is an example of a global change to the behavior of the prover since
this [rewrite] will not be performed subsequently (unless the rule
is again [enable]d). Finally, we can add a (local) [disable]
``hint'' to a [defthm], meaning to [disable] the lemma only in the
proof of one or more subgoals. For example:
(defthm my-app-length-commutativity
(equal (len (my-app x y))
(len (my-app y x)))
:hints ((\"Goal\" :in-theory (disable my-app-length))))
In this case, the hint supplied is a bad idea since the proof is much
harder with the hint than without it. Try it both ways.
By the way, to undo the previous event use :u (see [u]). To undo back
to some earlier event use :ubt (see [ubt]). To view the current
event use :pe :here. To list several [events] use :pbt (see [pbt]).
Notice the form of the hint in the previous example (see [hints]). It
specifies a goal to which the hint applies. \"Goal\" refers to the
top-level goal of the theorem. Subgoals are given unique names as
they are generated. It may be useful to suggest that a function
symbol be [disable]d only for Subgoal 1.3.9, say, and a different
function [enable]d only on Subgoal 5.2.8. Overuse of such [hints]
often suggests a poor global proof strategy.
We now recommend that you visit [documentation] on additional
examples. See [annotated-ACL2-scripts].")
(ANALYZING_COMMON_LISP_MODELS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Analyzing Common Lisp Models
To analyze a model you must be able to reason about the operations
and relations involved. Perhaps, for example, some aspect of the
model depends upon the fact that the concatenation operation is
associative.
In any Common Lisp you can confirm that
(app '(A B) (app '(C D) '(E F)))
and
(app (app '(A B) '(C D)) '(E F)))
both evaluate to the same thing, (A B C D E F).
But what distinguishes ACL2 (the logic) from applicative Common Lisp
(the language) is that in ACL2 you can prove that the concatenation
function app is associative when its arguments are true-lists,
whereas in Common Lisp all you can do is test that proposition.
That is, in ACL2 it makes sense to say that the following formula is
a ``theorem.''
Theorem Associativity of App
(implies (and (true-listp a)
(true-listp b))
(equal (app (app a b) c)
(app a (app b c))))
Theorems about the properties of models are proved by symbolically
manipulating the operations and relations involved. If the
concatenation of sequences is involved in your model, then you may
well need the theorem above in order to that your model has some
particular property.")
(AND
(BASICS ACL2-BUILT-INS)
"Conjunction
And is the macro for conjunctions. And takes any number of arguments.
And returns nil if one of the arguments is nil, but otherwise
returns the last argument. If there are no arguments, and returns
t.
And is a Common Lisp macro. See any Common Lisp documentation for
more information.
Macro: <and>
(defmacro and (&rest args)
(and-macro args))
Function: <and-macro>
(defun and-macro (lst)
(declare (xargs :guard t))
(if (consp lst)
(if (consp (cdr lst))
(list 'if
(car lst)
(and-macro (cdr lst))
nil)
(car lst))
t))")
(ANNOTATED-ACL2-SCRIPTS
(ACL2-TUTORIAL)
"Examples of ACL2 scripts
Beginning users may find these annotated scripts useful. We suggest
that you read these in the following order:
[Tutorial1-Towers-of-Hanoi]
[Tutorial2-Eights-Problem]
[Tutorial3-Phonebook-Example]
[Tutorial4-Defun-Sk-Example]
[Tutorial5-Miscellaneous-Examples]
You can also find useful demos in the [community-books] directory,
books/demos/, and its subdirectories.
The web page {Brief ACL2 Tutorial |
http://www.cs.utexas.edu/users/moore/publications/tutorial/rev3.html}
contains a script that illustrates how it feels to use The Method
to prove an unusual list reverse function correct. The screen shots
of ACL2's proof output are outdated -- in the version shown, ACL2
does not print Key Checkpoints, but the concept of key checkpoint
is clear in the discussion and the behavior of the user.
See {Polishing Proofs Tutorial |
http://www.cs.utexas.edu/users/moore/acl2/contrib/POLISHING-PROOFS-TUTORIAL.html}
for a tutorial on becoming successful at approaching a
formalization and proof problem in ACL2. That tutorial, written by
Shilpi Goel and Sandip Ray, has two parts: it illustrates how to
guide the theorem prover to a successful proof, and it shows how to
clean up the proof in order to facilitate maintenance and extension
of the resulting book (see [books]).
The {ACL2 Demo Given at TPHOLs 2008 |
http://www.cs.utexas.edu/users/moore/publications/tutorial/kaufmann-TPHOLs08/index.html}
by Matt Kaufmann includes scripts and a gzipped tar file containing
the entire contents of the demos.
The {sort equivalence demo |
http://www.cs.utexas.edu/users/moore/publications/tutorial/sort-equivalence}
is a collection of scripts illustrating both high-level strategy
and lower-level tactics dealing with the functional equivalence of
various list sorting algorithms. Start with the README on that
directory. There is also a {gzipped tar file |
http://www.cs.utexas.edu/users/moore/publications/tutorial/sort-equivalence.tgz}
with all of these scripts.
When you feel you have read enough examples, you might want to try
the following very simple example on your own. (See
[solution-to-simple-example] for a solution, after you work on this
example.) First define the notion of the ``fringe'' of a tree,
where we identify trees simply as [cons] structures, with [atom]s
at the leaves. For example:
ACL2 !>(fringe '((a . b) c . d))
(A B C D)
Next, define the notion of a ``leaf'' of a tree, i.e., a predicate
leaf-p that is true of an atom if and only if that atom appears at
the tip of the tree. Define this notion without referencing the
function fringe. Finally, prove the following theorem, whose proof
may well be automatic (i.e., not require any lemmas).
(defthm leaf-p-iff-member-fringe
(iff (leaf-p atm x)
(member-equal atm (fringe x))))
Subtopics
[Solution-to-simple-example]
Solution to a simple example
[Tutorial1-towers-of-hanoi]
The Towers of Hanoi Example
[Tutorial2-eights-problem]
The Eights Problem Example
[Tutorial3-phonebook-example]
A Phonebook Specification
[Tutorial4-defun-sk-example]
Example of quantified notions
[Tutorial5-miscellaneous-examples]
Miscellaneous ACL2 examples")
(AN_EXAMPLE_COMMON_LISP_FUNCTION_DEFINITION
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"An Example Common Lisp Function Definition
[{IMAGE}]
Consider the binary trees x and y below.
{IMAGE}
In Lisp, x is written as the list '(A B) or, equivalently, as '(A B .
NIL). Similarly, y may be written '(C D E). Suppose we wish to
replace the right-most tip of x by the entire tree y. This is
denoted (app x y), where app stands for ``append''.
{IMAGE}
We can define app with:
(defun app (x y) ; Concatenate x and y.
(declare (type (satisfies true-listp) x)); We expect x to end in NIL.
(cond ((endp x) y) ; If x is empty, return y.
(t (cons (car x) ; Else, copy first node
(app (cdr x) y))))) ; and recur into next.
If you defined this function in some Common Lisp, then to run app on
the x and y above you could then type
(app '(A B) '(C D E))
and Common Lisp will print the result (A B C D E).
[{IMAGE}]")
(AN_EXAMPLE_OF_ACL2_IN_USE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"An Example of ACL2 in Use
[{IMAGE}]
To introduce you to ACL2 we will consider the app function discussed
in the [Common Lisp] page, except we will omit for the moment the
declare form, which in ACL2 is called a guard.
Guards are arbitrary ACL2 terms that express the ``intended domain''
of functions. In that sense, guards are akin to type signatures.
However, Common Lisp and ACL2 are untyped programming languages:
while the language supports several different data types and the
types of objects can be determined by predicates at runtime, any
type of object may be passed to any function. Thus, guards are
``extra-logical.'' Recognizing both the practical and intellectual
value of knowing that your functions are applied to the kinds of
objects you intend, ACL2 imposes guards on Common Lisp and provides
a means of proving that functions are used as intended. But the
story is necessarily complicated and we do not recommend it to the
new user. Get used to the fact that any ACL2 function may be
applied to any objects and program accordingly. Read about guards
later.
Here is the definition again
(defun app (x y)
(cond ((endp x) y)
(t (cons (car x)
(app (cdr x) y)))))
The next few stops along the Walking Tour will show you
* how to use the ACL2 documentation, * what happens when the above
definition is submitted to ACL2, * what happens when you evaluate calls of
app, * what one simple theorem about app looks like, * how ACL2
proves the theorem, and * how that theorem can be used in another proof.
Along the way we will talk about the definitional principle, types,
the ACL2 read-eval-print loop, and how the theorem prover works.
When we complete this part of the tour we will return briefly to the
notion of guards and revisit several of the topics above in that
context.
[{IMAGE}]")
(APPEND
(LISTS ACL2-BUILT-INS)
"[concatenate] zero or more lists
Append, which takes zero or more arguments, expects all the arguments
except perhaps the last to be true (null-terminated) lists. It
returns the result of concatenating all the elements of all the
given lists into a single list. Actually, in ACL2 append is a macro
that expands into calls of the binary function [binary-append] if
there are at least two arguments; if there is just one argument
then the expansion is that argument; and finally, (append) expands
to nil.
Append is a Common Lisp function. See any Common Lisp documentation
for more information. See [append-without-guard] for a version of
append that has a guard of t.
Macro: <append>
(defmacro append (&rest rst)
(cond ((null rst) nil)
((null (cdr rst)) (car rst))
(t (xxxjoin 'binary-append rst))))
Function: <binary-append>
(defun binary-append (x y)
(declare (xargs :guard (true-listp x)))
(cond ((endp x) y)
(t (cons (car x)
(binary-append (cdr x) y)))))
Subtopics
[Binary-append]
[concatenate] two lists")
(APROPOS (POINTERS)
"See [finding-documentation].")
(ARCHITECTURE-OF-THE-PROVER
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"A simple overview of how the prover works
Six built-in proof techniques are used by ACL2 to decompose the goal
formula into subgoals.
* simplification --- decision procedures and rewriting with previously
proved rules, but actually including a host of other techniques
under your control. Simplification is the only proof technique
that can reduce a formula to 0 subgoals (i.e., prove it) rather
than just transform it to other formulas. The predominant
activity in most proofs is simplification. There are many ways
you can affect what the simplifier does to your formulas. Good
users spend most of their time thinking about how to control
the simplifier.
* destructor elimination --- getting rid of ``destructor terms'' like
(CAR X) and (CDR X) by replacing a variable, e.g., X, by a
``constructor'' term, e.g., (CONS A B). But you can tell ACL2
about new destructor/constructor combinations.
* fertilization --- using an equivalence hypothesis by substituting one
side for the other in the goal. When under induction, ACL2 may
decide to restrict the substitution as follows, using its
so-called cross-fertilization heuristic: substitute only into
one side of the conclusion, thus using an inductive hypothesis
in preparation for possible generalization in advance of
another induction. Note that cross-fertilization is used only
when generalization is enabled: with the hint :do-not
'(generalize), only full fertilization is applied.
* generalization --- replacing a term by a new variable and restricting
the new variable to have some of the properties of the term.
You can control the restrictions imposed on the new variable.
This is a heuristic that prepares the goal for another
induction.
* elimination of irrelevance --- throwing away unnecessary hypotheses.
This is a heuristic that prepares the goal for another
induction.
* induction --- selecting an induction scheme to prove a formula.
Inductions are ``suggested'' by the recursive functions
appearing in the formula. But you can control what inductions
are suggested by terms.
But you can add additional techniques, called clause processors.
The various techniques are tried in turn, with simplification first
and induction last. Each technique reports one of three outcomes:
it found nothing to change (i.e., the technique doesn't apply to
that subgoal), it decided to abort the proof attempt (typically
because there is reason to believe the proof is failing), or it
decomposed the goal into k subgoals.
The last outcome has a special case: if k is 0 then the technique
proved the goal. Whenever k is non-0, the process starts over again
with simplification on each of the k subgoals. However, it saves up
all the subgoals for which induction is the only proof technique
left to try. That way you see how it performs on every base case
and induction step of one induction before it launches into another
induction.
It runs until you or one of the proof techniques aborts the proof
attempt or until all subgoals have been proved.
Note that if simplification produces a subgoal, that subgoal is
re-simplified. This process continues until the subgoal cannot be
simplified further. Only then is the next proof technique is tried.
Such suboals are said to be stable under simplification.
While this is happening, the prover prints an English narrative
describing the process. Basically, after each goal is printed, the
system prints an English paragraph that names the next applicable
proof technique, gives a brief description of what that technique
does to the subgoal, and says how many new subgoals are produced.
Then each subgoal is dealt with in turn.
If the proof is successful, you could read this log as a proof of the
conjecture. But output from successful proofs is generally never
read because it is not important to The Method described in
[introduction-to-the-theorem-prover].
The output of an unsuccessful proof attempt concludes with some key
checkpoints which usually bear looking at.
For more information about how ACL2 orchestrates its proof
techniques, see [hints-and-the-waterfall].")
(AREF1
(ARRAYS ACL2-BUILT-INS)
"Access the elements of a 1-dimensional array
Example Form:
(aref1 'delta1 a (+ i k))
General Form:
(aref1 name alist index)
where name is a symbol, alist is a 1-dimensional array and index is a
legal index into alist. This function returns the value associated
with index in alist, or else the default value of the array. See
[arrays] for details.
This function executes in virtually constant time if alist is in fact
the ``semantic value'' associated with name (see [arrays]). When it
is not, aref1 must do a linear search through alist. In that case
the correct answer is returned but a slow array comment is printed
to the comment window. See [slow-array-warning].
Function: <aref1>
(defun
aref1 (name l n)
(declare (xargs :guard (and (array1p name l)
(integerp n)
(>= n 0)
(< n (car (dimensions name l))))))
(let ((x (and (not (eq n :header)) (assoc n l))))
(cond ((null x) (default name l))
(t (cdr x)))))")
(AREF2
(ARRAYS ACL2-BUILT-INS)
"Access the elements of a 2-dimensional array
Example Form:
(aref2 'delta1 a i j)
General Form:
(aref2 name alist i j)
where name is a symbol, alist is a 2-dimensional array and i and j
are legal indices into alist. This function returns the value
associated with (i . j) in alist, or else the default value of the
array. See [arrays] for details.
This function executes in virtually constant time if alist is in fact
the ``semantic value'' associated with name (see [arrays]). When it
is not, aref2 must do a linear search through alist. In that case
the correct answer is returned but a slow array comment is printed
to the comment window. See [slow-array-warning].
Function: <aref2>
(defun
aref2 (name l i j)
(declare (xargs :guard (and (array2p name l)
(integerp i)
(>= i 0)
(< i (car (dimensions name l)))
(integerp j)
(>= j 0)
(< j (cadr (dimensions name l))))))
(let ((x (assoc2 i j l)))
(cond ((null x) (default name l))
(t (cdr x)))))")
(ARGS
(DOCUMENTATION)
"args, [guard], type, [constraint], etc., of a function symbol
Example:
:args assoc-eq
Args takes one argument, a symbol which must be the name of a
function or macro, and prints out the formal parameters, the
[guard] expression, the output [signature], the deduced type, the
[constraint] (if any), and whether [documentation] about the symbol
is available via :[doc].")
(ARITIES-OKP
(ACL2-BUILT-INS)
"check the arities of given function symbols
Example:
(arities-ok '((IF . 3) (CAR . 1) (CONS . 2)) (w state))
General Form:
(arities-okp alist w)
where alist is a [symbol-alistp] and w is an ACL2 logical [world].
The alist is presumed to pair function symbols with arities. The
result is t or nil according to whether each symbol in the alist
has the associated arity as its [arity] in w. See
[well-formedness-guarantee].
Function: <arities-okp>
(defun arities-okp (user-table w)
(declare (xargs :guard (and (symbol-alistp user-table)
(plist-worldp-with-formals w))))
(cond ((endp user-table) t)
(t (and (equal (arity (car (car user-table)) w)
(cdr (car user-table)))
(arities-okp (cdr user-table) w)))))")
(ARITY
(ACL2-BUILT-INS)
"number of arguments of a function symbol
Examples:
(arity 'IF (w state))
(arity '(LAMBDA (X) (CONS X X)) (w state))
General Form:
(arity fn w)
where fn is a function symbol or a lambda expression and w is an ACL2
logical [world]. The result is the number of arguments the function
or lambda expression takes, or nil if the function symbol is not
defined in w.")
(ARRAY1P
(ARRAYS ACL2-BUILT-INS)
"Recognize a 1-dimensional array
Example Form:
(array1p 'delta1 a)
General Form:
(array1p name alist)
where name and alist are arbitrary objects. This function returns t
if alist is a 1-dimensional ACL2 array. Otherwise it returns nil.
The function operates in constant time if alist is the semantic
value of name. See [arrays].
Function: <array1p>
(defun
array1p (name l)
(declare (xargs :guard t))
(and
(symbolp name)
(alistp l)
(let
((header-keyword-list (cdr (assoc-eq :header l))))
(and
(keyword-value-listp header-keyword-list)
(let
((dimensions
(cadr (assoc-keyword :dimensions header-keyword-list)))
(maximum-length
(cadr (assoc-keyword :maximum-length header-keyword-list))))
(and (true-listp dimensions)
(equal (length dimensions) 1)
(integerp (car dimensions))
(integerp maximum-length)
(< 0 (car dimensions))
(< (car dimensions) maximum-length)
(<= maximum-length
*maximum-positive-32-bit-integer*)
(bounded-integer-alistp l (car dimensions))))))))")
(ARRAY2P
(ARRAYS ACL2-BUILT-INS)
"Recognize a 2-dimensional array
Example Form:
(array2p 'delta1 a)
General Form:
(array2p name alist)
where name and alist are arbitrary objects. This function returns t
if alist is a 2-dimensional ACL2 array. Otherwise it returns nil.
The function operates in constant time if alist is the semantic
value of name. See [arrays].
Function: <array2p>
(defun
array2p (name l)
(declare (xargs :guard t))
(and
(symbolp name)
(alistp l)
(let
((header-keyword-list (cdr (assoc-eq :header l))))
(and
(keyword-value-listp header-keyword-list)
(let
((dimensions
(cadr (assoc-keyword :dimensions header-keyword-list)))
(maximum-length
(cadr (assoc-keyword :maximum-length header-keyword-list))))
(and (true-listp dimensions)
(equal (length dimensions) 2)
(let ((d1 (car dimensions))
(d2 (cadr dimensions)))
(and (integerp d1)
(integerp d2)
(integerp maximum-length)
(< 0 d1)
(< 0 d2)
(< (* d1 d2) maximum-length)
(<= maximum-length
*maximum-positive-32-bit-integer*)
(bounded-integer-alistp2 l d1 d2)))))))))")
(ARRAYS
(PROGRAMMING)
"ACL2 arrays and operations on them
Below we begin a detailed presentation of ACL2 arrays. ACL2's
single-threaded objects (see [stobj]) provide a similar
functionality that is generally more efficient when there are
updates (writes), but is also more restrictive.
See [arrays-example] for a brief introduction illustrating the use of
ACL2 arrays.
ACL2 provides relatively efficient 1- and 2-dimensional arrays.
Arrays are awkward to provide efficiently in an applicative
language because the programmer rightly expects to be able to
``modify'' an array object with the effect of changing the behavior
of the element accessing function on that object. This, of course,
does not make any sense in an applicative setting. The element
accessing function is, after all, a function, and its behavior on a
given object is immutable. To ``modify'' an array object in an
applicative setting we must actually produce a new array object.
Arranging for this to be done efficiently is a challenge to the
implementors of the language. In addition, the programmer
accustomed to the von Neumann view of arrays must learn how to use
immutable applicative arrays efficiently.
In this note we explain 1-dimensional arrays. In particular, we
explain briefly how to create, access, and ``modify'' them, how
they are implemented, and how to program with them. 2-dimensional
arrays are dealt with by analogy.
The Logical Description of ACL2 Arrays
An ACL2 1-dimensional array is an object that associates arbitrary
objects with certain integers, called ``indices.'' Every array has
a dimension, dim, which is a positive integer. The indices of an
array are the consecutive integers from 0 through dim-1. To obtain
the object associated with the index i in an array a, one uses
(aref1 name a i). Name is a symbol that is irrelevant to the
semantics of [aref1] but affects the speed with which it computes.
We will talk more about array ``names'' later. To produce a new
array object that is like a but which associates val with index i,
one uses (aset1 name a i val).
An ACL2 1-dimensional array is actually an alist. There is no special
ACL2 function for creating arrays; they are generally built with
the standard list processing functions [list] and [cons]. However,
there is a special ACL2 function, called [compress1], for speeding
up access to the elements of such an alist. We discuss [compress1]
later.
One element of the alist must be the ``header'' of the array. The
[header] of a 1-dimensional array with dimension dim is of the
form:
(:HEADER :DIMENSIONS (dim)
:MAXIMUM-LENGTH max
:DEFAULT obj ; optional
:NAME name ; optional
:ORDER order ; optional values are < (the default), >, or :none/nil
).
Obj may be any object and is called the ``default value'' of the
array. [Max] must be an integer greater than dim. Name must be a
symbol. The :[default] and :name entries are optional; if
:[default] is omitted, the default value is nil. The function
[header], when given a name and a 1- or 2-dimensional array,
returns the [header] of the array. The functions [dimensions],
[maximum-length], and [default] are similar and return the
corresponding fields of the [header] of the array. The role of the
:[dimensions] field is obvious: it specifies the legal indices into
the array. The roles played by the :[maximum-length] and :[default]
fields are described below.
Aside from the [header], the other elements of the alist must each be
of the form (i . val), where i is an integer and 0 <= i < dim, and
val is an arbitrary object.
The :order field of the header is ignored for 2-dimensional arrays.
For 1-dimensional arrays, it specifies the order of keys (i, above)
when the array is compressed as with [compress1], as described
below. An :order of :none or nil specifies no reordering of the
alist by [compress1], and an order of > specifies reordering by
[compress1] so that keys are in descending order. Otherwise, the
alist is reordered by [compress1] so that keys are in ascending
order.
(Aref1 name a i) is [guard]ed so that name must be a symbol, a must
be an array and i must be an index into a. The value of (aref1 name
a i) is either (cdr (assoc i a)) or else is the default value of a,
depending on whether there is a pair in a whose [car] is i. Note
that name is irrelevant to the value of an [aref1] expression. You
might :pe aref1 to see how simple the definition is.
(Aset1 name a i val) is [guard]ed analogously to the [aref1]
expression. The value of the [aset1] expression is essentially
(cons (cons i val) a). Again, name is irrelevant. Note (aset1 name
a i val) is an array, a', with the property that (aref1 name a' i)
is val and, except for index i, all other indices into a' produce
the same value as in a. Note also that if a is viewed as an alist
(which it is) the pair ``binding'' i to its old value is in a' but
``covered up'' by the new pair. Thus, the length of an array grows
by one when [aset1] is done.
Because [aset1] covers old values with new ones, an array produced by
a sequence of [aset1] calls may have many irrelevant pairs in it.
The function [compress1] can remove these irrelevant pairs. Thus,
(compress1 name a) returns an array that is equivalent (vis-a-vis
[aref1]) to a but which may be shorter. For technical reasons, the
alist returned by [compress1] may also list the pairs in a
different order than listed in a.
To prevent arrays from growing excessively long due to repeated
[aset1] operations, [aset1] actually calls [compress1] on the new
alist whenever the length of the new alist exceeds the
:[maximum-length] entry, [max], in the [header] of the array. See
the definition of [aset1] (for example by using :[pe]). This is
primarily just a mechanism for freeing up [cons] space consumed
while doing [aset1] operations. Note however that this [compress1]
call is replaced by a hard error if the header specifies an :order
of :none or nil.
This completes the logical description of 1-dimensional arrays.
2-dimensional arrays are analogous. The :[dimensions] entry of the
[header] of a 2-dimensional array should be (dim1 dim2). A pair of
indices, i and j, is legal iff 0 <= i < dim1 and 0 <= j < dim2. The
:[maximum-length] must be greater than dim1*dim2. [Aref2], [aset2],
and [compress2] are like their counterparts but take an additional
index argument. Finally, the pairs in a 2-dimensional array are of
the form ((i . j) . val).
The Implementation of ACL2 Arrays
Very informally speaking, the function [compress1] ``creates'' an
ACL2 array that provides fast access, while the function [aref1]
``maintains'' fast access. We now describe this informal idea more
carefully.
[Aref1] is essentially [assoc]. If [aref1] were implemented naively
the time taken to access an array element would be linear in the
dimension of the array and the number of ``assignments'' to it (the
number of [aset1] calls done to create the array from the initial
alist). This is intolerable; arrays are ``supposed'' to provide
constant-time access and change.
The apparently irrelevant names associated with ACL2 arrays allow us
to provide constant-time access and change when arrays are used in
``conventional'' ways. The implementation of arrays makes it clear
what we mean by ``conventional.''
Recall that array names are symbols. Behind the scenes, ACL2
associates two objects with each ACL2 array name. The first object
is called the ``semantic value'' of the name and is an alist. The
second object is called the ``raw lisp array'' and is a Common Lisp
array.
When (compress1 name alist) builds a new alist, a', it sets the
semantic value of name to that new alist. Furthermore, it creates a
Common Lisp array and writes into it all of the index/value pairs
of a', initializing unassigned indices with the default value. This
array becomes the raw lisp array of name. [Compress1] then returns
a', the semantic value, as its result, as required by the
definition of [compress1].
When (aref1 name a i) is invoked, [aref1] first determines whether
the semantic value of name is a (i.e., is [eq] to the alist a). If
so, [aref1] can determine the ith element of a by invoking Common
Lisp's aref function on the raw lisp array associated with name.
Note that no linear search of the alist a is required; the
operation is done in constant time and involves retrieval of two
global variables, an [eq] test and jump, and a raw lisp array
access. In fact, an ACL2 array access of this sort is about 5 times
slower than a C array access. On the other hand, if name has no
semantic value or if it is different from a, then [aref1]
determines the answer by linear search of a as suggested by the
assoc-like definition of [aref1]. Thus, [aref1] always returns the
axiomatically specified result. It returns in constant time if the
array being accessed is the current semantic value of the name
used. The ramifications of this are discussed after we deal with
[aset1].
When (aset1 name a i val) is invoked, [aset1] does two [cons]es to
create the new array. Call that array a'. It will be returned as
the answer. (In this discussion we ignore the case in which [aset1]
does a [compress1].) However, before returning, [aset1] determines
if name's semantic value is a. If so, it makes the new semantic
value of name be a' and it smashes the raw lisp array of name with
val at index i, before returning a' as the result. Thus, after
doing an [aset1] and obtaining a new semantic value a', all
[aref1]s on that new array will be fast. Any [aref1]s on the old
semantic value, a, will be slow.
To understand the performance implications of this design, consider
the chronological sequence in which ACL2 (Common Lisp) evaluates
expressions: basically inner-most first, left-to-right,
call-by-value. An array use, such as (aref1 name a i), is ``fast''
(constant-time) if the alist supplied, a, is the value returned by
the most recently executed [compress1] or [aset1] on the name
supplied. In the functional expression of ``conventional'' array
processing, all uses of an array are fast.
The :name field of the [header] of an array is completely irrelevant.
Our convention is to store in that field the symbol we mean to use
as the name of the raw lisp array. But no ACL2 function inspects
:name and its primary value is that it allows the user, by
inspecting the semantic value of the array --- the alist --- to
recall the name of the raw array that probably holds that value. We
say ``probably'' since there is no enforcement that the alist was
compressed under the name in the [header] or that all asets used
that name. Such enforcement would be inefficient.
Some Programming Examples
In the following examples we will use ACL2 ``global variables'' to
hold several arrays. See [@], and see [assign].
Let the [state] global variable a be the 1-dimensional compressed
array of dimension 5 constructed below.
ACL2 !>(assign a (compress1 'demo
'((:header :dimensions (5)
:maximum-length 15
:default uninitialized
:name demo)
(0 . zero))))
Then (aref1 'demo (@ a) 0) is zero and (aref1 'demo (@ a) 1) is
uninitialized.
Now execute
ACL2 !>(assign b (aset1 'demo (@ a) 1 'one))
Then (aref1 'demo (@ b) 0) is zero and (aref1 'demo (@ b) 1) is one.
All of the [aref1]s done so far have been ``fast.''
Note that we now have two array objects, one in the global variable a
and one in the global variable b. B was obtained by assigning to a.
That assignment does not affect the alist a because this is an
applicative language. Thus, (aref1 'demo (@ a) 1) must still be
uninitialized. And if you execute that expression in ACL2 you will
see that indeed it is. However, a rather ugly comment is printed,
namely that this array access is ``slow.'' The reason it is slow is
that the raw lisp array associated with the name demo is the array
we are calling b. To access the elements of a, [aref1] must now do
a linear search. Any reference to a as an array is now
``unconventional;'' in a conventional language like Ada or Common
Lisp it would simply be impossible to refer to the value of the
array before the assignment that produced our b.
Now let us define a function that counts how many times a given
object, x, occurs in an array. For simplicity, we will pass in the
name and highest index of the array:
ACL2 !>(defun cnt (name a i x)
(declare (xargs :guard
(and (array1p name a)
(integerp i)
(>= i -1)
(< i (car (dimensions name a))))
:mode :logic
:measure (nfix (+ 1 i))))
(cond ((zp (1+ i)) 0) ; return 0 if i is at most -1
((equal x (aref1 name a i))
(1+ (cnt name a (1- i) x)))
(t (cnt name a (1- i) x))))
To determine how many times zero appears in (@ b) we can execute:
ACL2 !>(cnt 'demo (@ b) 4 'zero)
The answer is 1. How many times does uninitialized appear in (@ b)?
ACL2 !>(cnt 'demo (@ b) 4 'uninitialized)
The answer is 3, because positions 2, 3 and 4 of the array contain
that default value.
Now imagine that we want to assign 'two to index 2 and then count how
many times the 2nd element of the array occurs in the array. This
specification is actually ambiguous. In assigning to b we produce a
new array, which we might call c. Do we mean to count the
occurrences in c of the 2nd element of b or the 2nd element of c?
That is, do we count the occurrences of uninitialized or the
occurrences of two? If we mean the former the correct answer is 2
(positions 3 and 4 are uninitialized in c); if we mean the latter,
the correct answer is 1 (there is only one occurrence of two in c).
Below are ACL2 renderings of the two meanings, which we call [former]
and [latter]. (Warning: Our description of these examples, and of
an example [fast former] that follows, assumes that only one of
these three examples is actually executed; for example, they are
not executed in sequence. See ``A Word of Warning'' below for more
about this issue.)
(cnt 'demo (aset1 'demo (@ b) 2 'two) 4 (aref1 'demo (@ b) 2)) ; [former]
(let ((c (aset1 'demo (@ b) 2 'two))) ; [latter]
(cnt 'demo c 4 (aref1 'demo c 2)))
Note that in [former] we create c in the second argument of the call
to cnt (although we do not give it a name) and then refer to b in
the fourth argument. This is unconventional because the second
reference to b in [former] is no longer the semantic value of demo.
While ACL2 computes the correct answer, namely 2, the execution of
the [aref1] expression in [former] is done slowly.
A conventional rendering with the same meaning is
(let ((x (aref1 'demo (@ b) 2))) ; [fast former]
(cnt 'demo (aset1 'demo (@ b) 2 'two) 4 x))
which fetches the 2nd element of b before creating c by assignment.
It is important to understand that [former] and [fast former] mean
exactly the same thing: both count the number of occurrences of
uninitialized in c. Both are legal ACL2 and both compute the same
answer, 2. Indeed, we can symbolically transform [fast former] into
[former] merely by substituting the binding of x for x in the body
of the [let]. But [fast former] can be evaluated faster than
[former] because all of the references to demo use the then-current
semantic value of demo, which is b in the first line and c
throughout the execution of the cnt in the second line. [Fast
former] is the preferred form, both because of its execution speed
and its clarity. If you were writing in a conventional language you
would have to write something like [fast former] because there is
no way to refer to the 2nd element of the old value of b after
smashing b unless it had been saved first.
We turn now to [latter]. It is both clear and efficient. It creates c
by assignment to b and then it fetches the 2nd element of c, two,
and proceeds to count the number of occurrences in c. The answer is
1. [Latter] is a good example of typical ACL2 array manipulation:
after the assignment to b that creates c, c is used throughout.
It takes a while to get used to this because most of us have grown
accustomed to the peculiar semantics of arrays in conventional
languages. For example, in raw lisp we might have written something
like the following, treating b as a ``global variable'':
(cnt 'demo (aset 'demo b 2 'two) 4 (aref 'demo b 2))
which sort of resembles [former] but actually has the semantics of
[latter] because the b from which aref fetches the 2nd element is
not the same b used in the aset! The array b is destroyed by the
aset and b henceforth refers to the array produced by the aset, as
written more clearly in [latter].
A Word of Warning: Users must exercise care when experimenting with
[former], [latter] and [fast former]. Suppose you have just created
b with the assignment shown above,
ACL2 !>(assign b (aset1 'demo (@ a) 1 'one))
If you then evaluate [former] in ACL2 it will complain that the
[aref1] is slow and compute the answer, as discussed. Then suppose
you evaluate [latter] in ACL2. From our discussion you might expect
it to execute fast --- i.e., issue no complaint. But in fact you
will find that it complains repeatedly. The problem is that the
evaluation of [former] changed the semantic value of demo so that
it is no longer b. To try the experiment correctly you must make b
be the semantic value of demo again before the next example is
evaluated. One way to do that is to execute
ACL2 !>(assign b (compress1 'demo (@ b)))
before each expression. Because of issues like this it is often hard
to experiment with ACL2 arrays at the top-level. We find it easier
to write functions that use arrays correctly and efficiently than
to so use them interactively.
This last assignment also illustrates a very common use of
[compress1]. While it was introduced as a means of removing
irrelevant pairs from an array built up by repeated assignments, it
is actually most useful as a way of insuring fast access to the
elements of an array.
Many array processing tasks can be divided into two parts. During the
first part the array is built. During the second part the array is
used extensively but not modified. If your [programming] task can
be so divided, it might be appropriate to construct the array
entirely with list processing, thereby saving the cost of
maintaining the semantic value of the name while few references are
being made. Once the alist has stabilized, it might be worthwhile
to treat it as an array by calling [compress1], thereby gaining
constant time access to it.
ACL2's theorem prover uses this technique in connection with its
implementation of the notion of whether a [rune] is [disable]d or
not. Associated with every [rune] is a unique integer index, called
its ``nume.'' When each rule is stored, the corresponding nume is
stored as a component of the rule. [Theories] are lists of [rune]s
and membership in the ``current theory'' indicates that the
corresponding rule is [enable]d. But these lists are very long and
membership is a linear-time operation. So just before a proof
begins we map the list of [rune]s in the current theory into an
alist that pairs the corresponding numes with t. Then we compress
this alist into an array. Thus, given a rule we can obtain its nume
(because it is a component) and then determine in constant time
whether it is [enable]d. The array is never modified during the
proof, i.e., [aset1] is never used in this example. From the
logical perspective this code looks quite odd: we have replaced a
linear-time membership test with an apparently linear-time [assoc]
after going to the trouble of mapping from a list of [rune]s to an
alist of numes. But because the alist of numes is an array, the
``apparently linear-time [assoc]'' is more apparent than real; the
operation is constant-time.
Subtopics
[Aref1]
Access the elements of a 1-dimensional array
[Aref2]
Access the elements of a 2-dimensional array
[Array1p]
Recognize a 1-dimensional array
[Array2p]
Recognize a 2-dimensional array
[Arrays-example]
An example illustrating ACL2 arrays
[Aset1]
Set the elements of a 1-dimensional array
[Aset2]
Set the elements of a 2-dimensional array
[Compress1]
Remove irrelevant pairs from a 1-dimensional array
[Compress2]
Remove irrelevant pairs from a 2-dimensional array
[Default]
Return the :default from the [header] of a 1- or 2-dimensional array
[Dimensions]
Return the :dimensions from the [header] of a 1- or 2-dimensional
array
[Flush-compress]
Flush the under-the-hood array for the given name
[Header]
Return the header of a 1- or 2-dimensional array
[Maximum-length]
Return the :maximum-length from the [header] of an array
[Slow-array-warning]
A warning or error issued when [arrays] are used inefficiently")
(ARRAYS-EXAMPLE
(ARRAYS)
"An example illustrating ACL2 arrays
The example below illustrates the use of ACL2 arrays. It is not, of
course, a substitute for the detailed explanations provided
elsewhere (see [arrays], including subtopics).
ACL2 !>(defun defarray (name size initial-element)
(compress1 name
(cons (list :HEADER
:DIMENSIONS (list size)
:MAXIMUM-LENGTH (1+ size)
:DEFAULT initial-element
:NAME name)
nil)))
Since DEFARRAY is non-recursive, its admission is trivial. We observe
that the type of DEFARRAY is described by the theorem
(AND (CONSP (DEFARRAY NAME SIZE INITIAL-ELEMENT))
(TRUE-LISTP (DEFARRAY NAME SIZE INITIAL-ELEMENT))).
We used the :type-prescription rule COMPRESS1.
Summary
Form: ( DEFUN DEFARRAY ...)
Rules: ((:TYPE-PRESCRIPTION COMPRESS1))
Warnings: None
Time: 0.02 seconds (prove: 0.00, print: 0.02, other: 0.00)
DEFARRAY
ACL2 !>(assign my-ar (defarray 'a1 5 17))
((:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1))
ACL2 !>(aref1 'a1 (@ my-ar) 3)
17
ACL2 !>(aref1 'a1 (@ my-ar) 8)
ACL2 Error in TOP-LEVEL: The guard for the function symbol AREF1,
which is
(AND (ARRAY1P NAME L) (INTEGERP N) (>= N 0) (< N (CAR (DIMENSIONS NAME L)))),
is violated by the arguments in the call (AREF1 'A1 '(#) 8).
ACL2 !>(assign my-ar (aset1 'a1 (@ my-ar) 3 'xxx))
((3 . XXX)
(:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1))
ACL2 !>(aref1 'a1 (@ my-ar) 3)
XXX
ACL2 !>(aset1 'a1 (@ my-ar) 3 'yyy) ; BAD: (@ my-ar) now points to
; an old copy of the array!
((3 . YYY)
(3 . XXX)
(:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1))
ACL2 !>(aref1 'a1 (@ my-ar) 3) ; Because of \"BAD\" above, the array
; access is done using assoc rather
; than Lisp aref, hence is slower;
; but the answer is still correct,
; reflecting the value in (@ my-ar),
; which was not changed above.
**********************************************************
Slow Array Access! A call of AREF1 on an array named
A1 is being executed slowly. See :DOC slow-array-warning
**********************************************************
XXX
ACL2 !>")
(ASET1
(ARRAYS ACL2-BUILT-INS)
"Set the elements of a 1-dimensional array
Example Form:
(aset1 'delta1 a (+ i k) 27)
General Form:
(aset1 name alist index val)
where name is a symbol, alist is a 1-dimensional array named name,
index is a legal index into alist, and val is an arbitrary object.
See [arrays] for details. Roughly speaking this function
``modifies'' alist so that the value associated with index is val.
More precisely, it returns a new array, alist', of the same name
and dimension as alist that, under [aref1], is everywhere equal to
alist except at index where the result is val. That is, (aref1 name
alist' i) is (aref1 name alist i) for all legal indices i except
index, where (aref1 name alist' i) is val.
In order to ``modify'' alist, aset1 [cons]es a new pair onto the
front. If the length of the resulting alist exceeds the
:[maximum-length] entry in the array [header], aset1 compresses the
array as with [compress1].
It is generally expected that the ``semantic value'' of name will be
alist (see [arrays]). This function operates in virtually constant
time whether this condition is true or not (unless the [compress1]
operation is required). But the value returned by this function
cannot be used efficiently by subsequent aset1 operations unless
alist is the semantic value of name when aset1 is executed. Thus,
if the condition is not true, aset1 prints a slow array warning to
the comment window. See [slow-array-warning].
Function: <aset1>
(defun
aset1 (name l n val)
(declare (xargs :guard (and (array1p name l)
(integerp n)
(>= n 0)
(< n (car (dimensions name l))))))
(let ((l (cons (cons n val) l)))
(cond ((> (length l) (maximum-length name l))
(compress1 name l))
(t l))))")
(ASET2
(ARRAYS ACL2-BUILT-INS)
"Set the elements of a 2-dimensional array
Example Form:
(aset2 'delta1 a i j 27)
General Form:
(aset2 name alist i j val)
where name is a symbol, alist is a 2-dimensional array named name, i
and j are legal indices into alist, and val is an arbitrary object.
See [arrays] for details. Roughly speaking this function
``modifies'' alist so that the value associated with (i . j) is
val. More precisely, it returns a new array, alist', of the same
name and dimension as alist that, under [aref2], is everywhere
equal to alist except at (i . j) where the result is val. That is,
(aref2 name alist' x y) is (aref2 name alist x y) for all legal
indices x y except i and j where (aref2 name alist' i j) is val.
In order to ``modify'' alist, aset2 [cons]es a new pair onto the
front. If the length of the resulting alist exceeds the
:[maximum-length] entry in the array [header], aset2 compresses the
array as with [compress2].
It is generally expected that the ``semantic value'' of name will be
alist (see [arrays]). This function operates in virtually constant
time whether this condition is true or not (unless the [compress2]
operation is required). But the value returned by this function
cannot be used efficiently by subsequent aset2 operations unless
alist is the semantic value of name when aset2 is executed. Thus,
if the condition is not true, aset2 prints a slow array warning to
the comment window. See [slow-array-warning].
Function: <aset2>
(defun
aset2 (name l i j val)
(declare (xargs :guard (and (array2p name l)
(integerp i)
(>= i 0)
(< i (car (dimensions name l)))
(integerp j)
(>= j 0)
(< j (cadr (dimensions name l))))))
(let ((l (cons (cons (cons i j) val) l)))
(cond ((> (length l) (maximum-length name l))
(compress2 name l))
(t l))))")
(ASH
(NUMBERS ACL2-BUILT-INS)
"Arithmetic shift operation
(ash i c) is the result of taking the two's complement representation
of the integer i and shifting it by c bits: shifting left and
padding with c 0 bits if c is positive, shifting right and dropping
(abs c) bits if c is negative, and simply returning i if c is 0.
The [guard] for ash requires that its arguments are integers.
Ash is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <ash>
(defun ash (i c)
(declare (xargs :guard (and (integerp i) (integerp c))))
(floor (* (ifix i) (expt 2 c)) 1))")
(ASSERT$
(ERRORS ACL2-BUILT-INS)
"Cause a hard error if the given test is false
General Form:
(assert$ test form)
where test returns a single value and form is arbitrary.
Semantically, this call of assert$ is equivalent to form. However,
it causes a hard error if the value of test is nil. That hard error
invokes the function [illegal], which has a [guard] that is equal
to nil; so if you use assert$ in code for which you verify guards,
then a proof obligation will be that the occurrence of test is
never nil.
For a related utility, see [assert*]. Both assert$ and assert* create
a [guard] proof obligation (when used in a definition made in
[logic]-mode). However, assert$ checks the assertion at runtime,
while assert* does not.")
(ASSERT*
(ERRORS ACL2-BUILT-INS)
"Create a [guard] proof obligation that given test holds
General Form:
(assert* test form)
where test returns a single value and form is arbitrary.
Semantically, this call of assert* is equivalent to form. However,
a [guard] proof obligation is created that test holds, when used in
a definition made in [logic]-mode).
For a related utility, see [assert$]. Both assert$ and assert* create
a [guard] proof obligation (when used in a definition made in
[logic]-mode). However, assert$ checks the assertion at runtime,
while assert* does not.
Macro: <assert*>
(defmacro assert* (test form)
(cons 'and
(cons (cons 'mbt* (cons test 'nil))
(cons form 'nil))))")
(ASSERT-EVENT
(EVENTS)
"Assert that a given form returns a non-nil value
Examples:
(assert-event (equal (+ 3 4) 7))
(assert-event (equal (+ 3 4) 7) :msg (msg \"Error: ~x0\" 'equal-check))
(assert-event (equal (+ 3 4) 7) :on-skip-proofs t)
General Forms:
(assert-event form)
(assert-event form :on-skip-proofs t)
Assert-event takes a ground form, i.e., one with no free variables;
[stobj]s are allowed but only a single non-[stobj] value can be
returned. The form is then evaluated and if the result is nil, then
a so-called hard error (see [er]) results. This evaluation is
however not done if proofs are being skipped, as during
[include-book] (also see [skip-proofs] and see [ld-skip-proofsp]),
unless :on-skip-proofs t is supplied.
Normally, if an assert-event call fails then a generic failure
message is printed, showing the offending form. However, if keyword
argument :msg is supplied, then the failure message is printed as
with [fmt] argument ~@0; see [fmt]. In particular, :msg is
typically a string or a call (msg str arg-0 arg-1 ... arg-k), where
str is a string and each arg-i is the value to be associated with
#\\i upon formatted printing (as with [fmt]) of the string str.
This form may be put into a book to be certified (see [books]),
because assert-event is a macro whose calls expand to calls of
value-triple (see [embedded-event-form]). When certifying a book,
guard-checking is off, as though (set-guard-checking nil) has been
evaluated; see [set-guard-checking]. That, together with a ``safe
mode,'' guarantees that assert-event forms are evaluated in the
logic without guard violations while certifying a book.")
(ASSIGN
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Assign to a global variable in [state]
Examples:
(assign x (expt 2 10))
(assign a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B))
General Form:
(assign symbol term)
where symbol is any symbol (with certain enforced exclusions to avoid
overwriting ACL2 system ``globals'') and term is any ACL2 term that
could be evaluated at the top-level. Assign evaluates the term,
stores the result as the value of the given symbol in the
global-table of [state], and returns the result. (Note: the actual
implementation of the storage of this value is much more efficient
than this discussion of the logic might suggest.) Assign is a macro
that effectively expands to the more complicated but
understandable:
(pprogn (f-put-global 'symbol term state)
(mv nil (f-get-global 'symbol state) state)).
The macro f-put-global is closely related to [assign]: (assign var
val) macroexpands to (f-put-global 'var val state).
The macro [@] gives convenient access to the value of such globals.
The :[ubt] operation has no effect on the global-table of [state].
Thus, you may use these globals to hang onto useful data structures
even though you may undo back past where you computed and saved
them.")
(ASSOC
(ALISTS ACL2-BUILT-INS)
"Look up key in association list
General Forms:
(assoc x alist)
(assoc x alist :test 'eql) ; same as above (eql as equality test)
(assoc x alist :test 'eq) ; same, but eq is equality test
(assoc x alist :test 'equal) ; same, but equal is equality test
(Assoc x alist) is the first member of alist whose [car] is x, or nil
if no such member exists. The optional keyword, :TEST, has no
effect logically, but provides the test (default [eql]) used for
comparing x with the [car]s of successive elements of alist.
The [guard] for a call of assoc depends on the test. In all cases,
the second argument must satisfy [alistp]. If the test is [eql],
then either the first argument must be suitable for [eql] (see
[eqlablep]) or the second argument must satisfy [eqlable-alistp].
If the test is [eq], then either the first argument must be a
symbol or the second argument must satisfy [symbol-alistp].
See [equality-variants] for a discussion of the relation between
assoc and its variants:
(assoc-eq x alist) is equivalent to (assoc x alist :test 'eq);
(assoc-equal x alist) is equivalent to (assoc x alist :test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function assoc-equal.
Assoc is defined by Common Lisp. See any Common Lisp documentation
for more information.
Function: <assoc-equal>
(defun assoc-equal (x alist)
(declare (xargs :guard (alistp alist)))
(cond ((endp alist) nil)
((equal x (car (car alist)))
(car alist))
(t (assoc-equal x (cdr alist)))))")
(ASSOC-EQ (POINTERS) "See [assoc].")
(ASSOC-EQUAL (POINTERS) "See [assoc].")
(ASSOC-KEYWORD
(KEYWORD-VALUE-LISTP ACL2-BUILT-INS)
"Look up key in a [keyword-value-listp]
If l is a list of even length of the form (k1 a1 k2 a2 ... kn an),
where each ki is a keyword, then (assoc-keyword key l) is the first
tail of l starting with key if key is some ki, and is nil
otherwise.
The [guard] for (assoc-keyword key l) is (keyword-value-listp l).
Function: <assoc-keyword>
(defun assoc-keyword (key l)
(declare (xargs :guard (keyword-value-listp l)))
(cond ((endp l) nil)
((eq key (car l)) l)
(t (assoc-keyword key (cddr l)))))")
(ASSOC-STRING-EQUAL
(ALISTS ACL2-BUILT-INS)
"Look up key, a string, in association list
(Assoc-string-equal x alist) is similar to [assoc-equal]. However,
for string x and alist alist, the comparison of x with successive
keys in alist is done using [string-equal] rather than [equal].
The [guard] for assoc-string-equal requires that x is a string and
alist is an alist.
Function: <assoc-string-equal>
(defun
assoc-string-equal (str alist)
(declare
(xargs :guard (and (stringp str)
(standard-char-listp (coerce str 'list))
(standard-string-alistp alist))))
(cond ((endp alist) nil)
((string-equal str (car (car alist)))
(car alist))
(t (assoc-string-equal str (cdr alist)))))")
(ATOM
(CONSES ACL2-BUILT-INS)
"Recognizer for atoms
(atom x) is true if and only if x is an atom, i.e., not a [cons]
pair.
Atom has a [guard] of t, and is a Common Lisp function. See any
Common Lisp documentation for more information.
Function: <atom>
(defun atom (x)
(declare (xargs :guard t))
(not (consp x)))
Subtopics
[Atom-listp]
Recognizer for a true list of [atom]s
[Good-atom-listp]
Recognizer for a true list of ``good'' [atom]s")
(ATOM-LISTP
(ATOM LISTS ACL2-BUILT-INS)
"Recognizer for a true list of [atom]s
The predicate atom-listp tests whether its argument is a [true-listp]
of [atom]s, i.e., of non-conses.
Also see [good-atom-listp].
Function: <atom-listp>
(defun atom-listp (lst)
(declare (xargs :guard t))
(cond ((atom lst) (eq lst nil))
(t (and (atom (car lst))
(atom-listp (cdr lst))))))")
(A_FLYING_TOUR_OF_ACL2
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"A Flying Tour of ACL2
[{IMAGE}]
On this tour you will learn a little about what ACL2 is for rather
than how ACL2 works. At the top and bottom bottom of the ``page''
there are ``flying tour'' icons. Click on either icon to go to the
next page of the tour.
The tour visits the following topics sequentially. But on your first
reading, don't navigate through the tour by clicking on these
links; they are shown as live links only so that later you can
determine what you've visited. Instead, just use the flying tour
icons.
The Flight Plan
* [This Documentation]
* [What is ACL2?]
* [Mathematical Logic]
* [Mechanical Theorem Proving]
* [Mathematical Models in General]
* [Mathematical Models of Computing Machines]
[Formalizing Models]
[Running Models]
[Symbolic Execution of Models]
[Proving Theorems about Models]
* Requirements of ACL2
[The User's Skills]
[Training]
[Host System]
On your first reading, don't explore other links you see in the tour.
Some of them lead to the Walking Tour, which you can take
coherently when you finish this tour. Others lead into the
extensive hyptertext documentation and you are liable to get lost
there unless you're trying to answer a specific question. We intend
the tour to take about 10 minutes of your time.
[{IMAGE}]")
(A_SKETCH_OF_HOW_THE_REWRITER_WORKS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"A Sketch of How the Rewriter Works
Below we show the first target term, extracted from the current
conjecture. Below it we show the associativity rule.
{IMAGE}
The variables of the rewrite rule are instantiated so that the
left-hand side of the rule matches the target:
variable term from target
a x1
b x2
c (app x3 x4)
Then the target is replaced by the instantiated right-hand side of
the rule.
Sometimes rules have hypotheses. To make a long story short, if the
rule has hypotheses, then after matching the left-hand side, the
rewriter instantiates the hypotheses and rewrites them recursively.
This is called backchaining. If they all rewrite to true, then the
target is replaced as above.
We discuss the rewriter in more detail in the extended introduction
to how to use the theorem prover, see
[introduction-to-the-theorem-prover], which we will recommend you
work through after you have finished the two tours.")
(A_TINY_WARNING_SIGN
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"A Tiny Warning Sign
{IMAGE}
This warning sign, which usually appears as ``{ICON}'', indicates
that the link it marks takes you into ACL2's online documentation.
The documentation is a vast graph of documented topics intended to
help the user of ACL2 rather than the potential user. If you are
exploring ACL2's home page to learn about the system, perhaps you
should go back rather than follow the link marked with this sign.
But you are welcome to explore the online documentation as well.
Good luck.")
(A_TRIVIAL_PROOF (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"A Trivial Proof
{IMAGE}")
(A_TYPICAL_STATE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"A Typical State
[{IMAGE}]
{IMAGE}
Observe that the states in typical models talk about
booleans integers vectors records caches
bits symbols arrays stacks files
characters strings sequences tables directories
These objects are discrete rather than continuous; furthermore they
are built incrementally or inductively by repeatedly using
primitive operations to put together smaller pieces.
The functions we need to manipulate these objects do things like
concatenate, reverse, sort, search, count, etc.
[{IMAGE}]")
(A_WALKING_TOUR_OF_ACL2
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"A Walking Tour of ACL2
[{IMAGE}]
On this tour you will learn a little more about the ACL2 logic, the
theorem prover, and the user interface.
This time we will stick with really simple things, such as the
associativity of list concatenation.
We assume you have taken the Flying Tour but that you did not
necessarily follow all the ``off-tour'' links because we encouraged
you not to. With the Walking Tour we encourage you to visit
off-tour links --- provided they are not marked with the tiny
warning sign ([{ICON}]). But they are ``branches'' in the tour that
lead to ``dead ends.'' When you reach a dead end, remember to use
your browser's Back Button to return to the Walking Tour to
continue.
When you get to the end of the tour we'll give you a chance to repeat
quickly both the Flying and the Walking Tours to visit any off-tour
links still of interest.
[{IMAGE}]")
(BACKCHAIN-LIMIT
(REWRITE META LINEAR TYPE-PRESCRIPTION)
"Limiting the effort expended on relieving hypotheses
Before ACL2 can apply a rule with hypotheses, it must establish that
the hypotheses are true. (We ignore the relaxing of this
requirement afforded by [case-split]s and [force]d hypotheses.)
ACL2 typically establishes each hypothesis by backchaining ---
instantiating the hypothesis and then rewriting it recursively.
Here we describe how ACL2 allows the user to limit backchaining. At
the end, below, we describe the function [backchain-limit].
Each hypothesis of a [rewrite], [meta], [linear], or
[type-prescription] rule is assigned a backchain-limit when the
rule is stored. By default, this limit is nil, denoting infinity
(no limit). However, the value used for the default may be set to a
non-negative integer (or to nil) by the user; see
[set-default-backchain-limit]. The default is overridden when a
:backchain-limit-lst is supplied explicitly with the rule; see
[rule-classes]. The number of recursive applications of
backchaining starting with the hypothesis of a rule is limited to
the backchain-limit associated with that hypothesis.
Moreover, the user may set global backchain-limits that limit the
total backchaining depth. See [set-backchain-limit]. One limit is
for the use of [rewrite], [meta], and [linear] rules, while the
other limit is for so-called ``[type-set] reasoning'', which uses
rules of class [type-prescription] rules. The two limits operate
independently. Below, we discuss the first kind of backchain
limits, i.e., for other than [type-prescription] rules, except as
otherwise indicated; but the mechanism for those rules is similar.
Below we lay out the precise sense in which a global backchain-limit
interacts with the backchain-limits of individual rules in order to
limit backchaining. But first we note that when further
backchaining is disallowed, ACL2 can still prove a hypothesis in a
given context by using that contextual information. In fact,
[type-set] reasoning may be used (except that a weaker version of
it is used in the second case above, i.e., where we are already
doing type-set reasoning). Thus, the relieving of hypotheses may be
limited to the use of contextual information (without backchaining,
i.e., without recursively rewriting hypotheses) by executing
:set-backchain-limit 0.
Recall that there are two sorts of backchain limits: those applied to
hypotheses of individual rules, as assigned by their
:[rule-classes] or else taken from the default (see
[set-default-backchain-limit]); and the global limit, initially nil
(no limit) but settable with :[set-backchain-limit]. Here is how
these two types of limits interact to limit backchaining, i.e.,
recursive rewriting of hypotheses. ACL2 maintains a current
backchain limit, which is the limit on the depth of recursive calls
to the rewriter, as well as a current backchain depth, which is
initially 0 and is incremented each time ACL2 backchains (and is
decremented when a backchain completes). When ACL2 begins to
rewrite a literal (crudely, one of the ``top-level'' terms of the
goal currently being worked on), it sets the current
backchain-limit to the global value, which is initially nil but can
be set using :[set-backchain-limit]. When ACL2 is preparing to
relieve a hypothesis by backchaining (hence, after it has already
tried type-set reasoning), it first makes sure that the current
backchain limit is greater than the current backchain depth. If
not, then it refuses to relieve that hypothesis. Otherwise, it
increments the current backchain depth and calculates a new current
backchain-limit by taking the minimum of two values: the existing
current backchain-limit, and the sum of the current backchain depth
and the backchain-limit associated with the hypothesis. Thus, ACL2
only modifies the current backchain-limit if it is necessary to
decrease that limit in order to respect the backchain limit
associated with the hypothesis.
We illustrate with the following examples.
; We stub out some functions so that we can reason about them.
(defstub p0 (x) t)
(defstub p1 (x) t)
(defstub p2 (x) t)
(defstub p3 (x) t)
; Initially, the default-backchain-limit is nil, or infinite.
(defaxiom p2-implies-p1-limitless
(implies (p2 x)
(p1 x)))
; The following rule will have a backchain-limit of 0.
(defaxiom p1-implies-p0-limit-0
(implies (p1 x)
(p0 x))
:rule-classes ((:rewrite :backchain-limit-lst 0)))
; We have (p2 x) ==> (p1 x) ==> (p0 x). We wish to establish that
; (p2 x) ==> (p0 x). Normally, this would be no problem, but here
; we fail because ACL2 cannot establish (p0 x) by type-set reasoning
; alone.
(thm
(implies (p2 x)
(p0 x)))
; We set the default-backchain-limit (for rewriting) to 1.
:set-default-backchain-limit 1
; The following is more powerful than p1-implies-p0-limit-0
; because it can use rewrite rules to establish (p1 x).
(defaxiom p1-implies-p0-limit-1
(implies (p1 x)
(p0 x)))
; This theorem will succeed:
(thm
(implies (p2 x)
(p0 x)))
; We return the default-backchain-limit to its initial value.
:set-default-backchain-limit nil
; Here is our last axiom.
(defaxiom p3-implies-p2-limitless
(implies (p3 x)
(p2 x)))
; We now have (p3 x) ==> (p2 x) ==> (p1 x) ==> (p0 x). However the
; rule p1-implies-p0-limit-1 has a backchain-limit of 1; hence we
; are not allowed to backchain far enough back to use
; p3-implies-p2-limitless. We therefore lose.
(defthm will-fail
(implies (p3 x)
(p0 x)))
Finally, we remark that to see the current global backchain-limits,
issue the following commands.
(backchain-limit wrld :ts) ; backchain limit for type-set reasoning
(backchain-limit wrld :rewrite) ; backchain limit for rewriting
Subtopics
[Set-backchain-limit]
Sets the backchain-limit used by the type-set and rewriting
mechanisms
[Set-default-backchain-limit]
Sets the default backchain-limit used when admitting a rule")
(BACKCHAIN-LIMIT-RW (POINTERS)
"See [hints] for keyword :backchain-limit-rw.")
(BACKCHAINING
(RULE-CLASSES)
"Attempting to relieve the hypotheses of a rule
When the theorem prover attempts to apply a rule (e.g., a [rewrite]
rule), it must relieve (prove) the hypotheses of that rule. In the
ACL2 community, this process of relieving hypotheses is called
backchaining.
There is no such thing as a backchaining or backward-chaining rule
class (see [rule-classes]) in ACL2.")
(BACKTRACK (POINTERS)
"See [hints] for keyword :backtrack.")
(BASICS
(PROGRAMMING)
"Basic control structures for [programming] like [if] and [cond],
binding operators like [let] and [flet], multiple-value constructs
like [mv], and so forth.
Subtopics
[ACL2-count]
A commonly used measure for justifying recursion
[And]
Conjunction
[Booleanp]
Recognizer for booleans
[Case]
Conditional based on if-then-else using [eql]
[Case-match]
Pattern matching or destructuring
[Cond]
Conditional based on if-then-else
[Equal]
True equality
[Flet]
Local binding of function symbols
[Good-bye]
Quit entirely out of Lisp
[Identity]
The identity function
[If]
If-then-else function
[Iff]
Logical ``if and only if''
[Implies]
Logical implication
[Let]
Binding of lexically scoped (local) variables
[Let*]
Binding of lexically scoped (local) variables
[Mv]
Returning a multiple value
[Not]
Logical negation
[Null]
Recognizer for the empty list
[Or]
Disjunction
[Progn$]
Execute a sequence of forms and return the value of the last one
[Quote]
Create a constant
[Return-last]
Return the last argument, perhaps with side effects
[Xor]
Logical ``exclusive or''")
(BDD
(ACL2)
"Ordered binary decision diagrams with rewriting
Ordered binary decision diagrams (OBDDs, often simply called BDDs)
are a technique, originally published by Randy Bryant, for the
efficient simplification of Boolean expressions. In ACL2 we combine
this technique with rewriting to handle arbitrary ACL2 terms that
can represent not only Boolean values, but non-Boolean values as
well. In particular, we provide a setting for deciding equality of
bit vectors (lists of Boolean values).
An introduction to BDDs for the automated reasoning community may be
found in ``Introduction to the OBDD Algorithm for the ATP
Community'' by J Moore, Journal of Automated Reasoning (1994), pp.
33-45. (This paper also appears as Technical Report #84 from
Computational Logic, Inc.)
Further information about BDDs in ACL2 can be found in the subtopics
of this [documentation] section. In particular, see
[bdd-introduction] for a good starting place that provides a number
of examples.
See [hints] for a description of :bdd hints. For quick reference,
here is an example; but only the :vars part of the hint is
required, as explained in the documentation for [hints]. The values
shown are the defaults.
(:vars nil :bdd-constructors (cons) :prove t :literal :all)
We suggest that you next visit the documentation topic
[bdd-introduction].
Subtopics
[Bdd-algorithm]
Summary of the BDD algorithm in ACL2
[Bdd-introduction]
Examples illustrating the use of BDDs in ACL2
[If*]
For conditional rewriting with BDDs
[Obdd]
Ordered binary decision diagrams with rewriting
[Show-bdd]
Inspect failed BDD proof attempts")
(BDD-ALGORITHM
(BDD)
"Summary of the BDD algorithm in ACL2
The BDD algorithm in ACL2 uses a combination of manipulation of IF
terms and unconditional rewriting. In this discussion we begin with
some relevant mathematical theory. This is followed by a
description of how ACL2 does BDDs, including concluding discussions
of soundness, completeness, and efficiency.
We recommend that you read the other documentation about BDDs in ACL2
before reading the rather technical material that follows. See
[bdd].
Here is an outline of our presentation. Readers who want a user
perspective, without undue mathematical theory, may wish to skip to
Part (B), referring to Part (A) only on occasion if necessary.
(A) Mathematical Considerations
(A1) BDD term order
(A2) BDD-constructors and BDD terms, and their connection with
aborting the BDD algorithm
(A3) Canonical BDD terms
(A4) A theorem stating the equivalence of provable and syntactic
equality for canonical BDD terms
(B) Algorithmic Considerations
(B1) BDD rules (rules used by the rewriting portion of the ACL2 BDD
algorithm)
(B2) Terms ``known to be Boolean''
(B3) An ``IF-lifting'' operation used by the algorithm, as well as an
iterative version of that operation
(B4) The ACL2 BDD algorithm
(B5) Soundness and Completeness of the ACL2 BDD algorithm
(B6) Efficiency considerations
(A) Mathematical Considerations
(A1) BDD term order
Our BDD algorithm creates a total ``BDD term order'' on ACL2 terms,
on the fly. We use this order in our discussions below of
IF-lifting and of canonical BDD terms, and in the algorithm's use
of commutativity. The particular order is unimportant, except that
we guarantee (for purposes of commutative functions) that constants
are smaller in this order than non-constants.
(A2) BDD-constructors (assumed to be '(cons)) and BDD terms
We take as given a list of function symbols that we call the
``BDD-constructors.'' By default, the only BDD-constructor is
[cons], although it is legal to specify any list of function
symbols as the BDD-constructors, either by using the
[ACL2-defaults-table] (see [ACL2-defaults-table]) or by supplying a
:BDD-CONSTRUCTORS hint (see [hints]). Warning: this capability is
largely untested and may produce undesirable results. Henceforth,
except when explicitly stated to the contrary, we assume that
BDD-constructors is '(cons).
Roughly speaking, a [bdd] term is the sort of [term] produced by our
BDD algorithm, namely a tree with all [cons] nodes lying above all
non-CONS nodes. More formally, a [term] is said to be a [bdd] term
if it contains no subterm of either of the following forms, where f
is not CONS.
(f ... (CONS ...) ...)
(f ... 'x ...) ; where (consp x) = t
We will see that whenever the BDD algorithm attempts to create a
[term] that is not a [bdd] term, it aborts instead. Thus, whenever
the algorithm completes without aborting, it creates a [bdd] term.
(A3) Canonical BDD terms
We can strengthen the notion of ``BDD term'' to a notion of
``canonical BDD term'' by imposing the following additional
requirements, for every subterm of the form (IF x y z):
(a) x is a variable, and it precedes (in the BDD term order) every
variable occurring in y or z;
(b) y and z are syntactically distinct; and,
(c) it is not the case that y is t and z is nil.
We claim that it follows easily from our description of the BDD
algorithm that every term it creates is a canonical BDD term,
assuming that the variables occurring in all such terms are treated
by the algorithm as being Boolean (see (B2) below) and that the
terms contain no function symbols other than IF and CONS. Thus,
under those assumptions the following theorem shows that the BDD
algorithm never creates distinct terms that are provably equal, a
property that is useful for completeness and efficiency (as we
explain in (B5) and (B6) below).
(A4) Provably equal canonical BDD terms are identical
We believe that the following theorem and proof are routine
extensions of a standard result and proof to terms that allow calls
of CONS.
Theorem. Suppose that t1 and t2 are canonical BDD terms that contain
no function symbols other than IF and CONS. Also suppose that
(EQUAL t1 t2) is a theorem. Then t1 and t2 are syntactically
identical.
Proof of theorem: By induction on the total number of symbols
occurring in these two terms. First suppose that at least one term
is a variable; without loss of generality let it be t1. We must
prove that t2 is syntactically the same as t1. Now it is clearly
consistent that (EQUAL t1 t2) is false if t2 is a call of CONS (to
see this, simply let t1 be an value that is not a CONSP).
Similarly, t2 cannot be a constant or a variable other than t1. The
remaining possibility to rule out is that t2 is of the form (IF t3
t4 t5), since by assumption its function symbol must be IF or CONS
and we have already handled the latter case. Since t2 is canonical,
we know that t3 is a variable. Since (EQUAL t1 t2) is provable,
i.e.,
(EQUAL t1 (if t3 t4 t5))
is provable, it follows that we may substitute either t or nil for t3
into this equality to obtain two new provable equalities. First,
suppose that t1 and t3 are distinct variables. Then these
substitutions show that t1 is provably equal to both t4 and t5
(since t3 does not occur in t4 or t5 by property (a) above, as t2
is canonical), and hence t4 and t5 are provably equal to each
other, which implies by the inductive hypothesis that they are the
same term --- and this contradicts the assumption that t2 is
canonical (property (b)). Therefore t1 and t3 are the same
variable, i.e., the equality displayed above is actually (EQUAL t1
(if t1 t4 t5)). Substituting t and then nil for t1 into this
provable equality lets us prove (EQUAL t t4) and (EQUAL nil t5),
which by the inductive hypothesis implies that t4 is
(syntactically) the term t and t5 is nil. That is, t2 is (IF t1 t
nil), which contradicts the assumption that t2 is canonical
(property (c)).
Next, suppose that at least one term is a call of IF. Our first
observation is that the other term is also a call of IF. For if the
other is a call of CONS, then they cannot be provably equal,
because the former has no function symbols other than IF and hence
is Boolean when all its variables are assigned Boolean values.
Also, if the other is a constant, then both branches of the IF term
are provably equal to that constant and hence these branches are
syntactically identical by the inductive hypothesis, contradicting
property (b). Hence, we may assume for this case that both terms
are calls of IF; let us write them as follows.
t0: (IF t1 t2 t3)
u0: (IF u1 u2 u3)
Note that t1 and u1 are variables, by property (a) of canonical BDD
terms. First we claim that t1 does not strictly precede u1 in the
BDD term order. For suppose t1 does strictly precede u1. Then
property (a) of canonical BDD terms guarantees that t1 does not
occur in u0. Hence, an argument much like one used above shows that
u0 is provably equal to both t2 (substituting t for t1) and t3
(substituting nil for t1), and hence t2 and t3 are provably equal.
That implies that they are identical terms, by the inductive
hypothesis, which then contradicts property (b) for t0. Similarly,
u1 does not strictly precede t1 in the BDD term order. Therefore,
t1 and u1 are the same variable. By substituting t for this
variable we see that t2 and u2 are provably equal, and hence they
are equal by the inductive hypothesis. Similarly, by substituting
nil for t1 (and u1) we see that t3 and u3 are provably, hence
syntactically, equal.
We have covered all cases in which at least one term is a variable or
at least one term is a call of IF. If both terms are constants,
then provable and syntactic equality are clearly equivalent.
Finally, then, we may assume that one term is a call of CONS and
the other is a constant or a call of CONS. The constant case is
similar to the CONS case if the constant is a CONSP, so we omit it;
while if the constant is not a CONSP then it is not provably equal
to a call of CONS; in fact it is provably not equal!
So, we are left with a final case, in which canonical BDD terms (CONS
t1 t2) and (CONS u1 u2) are provably equal, and we want to show
that t1 and u1 are syntactically equal as are t2 and u2. These
conclusions are easy consequences of the inductive hypothesis,
since the ACL2 axiom CONS-EQUAL (which you can inspect using :[pe])
shows that equality of the given terms is equivalent to the
conjunction of (EQUAL t1 t2) and (EQUAL u1 u2). Q.E.D.
(B) Algorithmic Considerations
(B1) BDD rules
A rule of class :[rewrite] (see [rule-classes]) is said to be a
``[bdd] rewrite rule'' if and only if it satisfies the following
criteria. (1) The rule is [enable]d. (2) Its [equivalence] relation
is [equal]. (3) It has no hypotheses. (4) Its :[loop-stopper] field
is nil, i.e., it is not a permutative rule. (5) All variables
occurring in the rule occur in its left-hand side (i.e., there are
no ``free variables''; see [rewrite]). A rule of class
:[definition] (see [rule-classes]) is said to be a ``[bdd]
definition rule'' if it satisfies all the criteria above (except
(4), which does not apply), and moreover the top function symbol of
the left-hand side was not recursively (or mutually recursively)
defined. Technical point: Note that this additional criterion is
independent of whether or not the indicated function symbol
actually occurs in the right-hand side of the rule.
Both BDD rewrite rules and BDD definition rules are said to be ``BDD
rules.''
(B2) Terms ''known to be Boolean''
We apply the BDD algorithm in the context of a top-level goal to
prove, namely, the goal at which the :BDD hint is attached. As we
run the BDD algorithm, we allow ourselves to say that a set of
[term]s is ``known to be Boolean'' if we can verify that the goal
is provable from the assumption that at least one of the terms is
not Boolean. Equivalently, we allow ourselves to say that a set of
terms is ``known to be Boolean'' if we can verify that the original
goal is provably equivalent to the assertion that if all terms in
the set are Boolean, then the goal holds. The notion ``known to be
Boolean'' is conservative in the sense that there are generally
sets of terms for which the above equivalent criteria hold and yet
the sets of terms are not noted as as being ``known to be
Boolean.'' However, ACL2 uses a number of tricks, including
[type-set] reasoning and analysis of the structure of the top-level
goal, to attempt to establish that a sufficiently inclusive set of
terms is known to be Boolean.
From a practical standpoint, the algorithm determines a set of terms
known to be Boolean; we allow ourselves to say that each term in
this set is ``known to be Boolean.'' The algorithm assumes that
these terms are indeed Boolean, and can make use of that
assumption. For example, if t1 is known to be Boolean then the
algorithm simplifies (IF t1 t nil) to t1; see (iv) in the
discussion immediately below.
(B3) IF-lifting and the IF-lifting-for-IF loop
Suppose that one has a [term] of the form (f ... (IF test x y) ...),
where f is a function symbol other than CONS. Then we say that
``IF-lifting'' test ``from'' this term produces the following term,
which is provably equal to the given term.
(if test
(f ... x ...) ; resulting true branch
(f ... y ...)) ; resulting false branch
Here, we replace each argument of f of the form (IF test .. ..), for
the same test, in the same way. In this case we say that
``IF-lifting applies to'' the given term, ``yielding the test''
test and with the ``resulting two branches'' displayed above.
Whenever we apply IF-lifting, we do so for the available test that
is least in the BDD term order (see (A1) above).
We consider arguments v of f that are ``known to be Boolean'' (see
above) to be replaced by (IF v t nil) for the purposes of
IF-lifting, i.e., before IF-lifting is applied.
There is one special case, however, for IF-lifting. Suppose that the
given term is of the form (IF v y z) where v is a variable and is
the test to be lifted out (i.e., it is least in the BDD term order
among the potential tests). Moroever, suppose that neither y nor z
is of the form (IF v W1 W2) for that same v. Then IF-lifting does
not apply to the given term.
We may now describe the IF-lifting-for-IF loop, which applies to
terms of the form (IF test tbr fbr) where the algorithm has already
produced test, tbr, and fbr. First, if test is nil then we return
fbr, while if test is a non-nil constant or a call of CONS then we
return tbr. Otherwise, we see if IF-lifting applies. If IF-lifting
does not apply, then we return (IF test tbr fbr). Otherwise, we
apply IF-lifting to obtain a term of the form (IF x y z), by
lifting out the appropriate test. Now we recursively apply the
IF-lifting-for-IF loop to the term (IF x y z), unless any of the
following special cases apply.
(i) If y and z are the same term, then return y.
(ii) Otherwise, if x and z are the same term, then replace z by nil
before recursively applying IF-lifting-for-IF.
(iii) Otherwise, if x and y are the same term and y is known to be
Boolean, then replace y by t before recursively applying
IF-lifting-for-IF.
(iv) If z is nil and either x and y are the same term or x is ``known
to be Boolean'' and y is t, then return x.
NOTE: When a variable x is known to be Boolean, it is easy to see
that the form (IF x t nil) is always reduced to x by this
algorithm.
(B4) The ACL2 BDD algorithm
We are now ready to present the BDD algorithm for ACL2. It is given
an ACL2 [term], x, as well as an association list va that maps
variables to terms, including all variables occurring in x. We
maintain the invariant that whenever a variable is mapped by va to
a term, that term has already been constructed by the algorithm,
except: initially va maps every variable occurring in the top-level
term to itself. The algorithm proceeds as follows. We implicitly
ordain that whenever the BDD algorithm attempts to create a [term]
that is not a [bdd] term (as defined above in (A2)), it aborts
instead. Thus, whenever the algorithm completes without aborting,
it creates a [bdd] term.
If x is a variable, return the result of looking it up in va.
If x is a constant, return x.
If x is of the form (IF test tbr fbr), then first run the algorithm
on test with the given va to obtain test'. If test' is nil,
then return the result fbr' of running the algorithm on fbr
with the given va. If test' is a constant other than nil, or is
a call of CONS, then return the result tbr' of running the
algorithm on tbr with the given va. If tbr is identical to fbr,
return tbr. Otherwise, return the result of applying the
IF-lifting-for-IF loop (described above) to the term (IF test'
tbr' fbr').
If x is of the form (IF* test tbr fbr), then compute the result
exactly as though [if] were used rather than [if*], except that
if test' is not a constant or a call of CONS (see paragraph
above), then abort the BDD computation. Informally, the tests
of [if*] terms are expected to ``resolve.'' NOTE: This
description shows how [if*] can be used to implement
conditional rewriting in the BDD algorithm.
If x is a LAMBDA expression ((LAMBDA vars body) . args) (which often
corresponds to a [let] term; see [let]), then first form an
alist va' by binding each v in vars to the result of running
the algorithm on the corresponding member of args, with the
current alist va. Then, return the result of the algorithm on
body in the alist va'.
Otherwise, x is of the form (f x1 x2 ... xn), where f is a function
symbol other than [if] or [if*]. In that case, let xi' be the
result of running the algorithm on xi, for i from 1 to n, using
the given alist va. First there are a few special cases. If f
is [equal] then we return t if x1' is syntactically identical
to x2' (where this test is very fast; see (B6) below); we
return x1' if it is known to be Boolean and x2' is t; and
similarly, we return x2' if it is known to be Boolean and x1'
is t. Next, if each xi' is a constant and the
:[executable-counterpart] of f is enabled, then the result is
obtained by computation. Next, if f is [booleanp] and x1' is
known to be Boolean, t is returned. Otherwise, we proceed as
follows, first possibly swapping the arguments if they are out
of (the BDD term) order and if f is known to be commutative
(see below). If a BDD rewrite rule (as defined above) matches
the term (f x1'... xn'), then the most recently stored such
rule is applied. If there is no such match and f is a
BDD-constructor, then we return (f x1'... xn'). Otherwise, if a
BDD definition rule matches this term, then the most recently
stored such rule (which will usually be the original definition
for most users) is applied. If none of the above applies and
neither does IF-lifting, then we return (f x1'... xn').
Otherwise we apply IF-lifting to (f x1'... xn') to obtain a
term (IF test tbr fbr); but we aren't done yet. Rather, we run
the BDD algorithm (using the same alist) on tbr and fbr to
obtain terms tbr' and fbr', and we return (IF test tbr' fbr')
unless tbr' is syntactically identical to fbr', in which case
we return tbr'.
When is it the case that, as said above, ``f is known to be
commutative''? This happens when an enabled rewrite rule is of the
form (EQUAL (f X Y) (f Y X)). Regarding swapping the arguments in
that case: recall that we may assume very little about the BDD term
order, essentially only that we swap the two arguments when the
second is a constant and the first is not, for example, in (+ x 1).
Other than that situation, one cannot expect to predict accurately
when the arguments of commutative operators will be swapped.
(B5) Soundness and Completeness of the ACL2 BDD algorithm
Roughly speaking, ``soundness'' means that the BDD algorithm should
give correct answers, and ``completeness'' means that it should be
powerful enough to prove all true facts. Let us make the soundness
claim a little more precise, and then we'll address completeness
under suitable hypotheses.
Claim (Soundness). If the ACL2 BDD algorithm runs to completion on an
input term t0, then it produces a result that is provably equal to
t0.
We leave the proof of this claim to the reader. The basic idea is
simply to check that each step of the algorithm preserves the
meaning of the term under the bindings in the given alist.
Let us start our discussion of completeness by recalling the theorem
proved above in (A4).
Theorem. Suppose that t1 and t2 are canonical BDD terms that contain
no function symbols other than IF and CONS. Also suppose that
(EQUAL t1 t2) is a theorem. Then t1 and t2 are syntactically
identical.
Below we show how this theorem implies the following completeness
property of the ACL2 BDD algorithm. We continue to assume that CONS
is the only BDD-constructor.
Claim (Completeness). Suppose that t1 and t2 are provably equal
terms, under the assumption that all their variables are known to
be Boolean. Assume further that under this same assumption,
top-level runs of the ACL2 BDD algorithm on these terms return
terms that contain only the function symbols IF and CONS. Then the
algorithm returns the same term for both t1 and t2, and the
algorithm reduces (EQUAL t1 t2) to t.
Why is this claim true? First, notice that the second part of the
conclusion follows immediately from the first, by definition of the
algorithm. Next, notice that the terms u1 and u2 obtained by
running the algorithm on t1 and t2, respectively, are provably
equal to t1 and t2, respectively, by the Soundness Claim. It
follows that u1 and u2 are provably equal to each other. Since
these terms contain no function symbols other than IF or CONS, by
hypothesis, the Claim now follows from the Theorem above together
with the following lemma.
Lemma. Suppose that the result of running the ACL2 BDD algorithm on a
top-level term t0 is a term u0 that contains only the function
symbols IF and CONS, where all variables of t0 are known to be
Boolean. Then u0 is a canonical BDD term.
Proof: left to the reader. Simply follow the definition of the
algorithm, with a separate argument for the IF-lifting-for-IF loop.
Finally, let us remark on the assumptions of the Completeness Claim
above. The assumption that all variables are known to be Boolean is
often true; in fact, the system uses the forward-chaining rule
boolean-listp-forward (you can see it using :[pe]) to try to
establish this assumption, if your theorem has a form such as the
following.
(let ((x (list x0 x1 ...))
(y (list y0 y1 ...)))
(implies (and (boolean-listp x)
(boolean-listp y))
...))
Moreover, the :BDD hint can be used to force the prover to abort if
it cannot check that the indicated variables are known to be
Boolean; see [hints].
Finally, consider the effect in practice of the assumption that the
terms resulting from application of the algorithm contain calls of
IF and CONS only. Typical use of BDDs in ACL2 takes place in a
theory (see [theories]) in which all relevant non-recursive
function symbols are enabled and all recursive function symbols
possess enabled BDD rewrite rules that tell them how open up. For
example, such a rule may say how to expand on a given function
call's argument that has the form (CONS a x), while another may say
how to expand when that argument is nil). (See for example the
rules append-cons and append-nil in the documentation for [if*].)
We leave it to future work to formulate a theorem that guarantees
that the BDD algorithm produces terms containing calls only of IF
and CONS assuming a suitably ``complete'' collection of rewrite
rules.
(B6) Efficiency considerations
Following Bryant's algorithm, we use a graph representation of
[term]s created by the BDD algorithm's computation. This
representation enjoys some important properties.
(Time efficiency) The test for syntactic equality of BDD terms is
very fast.
(Space efficiency) Equal BDD data structures are stored identically
in memory.
Implementation note. The representation actually uses a sort of hash
table for BDD terms that is implemented as an ACL2 1-dimensional
array. See [arrays]. In addition, we use a second such hash table
to avoid recomputing the result of applying a function symbol to
the result of running the algorithm on its arguments. We believe
that these uses of hash tables are standard. They are also
discussed in Moore's paper on BDDs; see [bdd] for the reference.")
(BDD-INTRODUCTION
(BDD)
"Examples illustrating the use of BDDs in ACL2
See [bdd] for a brief introduction to BDDs in ACL2 and for pointers
to other documentation on BDDs in ACL2. Here, we illustrate the use
of BDDs in ACL2 by way of some examples. For a further example, see
[if*].
Let us begin with a really simple example. (We will explain the :bdd
hint (:vars nil) below.)
ACL2 !>(thm (equal (if a b c) (if (not a) c b))
:hints ((\"Goal\" :bdd (:vars nil)))) ; Prove with BDDs
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
But simplification with BDDs (7 nodes) reduces this to T, using the
:definitions EQUAL and NOT.
Q.E.D.
Summary
Form: ( THM ...)
Rules: ((:DEFINITION EQUAL) (:DEFINITION NOT))
Warnings: None
Time: 0.18 seconds (prove: 0.05, print: 0.02, other: 0.12)
Proof succeeded.
ACL2 !>
The :bdd hint (:vars nil) indicates that BDDs are to be used on the
indicated goal, and that any so-called ``variable ordering'' may be
used: ACL2 may use a convenient order that is far from optimal. It
is beyond the scope of the present documentation to address the
issue of how the user may choose good variable orderings. Someday
our implementation of BDDs may be improved to include
heuristically-chosen variable orderings rather than rather random
ones.
Here is a more interesting example.
(defun v-not (x)
; Complement every element of a list of Booleans.
(if (consp x)
(cons (not (car x)) (v-not (cdr x)))
nil))
; Now we prove a rewrite rule that explains how to open up v-not on
; a consp.
(defthm v-not-cons
(equal (v-not (cons x y))
(cons (not x) (v-not y))))
; Finally, we prove for 7-bit lists that v-not is self-inverting.
(thm
(let ((x (list x0 x1 x2 x3 x4 x5 x6)))
(implies (boolean-listp x)
(equal (v-not (v-not x)) x)))
:hints ((\"Goal\" :bdd
;; Note that this time we specify a variable order.
(:vars (x0 x1 x2 x3 x4 x5 x6)))))
It turns out that the variable order doesn't seem to matter in this
example; using several orders we found that 30 nodes were created,
and the proof time was about 1/10 of a second on a (somewhat
enhanced) Sparc 2. The same proof took about a minute and a half
without any :bdd hint! This observation is a bit misleading
perhaps, since the theorem for arbitrary x,
(thm
(implies (boolean-listp x)
(equal (v-not (v-not x)) x)))
only takes about 1.5 times as long as the :bdd proof for 7 bits,
above! Nevertheless, BDDs can be very useful in reducing proof
time, especially when there is no regular structure to facilitate
proof by induction, or when the induction scheme is so complicated
to construct that significant user effort is required to get the
proof by induction to go through.
Finally, consider the preceding example, with a :bdd hint of (say)
(:vars nil), but with the rewrite rule v-not-cons above disabled.
In that case, the proof fails, as we see below. That is because the
BDD algorithm in ACL2 uses hypothesis-free :[rewrite] rules,
:[executable-counterpart]s, and nonrecursive definitions, but it
does not use recursive definitions.
Notice that when we issue the (show-bdd) command, the system's
response clearly shows that we need a rewrite rule for simplifying
terms of the form (v-not (cons ...)).
ACL2 !>(thm
(let ((x (list x0 x1 x2 x3 x4 x5 x6)))
(implies (boolean-listp x)
(equal (v-not (v-not x)) x)))
:hints ((\"Goal\" :bdd (:vars nil)
:in-theory (disable v-not-cons))))
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
ACL2 Error in ( THM ...): Attempted to create V-NOT node during BDD
processing with an argument that is a call of a bdd-constructor,
which would produce a non-BDD term (as defined in :DOC
bdd-algorithm). See :DOC show-bdd.
Summary
Form: ( THM ...)
Rules: NIL
Warnings: None
Time: 0.58 seconds (prove: 0.13, print: 0.00, other: 0.45)
******** FAILED ******** See :DOC failure ******** FAILED ********
ACL2 !>(show-bdd)
BDD computation on Goal yielded 17 nodes.
------------------------------
BDD computation was aborted on Goal, and hence there is no
falsifying assignment that can be constructed. Here is a backtrace
of calls, starting with the top-level call and ending with the one
that led to the abort. See :DOC show-bdd.
(LET ((X (LIST X0 X1 X2 X3 X4 X5 ...)))
(IMPLIES (BOOLEAN-LISTP X)
(EQUAL (V-NOT (V-NOT X)) X)))
alist: ((X6 X6) (X5 X5) (X4 X4) (X3 X3) (X2 X2) (X1 X1) (X0 X0))
(EQUAL (V-NOT (V-NOT X)) X)
alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...)))
(V-NOT (V-NOT X))
alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...)))
(V-NOT X)
alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...)))
ACL2 !>
The term that has caused the BDD algorithm to abort is thus (V-NOT
X), where X has the value (LIST X0 X1 X2 X3 X4 X5 ...), i.e., (CONS
X0 (LIST X1 X2 X3 X4 X5 ...)). Thus, we see the utility of
introducing a rewrite rule to simplify terms of the form (V-NOT
(CONS ...)). The moral of this story is that if you get an error of
the sort shown above, you may find it useful to execute the command
(show-bdd) and use the result as advice that suggests the left hand
side of a rewrite rule.
Here is another sort of failed proof. In this version we have omitted
the hypothesis that the input is a bit vector. Below we use
show-bdd to see what went wrong, and use the resulting information
to construct a counterexample. This failed proof corresponds to a
slightly modified input theorem, in which x is bound to the
4-element list (list x0 x1 x2 x3).
ACL2 !>(thm
(let ((x (list x0 x1 x2 x3)))
(equal (v-not (v-not x)) x))
:hints ((\"Goal\" :bdd
;; This time we do not specify a variable order.
(:vars nil))))
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
ACL2 Error in ( THM ...): The :BDD hint for the current goal has
successfully simplified this goal, but has failed to prove it.
Consider using (SHOW-BDD) to suggest a counterexample; see :DOC
show-bdd.
Summary
Form: ( THM ...)
Rules: NIL
Warnings: None
Time: 0.18 seconds (prove: 0.07, print: 0.00, other: 0.12)
******** FAILED ******** See :DOC failure ******** FAILED ********
ACL2 !>(show-bdd)
BDD computation on Goal yielded 73 nodes.
------------------------------
Falsifying constraints:
((X0 \"Some non-nil value\")
(X1 \"Some non-nil value\")
(X2 \"Some non-nil value\")
(X3 \"Some non-nil value\")
((EQUAL 'T X0) T)
((EQUAL 'T X1) T)
((EQUAL 'T X2) T)
((EQUAL 'T X3) NIL))
------------------------------
Term obtained from BDD computation on Goal:
(IF X0
(IF X1
(IF X2 (IF X3 (IF # # #) (IF X3 # #))
(IF X2 'NIL (IF X3 # #)))
(IF X1 'NIL
(IF X2 (IF X3 # #) (IF X2 # #))))
(IF X0 'NIL
(IF X1 (IF X2 (IF X3 # #) (IF X2 # #))
(IF X1 'NIL (IF X2 # #)))))
ACL2 Query (:SHOW-BDD): Print the term in full? (N, Y, W or ?):
n ; I've seen enough. The assignment shown above suggests
; (though not conclusively) that if we bind x3 to a non-nil
; value other than T, and bind x0, x1, and x2 to t, then we
; this may give us a counterexample.
ACL2 !>(let ((x0 t) (x1 t) (x2 t) (x3 7))
(let ((x (list x0 x1 x2 x3)))
;; Let's use LIST instead of EQUAL to see how the two
;; lists differ.
(list (v-not (v-not x)) x)))
((T T T T) (T T T 7))
ACL2 !>
See [if*] for another example.")
(BIBLIOGRAPHY
(ABOUT-ACL2)
"Reports about ACL2
The ACL2 home page includes a {list of notes and reports about ACL2 |
http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html}.")
(BINARY-*
(* ACL2-BUILT-INS)
"Multiplication function
Completion Axiom (completion-of-*):
(equal (binary-* x y)
(if (acl2-numberp x)
(if (acl2-numberp y)
(binary-* x y)
0)
0))
[Guard] for (binary-* x y):
(and (acl2-numberp x) (acl2-numberp y))
Notice that like all arithmetic functions, binary-* treats
non-numeric inputs as 0.
Calls of the macro [*] expand to calls of binary-*; see [*].")
(BINARY-+
(+ ACL2-BUILT-INS)
"Addition function
Completion Axiom (completion-of-+):
(equal (binary-+ x y)
(if (acl2-numberp x)
(if (acl2-numberp y)
(binary-+ x y)
x)
(if (acl2-numberp y)
y
0)))
[Guard] for (binary-+ x y):
(and (acl2-numberp x) (acl2-numberp y))
Notice that like all arithmetic functions, binary-+ treats
non-numeric inputs as 0.
Calls of the macro [+] expand to calls of binary-+; see [+].")
(BINARY-APPEND
(APPEND ACL2-BUILT-INS)
"[concatenate] two lists
This binary function implements [append], which is a macro in ACL2.
See [append]
The [guard] for binary-append requires the first argument to be a
[true-listp].
Function: <binary-append>
(defun binary-append (x y)
(declare (xargs :guard (true-listp x)))
(cond ((endp x) y)
(t (cons (car x)
(binary-append (cdr x) y)))))")
(BIND-FREE
(REWRITE LINEAR DEFINITION)
"To bind free variables of a rewrite, definition, or linear rule
Examples:
(IMPLIES (AND (RATIONALP LHS)
(RATIONALP RHS)
(BIND-FREE (FIND-MATCH-IN-PLUS-NESTS LHS RHS) (X)))
(EQUAL (EQUAL LHS RHS)
(EQUAL (+ (- X) LHS) (+ (- X) RHS))))
(IMPLIES (AND (BIND-FREE
(FIND-RATIONAL-MATCH-IN-TIMES-NESTS LHS RHS MFC STATE)
(X))
(RATIONALP X)
(CASE-SPLIT (NOT (EQUAL X 0))))
(EQUAL (< LHS RHS)
(IF (< 0 X)
(< (* (/ X) LHS) (* (/ X) RHS))
(< (* (/ X) RHS) (* (/ X) LHS)))))
General Forms:
(BIND-FREE term var-list)
(BIND-FREE term t)
(BIND-FREE term)
A rule which uses a bind-free hypothesis has similarities to both a
rule which uses a [syntaxp] hypothesis and to a :[meta] rule.
Bind-free is like [syntaxp], in that it logically always returns t
but may affect the application of a :[rewrite], :[definition], or
:[linear] rule when it is called at the top-level of a hypothesis.
It is like a :[meta] rule, in that it allows the user to perform
transformations of terms under progammatic control.
Note that a bind-free hypothesis does not, in general, deal with the
meaning or semantics or values of the terms, but rather with their
syntactic forms. Before attempting to write a rule which uses
bind-free, the user should be familiar with [syntaxp] and the
internal form that ACL2 uses for terms. This internal form is
similar to what the user sees, but there are subtle and important
differences. [Trans] can be used to view this internal form.
Just as for a [syntaxp] hypothesis, there are two basic types of
bind-free hypotheses. The simpler type of bind-free hypothesis may
be used as the nth hypothesis in a :[rewrite], :[definition], or
:[linear] rule whose :[corollary] is (implies (and hyp1 ... hypn
... hypk) (equiv lhs rhs)) provided term is a term, term contains
at least one variable, and every variable occuring freely in term
occurs freely in lhs or in some hypi, i<n. In addition, term must
not use any stobjs. Later below we will describe the second type,
an extended bind-free hypothesis, which may use [state]. Whether
simple or extended, a bind-free hypothesis may return an alist that
binds free variables, as explained below, or it may return a list
of such alists. We focus on the first of these cases: return of a
single binding alist. We conclude our discussion with a section
that covers the other case: return of a list of alists.
We begin our description of bind-free by examining the first example
above in some detail.
We wish to write a rule which will cancel ``like'' addends from both
sides of an equality. Clearly, one could write a series of rules
such as
(DEFTHM THE-HARD-WAY-2-1
(EQUAL (EQUAL (+ A X B)
(+ X C))
(EQUAL (+ A B)
(FIX C))))
with one rule for each combination of positions the matching addends
might be found in (if one knew before-hand the maximum number of
addends that would appear in a sum). But there is a better way. (In
what follows, we assume the presence of an appropriate set of rules
for simplifying sums.)
Consider the following definitions and theorem:
(DEFUN INTERSECTION-EQUAL (X Y)
(COND ((ENDP X)
NIL)
((MEMBER-EQUAL (CAR X) Y)
(CONS (CAR X) (INTERSECTION-EQUAL (CDR X) Y)))
(T
(INTERSECTION-EQUAL (CDR X) Y))))
(DEFUN PLUS-LEAVES (TERM)
(IF (EQ (FN-SYMB TERM) 'BINARY-+)
(CONS (FARGN TERM 1)
(PLUS-LEAVES (FARGN TERM 2)))
(LIST TERM)))
(DEFUN FIND-MATCH-IN-PLUS-NESTS (LHS RHS)
(IF (AND (EQ (FN-SYMB LHS) 'BINARY-+)
(EQ (FN-SYMB RHS) 'BINARY-+))
(LET ((COMMON-ADDENDS (INTERSECTION-EQUAL (PLUS-LEAVES LHS)
(PLUS-LEAVES RHS))))
(IF COMMON-ADDENDS
(LIST (CONS 'X (CAR COMMON-ADDENDS)))
NIL))
NIL))
(DEFTHM CANCEL-MATCHING-ADDENDS-EQUAL
(IMPLIES (AND (RATIONALP LHS)
(RATIONALP RHS)
(BIND-FREE (FIND-MATCH-IN-PLUS-NESTS LHS RHS) (X)))
(EQUAL (EQUAL LHS RHS)
(EQUAL (+ (- X) LHS) (+ (- X) RHS)))))
How is this rule applied to the following term?
(equal (+ 3 (expt a n) (foo a c))
(+ (bar b) (expt a n)))
As mentioned above, the internal form of an ACL2 term is not always
what one sees printed out by ACL2. In this case, by using :[trans]
one can see that the term is stored internally as
(equal (binary-+ '3
(binary-+ (expt a n) (foo a c)))
(binary-+ (bar b) (expt a n))).
When ACL2 attempts to apply cancel-matching-addends-equal to the term
under discussion, it first forms a substitution that instantiates
the left-hand side of the conclusion so that it is identical to the
target term. This substitution is kept track of by the substitution
alist:
((LHS . (binary-+ '3
(binary-+ (expt a n) (foo a c))))
(RHS . (binary-+ (bar b) (expt a n)))).
ACL2 then attempts to relieve the hypotheses in the order they were
given. Ordinarily this means that we instantiate each hypothesis
with our substitution and then attempt to rewrite the resulting
instance to true. Thus, in order to relieve the first hypothesis,
we rewrite:
(RATIONALP (binary-+ '3
(binary-+ (expt a n) (foo a c)))).
Let us assume that the first two hypotheses rewrite to t. How do we
relieve the bind-free hypothesis? Just as for a [syntaxp]
hypothesis, ACL2 evaluates (find-match-in-plus-nests lhs rhs) in an
environment where lhs and rhs are instantiated as determined by the
substitution. In this case we evaluate
(FIND-MATCH-IN-PLUS-NESTS '(binary-+ '3
(binary-+ (expt a n) (foo a c)))
'(binary-+ (bar b) (expt a n))).
Observe that, just as in the case of a [syntaxp] hypothesis, we
substitute the quotation of the variables bindings into the term to
be evaluated. See [syntaxp] for the reasons for this. The result of
this evaluation, ((X . (EXPT A N))), is then used to extend the
substitution alist:
((X . (EXPT A N))
(LHS . (binary-+ '3
(binary-+ (expt a n) (foo a c))))
(RHS . (binary-+ (bar b) (expt a n)))),
and this extended substitution determines
cancel-matching-addends-equal's result:
(EQUAL (+ (- X) LHS) (+ (- X) RHS))
==>
(EQUAL (+ (- (EXPT A N)) 3 (EXPT A N) (FOO A C))
(+ (- (EXPT A N)) (BAR B) (EXPT A N))).
Question: What is the internal form of this result?
Hint: Use :[trans].
When this rule fires, it adds the negation of a common term to both
sides of the equality by selecting a binding for the otherwise-free
variable x, under programmatic control. Note that other mechanisms
such as the binding of [free-variables] may also extend the
substitution alist.
Just as for a [syntaxp] test, a bind-free form signals failure by
returning nil. However, while a [syntaxp] test signals success by
returning true, a bind-free form signals success by returning an
alist which is used to extend the current substitution alist.
Because of this use of the alist, there are several restrictions on
it --- in particular the alist must only bind variables, these
variables must not be already bound by the substitution alist, and
the variables must be bound to ACL2 terms. If term returns an alist
and the alist meets these restrictions, we append the alist to the
substitution alist and use the result as the new current
substitution alist. This new current substitution alist is then
used when we attempt to relieve the next hypothesis or, if there
are no more, instantiate the right hand side of the rule.
There is also a second, optional, var-list argument to a bind-free
hypothesis. If provided, it must be either t or a list of
variables. If it is not provided, it defaults to t. If it is a list
of variables, this second argument is used to place a further
restriction on the possible values of the alist to be returned by
term: any variables bound in the alist must be present in the list
of variables. We strongly recommend the use of this list of
variables, as it allows some consistency checks to be performed at
the time of the rule's admittance which are not possible otherwise.
An extended bind-free hypothesis is similar to the simple type
described above, but it uses two additional variables, mfc and
state, which must not be bound by the left hand side or an earlier
hypothesis of the rule. They must be the last two variables
mentioned by term: first mfc, then state. These two variables give
access to the functions mfc-xxx; see [extended-metafunctions]. As
described there, mfc is bound to the so-called metafunction-context
and state to ACL2's [state]. See [bind-free-examples] for examples
of the use of these extended bind-free hypotheses.
SECTION: Returning a list of alists.
As promised above, we conclude with a discussion of the case that
evaluation of the bind-free term produces a list of alists, x,
rather than a single alist. In this case each member b of x is
considered in turn, starting with the first and proceeding through
the list. Each such b is handled exactly as discussed above, as
though it were the result of evaluating the bind-free term. Thus,
each b extends the current variable binding alist, and all
remaining hypotheses are then relieved, as though b had been the
value obtained by evaluating the bind-free term. As soon as one
such b leads to successful relieving of all remaining hypotheses,
the process of relieving hypotheses concludes, so no further
members of x are considered.
We illustrate with a simple pedagogical example. First introduce
functions p1 and p2 such that a rewrite rule specifies that p2
implies p1, but with a free variable.
(defstub p1 (x) t)
(defstub p2 (x y) t)
(defaxiom p2-implies-p1
(implies (p2 x y)
(p1 x)))
If we add the following axiom, then (p1 x) follows logically for all
x.
(defaxiom p2-instance
(p2 v (cons v 4)))
Unfortunately, evaluation of (thm (p1 a)) fails, because ACL2 fails
to bind the free variable y in order to apply the rule p2-instance.
Let's define a function that produces a list of alists, each binding
the variable y. Of course, we know that only the middle one below
is necessary in this simple example. In more complex examples, one
might use heuristics to construct such a list of alists.
(defun my-alists (x)
(list (list (cons 'y (fcons-term* 'cons x ''3)))
(list (cons 'y (fcons-term* 'cons x ''4)))
(list (cons 'y (fcons-term* 'cons x ''5)))))
The following rewrite rule uses bind-free to return a list of
candidate alists binding y.
(defthm p2-implies-p1-better
(implies (and (bind-free (my-alists x)
(y)) ; the second argument, (y), is optional
(p2 x y))
(p1 x)))
Now the proof succeeds for (thm (p1 a)). Why? When ACL2 applies the
rewrite rule p2-implies-p1-better, it evaluates my-alists, as we
can see from the following [trace], to bind y in three different
alists.
ACL2 !>(thm (p1 a))
1> (ACL2_*1*_ACL2::MY-ALISTS A)
<1 (ACL2_*1*_ACL2::MY-ALISTS (((Y CONS A '3))
((Y CONS A '4))
((Y CONS A '5))))
Q.E.D.
The first alist, binding y to (cons a '3), fails to allow the
hypothesis (p2 x y) to be proved. But the next binding of y, to
(cons a '4), succeeds: then the current binding alist is ((x . a)
(y . (cons a '4))), for which the hypothesis (p2 x y) rewrites to
true using the rewrite rule p2-instance.
Subtopics
[Bind-free-examples]
Examples pertaining to [bind-free] hypotheses")
(BIND-FREE-EXAMPLES
(BIND-FREE)
"Examples pertaining to [bind-free] hypotheses
See [bind-free] for a basic discussion of the use of bind-free to
control rewriting.
Note that the examples below all illustrate the common case in which
a bind-free hypothesis generates a binding alist. See [bind-free],
in particular the final section, for a discussion of the case that
instead a list of binding alists is generated.
We give examples of the use of [bind-free] hypotheses from the
perspective of a user interested in reasoning about arithmetic, but
it should be clear that [bind-free] can be used for many other
purposes also.
EXAMPLE 1: Cancel a common factor.
(defun bind-divisor (a b)
; If a and b are polynomials with a common factor c, we return a
; binding for x. We could imagine writing get-factor to compute the
; gcd, or simply to return a single non-invertible factor.
(let ((c (get-factor a b)))
(and c (list (cons 'x c)))))
(defthm cancel-factor
;; We use case-split here to ensure that, once we have selected
;; a binding for x, the rest of the hypotheses will be relieved.
(implies (and (acl2-numberp a)
(acl2-numberp b)
(bind-free (bind-divisor a b) (x))
(case-split (not (equal x 0)))
(case-split (acl2-numberp x)))
(iff (equal a b)
(equal (/ a x) (/ b x)))))
EXAMPLE 2: Pull integer summand out of floor. Note: This example has
an extended [bind-free] hypothesis, which uses the term
(find-int-in-sum sum mfc state).
(defun fl (x)
;; This function is defined, and used, in the IHS books.
(floor x 1))
(defun int-binding (term mfc state)
;; The call to mfc-ts returns the encoded type of term. ;
;; Thus, we are asking if term is known by type reasoning to ;
;; be an integer. ;
(declare (xargs :stobjs (state) :mode :program))
(if (ts-subsetp (mfc-ts term mfc state)
*ts-integer*)
(list (cons 'int term))
nil))
(defun find-int-in-sum (sum mfc state)
(declare (xargs :stobjs (state) :mode :program))
(if (and (nvariablep sum)
(not (fquotep sum))
(eq (ffn-symb sum) 'binary-+))
(or (int-binding (fargn sum 1) mfc state)
(find-int-in-sum (fargn sum 2) mfc state))
(int-binding sum mfc state)))
; Some additional work is required to prove the following. So for
; purposes of illustration, we wrap skip-proofs around the defthm.
(skip-proofs
(defthm cancel-fl-int
;; The use of case-split is probably not needed, since we should
;; know that int is an integer by the way we selected it. But this
;; is safer.
(implies (and (acl2-numberp sum)
(bind-free (find-int-in-sum sum mfc state) (int))
(case-split (integerp int)))
(equal (fl sum)
(+ int (fl (- sum int)))))
:rule-classes ((:rewrite :match-free :all)))
)
; Arithmetic libraries will have this sort of lemma.
(defthm hack (equal (+ (- x) x y) (fix y)))
(in-theory (disable fl))
(thm (implies (and (integerp x) (acl2-numberp y))
(equal (fl (+ x y)) (+ x (fl y)))))
EXAMPLE 3: Simplify terms such as (equal (+ a (* a b)) 0)
(defun factors (product)
;; We return a list of all the factors of product. We do not
;; require that product actually be a product.
(if (eq (fn-symb product) 'BINARY-*)
(cons (fargn product 1)
(factors (fargn product 2)))
(list product)))
(defun make-product (factors)
;; Factors is assumed to be a list of ACL2 terms. We return an
;; ACL2 term which is the product of all the ellements of the
;; list factors.
(cond ((atom factors)
''1)
((null (cdr factors))
(car factors))
((null (cddr factors))
(list 'BINARY-* (car factors) (cadr factors)))
(t
(list 'BINARY-* (car factors) (make-product (cdr factors))))))
(defun quotient (common-factors sum)
;; Common-factors is a list of ACL2 terms. Sum is an ACL2 term each
;; of whose addends have common-factors as factors. We return
;; (/ sum (make-product common-factors)).
(if (eq (fn-symb sum) 'BINARY-+)
(let ((first (make-product (set-difference-equal (factors (fargn sum 1))
common-factors))))
(list 'BINARY-+ first (quotient common-factors (fargn sum 2))))
(make-product (set-difference-equal (factors sum)
common-factors))))
(defun intersection-equal (x y)
(cond ((endp x)
nil)
((member-equal (car x) y)
(cons (car x) (intersection-equal (cdr x) y)))
(t
(intersection-equal (cdr x) y))))
(defun common-factors (factors sum)
;; Factors is a list of the factors common to all of the addends
;; examined so far. On entry, factors is a list of the factors in
;; the first addend of the original sum, and sum is the rest of the
;; addends. We sweep through sum, trying to find a set of factors
;; common to all the addends of sum.
(declare (xargs :measure (acl2-count sum)))
(cond ((null factors)
nil)
((eq (fn-symb sum) 'BINARY-+)
(common-factors (intersection-equal factors (factors (fargn sum 1)))
(fargn sum 2)))
(t
(intersection-equal factors (factors sum)))))
(defun simplify-terms-such-as-a+ab-rel-0-fn (sum)
;; If we can find a set of factors common to all the addends of sum,
;; we return an alist binding common to the product of these common
;; factors and binding quotient to (/ sum common).
(if (eq (fn-symb sum) 'BINARY-+)
(let ((common-factors (common-factors (factors (fargn sum 1))
(fargn sum 2))))
(if common-factors
(let ((common (make-product common-factors))
(quotient (quotient common-factors sum)))
(list (cons 'common common)
(cons 'quotient quotient)))
nil))
nil))
(defthm simplify-terms-such-as-a+ab-=-0
(implies (and (bind-free
(simplify-terms-such-as-a+ab-rel-0-fn sum)
(common quotient))
(case-split (acl2-numberp common))
(case-split (acl2-numberp quotient))
(case-split (equal sum
(* common quotient))))
(equal (equal sum 0)
(or (equal common 0)
(equal quotient 0)))))
(thm (equal (equal (+ u (* u v)) 0)
(or (equal u 0) (equal v -1))))")
(BOOK-COMPILED-FILE
(BOOKS-REFERENCE)
"Creating and loading of compiled and expansion files for [books]
An effect of [compilation] is to speed up the execution of the
functions defined in a book. Compilation can also remove tail
recursion, thus avoiding stack overflows. The presence of compiled
code for the functions in the book should not otherwise affect the
performance of ACL2. See [guard] for a discussion; also See
[compilation].
By default, the [certify-book] command compiles the book that it
certifies. see [certify-book] for how to control this behavior.
By default, the [include-book] command loads the compiled file for
the book. The details of how this loading works are subtle, and do
not need to be understood by most users. The ACL2 source code
contains an ``Essay on Hash Table Support for Compilation'' that
explains such details for those interested. All that users should
generally need to know about this is that the compiled file is
always the result of compiling a so-called ``expansion file'',
which contains certain additional code besides the book itself. The
relevance to users of the expansion file is that it can be loaded
if the compiled file is missing (except when :load-compiled-file t
is specified by the [include-book] form), and its existence is
required in order for [include-book] to create a book's compiled
file, as described below.
Most users can skip the remainder of this documentation topic, which
addresses the uncommon activity of using [include-book] to compile
books.
Include-book can be made to compile a book by supplying its keyword
argument :load-compiled-file the value :comp. However, a compiled
file can only be produced if there is already an expansion file
that is at least as recent as the book's [certificate]. Such a
file, whose name happens to be the result of concatenating the
string \"@expansion.lsp\" to the book name (without the \".lisp\"
suffix), is created by [certify-book] when state global variable
'save-expansion-file has a non-nil value. That will be the case if
ACL2 started up when environment variable ACL2_SAVE_EXPANSION was t
(or any value that is not the empty string and whose
[string-upcase] is not \"NIL\"), until the time (if any) that
'save-expansion-file is assigned a different value by the user. In
most respects, the :comp setting is treated exactly the same as
:warn; but after all events in the book are processed, the
expansion file is compiled if a compiled file was not loaded, after
which the resulting compiled file is loaded.
One can thus, for example, compile books for several different host
Lisps --- useful when installing ACL2 executables at the same site
that are built on different host Lisps. A convenient way to do this
in an environment that provides Gnu `make' is to certify the
community books using the shell command ``make regression'' in the
acl2-sources/ directory, after setting environment variable
ACL2_SAVE_EXPANSION to t, and then moving to the books directory
and executing the appropriate `make' commands to compile the books
(targets fasl, o, and so on, according to the compiled file
extension for the host Lisp).
We conclude by saying more about the :load-compiled-file argument of
[include-book]. We assume that [state] global 'compiler-enabled has
a non-nil value; otherwise :load-compiled-file is always treated as
nil.
We do not consider raw mode below (see [set-raw-mode]), which
presents a special case: ACL2 will attempt to load the book itself
whenever it would otherwise load the expansion or compiled file,
but cannot (either because the :load-compiled-file argument is nil,
or for each of the expansion and compiled files, either it does not
exist or it is out of date with respect to the .cert file).
The :load-compiled-file argument is not recursive: calls of
include-book that are inside the book supplied to include-book use
their own :load-compiled-file arguments. However, those subsidiary
include-book calls can nevertheless be sensitive to the
:load-compiled-file arguments of enclosing include-book calls, as
follows. If :load-compiled-file has value t, then every subsidiary
include-book is required to load a compiled file. Moreover, if a
book's compiled file or expansion file is loaded in raw Lisp, then
an attempt will be made to load the compiled file or expansion file
for any [include-book] form encountered during that load. If that
attempt fails, then that load immediately aborts, as does its
parent load, and so on up the chain. If, when going up the chain,
an [include-book] is aborted for which keyword argument
:load-compiled-file has value t, then an error occurs.
When loading a book's compiled file or expansion file, FILE, it is
possible to encounter an [include-book] form for a book that has no
suitable compiled file or expansion file. In that case, the load of
FILE is aborted at that point. Similarly, the load of FILE is
aborted in the case that this include-book form has a suitable
compiled file or expansion file whose load is itself aborted. Thus,
whenever any include-book aborts, so do all of its parent
include-books, up the chain. Such an abort causes an error when the
include-book form specifies a :load-compiled-file value of t.")
(BOOK-CONTENTS
(BOOKS-TOUR)
"Restrictions on the forms inside [books]
Example Book:
; This book defines my app function and the theorem that it is
; associative. One irrelevant help lemma is proved first but
; it is local and so not seen by include-book. I depend on the
; inferior book \"weird-list-primitives\" from which I get
; definitions of hd and tl.
(in-package \"MY-PKG\")
(include-book \"weird-list-primitives\")
(defun app (x y) (if (consp x) (cons (hd x) (app (tl x) y)) y))
(local
(defthm help-lemma
(implies (true-listp x) (equal (app x nil) x))))
(defthm app-is-associative
(equal (app (app a b) c) (app a (app b c))))
The first form in a book must be (in-package \"pkg\") where \"pkg\" is
some package name known to ACL2 whenever the book is certified. The
rest of the forms in a book are embedded event forms, i.e.,
[defun]s, [defthm]s, etc., some of which may be marked [local]. See
[embedded-event-form]. The usual Common Lisp commenting conventions
are provided. Note that since a book consists of embedded event
forms, we can talk about the ``[local]'' and ``non-local'' [events]
of a book.
Because [in-package] is not an embedded event form, the only
[in-package] in a book is the initial one. Because [defpkg] is not
an embedded event form, a book can never contain a [defpkg] form.
Because [include-book] is an embedded event form, [books] may
contain references to other [books]. This makes [books] structured
objects.
When the forms in a book are read from the file, they are read with
[current-package] set to the package named in the [in-package] form
at the top of the file. The effect of this is that all symbols are
[intern]ed in that package, except those whose packages are given
explicitly with the ``::'' notation. For example, if a book begins
with (in-package \"ACL2-X\") and then contains the form
(defun fn (x)
(acl2::list 'car x))
then [defun], fn, x, and [car] are all [intern]ed in the \"ACL2-X\"
package. I.e., it is as though the following form were read
instead:
(acl2-x::defun acl2-x::fn (acl2-x::x)
(acl2::list 'acl2-x::car acl2-x::x)).
Of course, acl2-x::defun would be the same symbol as acl2::defun if
the \"ACL2-X\" package imported acl2::defun.
If each book has its own unique package name and all the names
defined within the book are in that package, then name clashes
between [books] are completely avoided. This permits the
construction of useful logical [world]s by the successive inclusion
of many [books]. Although it is often too much trouble to manage
several packages, their judicious use is a way to minimize name
clashes. Often, a better way is to use local; see [local].
How does [include-book] know the definitions of the packages used in
a book, since [defpkg]s cannot be among the forms? More generally,
how do we know that the forms in a book will be admissible in the
host logical [world] of an [include-book]? See [certificate] for
answers to these questions.")
(BOOK-EXAMPLE
(BOOKS-TOUR)
"How to create, certify, and use a simple book
Suppose you have developed a sequence of admissible [events] which
you want to turn into a book. We call this ``publishing'' the book.
This note explains how to do that.
A key idea of [books] is that they are ``incremental'' in the sense
that when you include a book in a host logical [world], the [world]
is incrementally extended by the results established in that book.
This is allowed only if every name defined by the incoming book is
either new or is already identically defined. See
[redundant-events]. This is exactly the same problem faced by a
programmer who wishes to provide a utility to other people: how can
he make sure he doesn't create name conflicts? The solution, in
Common Lisp, is also the same: use packages. While [books] and
packages have a very tenuous formal connection (every book must
start with an [in-package]), the creation of a book is intimately
concerned with the package issue. Having motivated what would
otherwise appear as an unnecessary fascination with packages below,
we now proceed with a description of how to publish a book.
Just to be concrete, let's suppose you have already gotten ACL2 to
accept the following sequence of [command]s, starting in the ACL2
initial [state].
(defpkg \"ACL2-MY-BOOK\"
(union-eq *common-lisp-symbols-from-main-lisp-package*
*acl2-exports*))
(in-package \"ACL2-MY-BOOK\")
(defun app (x y)
(if (consp x) (cons (car x) (app (cdr x) y)) y))
(defun rev (x)
(if (consp x) (app (rev (cdr x)) (list (car x))) nil))
(defthm rev-app-hack
(equal (rev (app a (list x))) (cons x (rev a))))
(defthm rev-rev
(implies (acl2::true-listp x) (equal (rev (rev x)) x)))
Observe that the first form above defines a package (which imports
the symbols defined in CLTL such as [if] and [cons] and the symbols
used to [command] ACL2 such as [defun] and [defthm]). The second
form selects that package as the current one. All subsequent forms
are read into that package. The remaining forms are just event
forms: [defun]s and [defthm]s in this case.
Typically you would have created a file with Emacs containing these
forms and you will have submitted each of them interactively to
ACL2 to confirm that they are all admissible. That interactive
verification should start in ACL2's initial [world] --- although
you might, of course, start your sequence of [events] with some
[include-book]s to build a more elaborate [world].
The first step towards publishing a book containing the results above
is to create a file that starts with the [in-package] and then
contains the rest of the forms. Let's call that file
\"my-book.lisp\". The name is unimportant, except it must end with
\".lisp\". If there are [events] that you do not wish to be available
to the user of the book --- e.g., lemmas you proved on your way
toward proving the main ones --- you may so mark them by enclosing
them in [local] forms. See [local]. Let us suppose you wish to hide
rev-app-hack above. You may also add standard Lisp comments to the
file. The final content of \"my-book.lisp\" might be:
; This book contains my app and rev functions and the theorem
; that rev is its own inverse.
(in-package \"ACL2-MY-BOOK\")
(defun app (x y)
(if (consp x) (cons (car x) (app (cdr x) y)) y))
(defun rev (x)
(if (consp x) (app (rev (cdr x)) (list (car x))) nil))
; The following hack is not exported.
(local (defthm rev-app-hack
(equal (rev (app a (list x))) (cons x (rev a)))))
(defthm rev-rev
(implies (acl2::true-listp x) (equal (rev (rev x)) x)))
The file shown above is the book. By the time this note is done you
will have seen how to certify that the book is correct, how to
compile it, and how to use it in other host [world]s. Observe that
the [defpkg] is not in the book. It cannot be: Common Lisp
compilers disagree on how to treat new package definitions
appearing in files to be compiled.
Since a book is just a source file typed by the user, ACL2 provides a
mechanism for checking that the [events] are all admissible and
then marking the file as checked. This is called certification. To
certify \"my-book.lisp\" you should first get into ACL2 with an
initial [world]. Then, define the package needed by the book, by
typing the following [defpkg] to the ACL2 [prompt]:
ACL2 !>(defpkg \"ACL2-MY-BOOK\"
(union-eq *common-lisp-symbols-from-main-lisp-package*
*acl2-exports*))
Then execute the [command]:
ACL2 !>(certify-book \"my-book\" 1 t) ; the `t' is in fact the default
Observe that you do not type the \".lisp\" part of the file name. For
purposes of [books], the book's name is \"my-book\" and by the time
all is said and done, there will be several extensions in addition
to the \".lisp\" extension associated with it.
The 1 tells [certify-book] that you acknowledge that there is one
command in this ``certification [world]'' (namely the [defpkg]). To
use the book, any prospective host [world] must be extended by the
addition of whatever [command]s occurred before certification. It
would be a pity to certify a book in a [world] containing junk
because that junk will become the ``[portcullis]'' guarding
entrance to the book. The t above tells [certify-book] that you
wish to compile \"my-book.lisp\" also (but see [compilation] for an
exception). [Certify-book] makes many checks but by far the most
important and time-consuming one is that it ``proves'' every event
in the file.
When [certify-book] is done it will have created two new files. The
first will be called \"my-book.cert\" and contains the
``[certificate]'' attesting to the admissibility of the [events] in
\"my-book.lisp\". The [certificate] contains the [defpkg] and any
other forms necessary to construct the certification [world]. It
also contains various check sums used to help you keep track of
which version of \"my-book.lisp\" was certified.
The second file that may be created by [certify-book] is the compiled
version of \"my-book.lisp\" and will have a name that is assigned by
the host compiler (e.g., \"my-book.o\" in GCL, \"my-book.fasl\" in
SBCL). [Certify-book] will also load this object file. When
[certify-book] is done, you may throw away the logical [world] it
created, for example by executing the [command] :u.
To use the book later in any ACL2 session, just execute the event
(include-book \"my-book\"). This will do the necessary [defpkg], load
the non-[local] [events] in \"my-book.lisp\" and then may load the
compiled code for the non-local functions defined in that file.
Checks are made to ensure that the [certificate] file exists and
describes the version of \"my-book.lisp\" that is read. The compiled
code is loaded if and only if it exists and has a later write date
than the source file (but see [compilation] for an exception).
Since [include-book] is itself an event, you may put such forms into
other [books]. Thus it is possible for the inclusion of a single
book to lead to the inclusion of many others. The check sum
information maintained in [certificate]s helps deal with the
version control problem of the referenced [books]. I.e., if this
version of \"my-book\" is used during the certification of
\"your-book\", then the [certificate] for \"your-book\" includes the
check sum of this version of \"my-book\". If a later (include-book
\"your-book\") finds a version of \"my-book\" with a different check
sum, an error is signalled. But check sums are not perfect and the
insecurity of the host file system prevents ACL2 from guaranteeing
the logical soundness of an [include-book] event, even for a book
that appears to have a valid [certificate] (they can be forged,
after all). (See [certificate] for further discussion.)
This concludes the example of how to create, certify and use a book.
If you wish, you could now review the [documentation] for
book-related topics (see [books]) and browse through them. They'll
probably make sense in this context. Alternatively, you could
continue the ``guided tour'' through the rest of the
[documentation] of [books]. See [book-name], following the pointer
given at the conclusion.")
(BOOK-MAKEFILES (POINTERS)
"See [books-certification].")
(BOOK-NAME
(BOOKS-TOUR)
"Conventions associated with book names
Examples:
\"list-processing\"
\"/usr/home/smith/my-arith\"
Book names are string constants that can be elaborated into file
names. We elaborate book names by concatenating the ``connected
book directory'' (see [cbd]) string on the left and some
``extension,'' such as \".lisp\", on the right. However, the
connected book directory is not added if the book name itself
already represents an absolute file name. Furthermore,
[include-book] and [certify-book] temporarily reset the connected
book directory to be the directory of the book being processed.
This allows [include-book] forms to use file names without explicit
mention of the enclosing book's directory. This in turn allows
[books] (together with those that they include, using
[include-book]) to be moved between directories while maintaining
their certification and utility.
You may wish to read elsewhere for details of ACL2 file name
conventions (see [pathname]), for a discussion of the filename that
is the result of the elaboration described here (see
[full-book-name]), and for details of the concept of the connected
book directory (see [cbd]). For details of how [include-book] (see
[include-book]) and [certify-book] (see [certify-book]) use these
concepts, see below.
Often a book name is simply the familiar name of the file. (See
[full-book-name] for discussion of the notions of ``directory
string,'' ``familiar name,'' and ``extension''. These concepts are
not on the guided tour through [books] and you should read them
separately.) However, it is permitted for book names to include a
directory or part of a directory name. Book names never include the
extension, since ACL2 must routinely tack several different
extensions onto the name during [include-book]. For example,
[include-book] uses the \".lisp\", \".cert\" and possibly the \".o\" or
\".lbin\" extensions of the book name.
Book names are elaborated into full file names by [include-book] and
[certify-book]. This elaboration is sensitive to the ``connected
book directory.'' The connected book directory is an absolute
filename string (see [pathname]) that is part of the ACL2 [state].
(You may wish to see [cbd] and to see [set-cbd] --- note that these
are not on the guided tour). If a book name is an absolute filename
string, ACL2 elaborates it simply by appending the desired
extension to the right. If a book name is a relative filename
string, ACL2 appends the connected book directory on the left and
the desired extension on the right.
Note that it is possible that the book name includes some partial
specification of the directory. For example, if the connected book
directory is \"/usr/home/smith/\" then the book name
\"project/task-1/arith\" is a book name that will be elaborated to
\"/usr/home/smith/project/task-1/arith.lisp\".
Observe that while the [events] in this \"arith\" book are being
processed the connected book directory will temporarily be set to
\"/usr/home/smith/project/task-1/\".
Thus, if the book requires other [books], e.g.,
(include-book \"naturals\")
then it is not necessary to specify the directory on which they
reside provided that directory is the same as the superior book.
This inheritance of the connected book directory and its use to
elaborate the names of inferior [books] makes it possible to move
[books] and their inferiors to new directories, provided they
maintain the same relative relationship. It is even possible to
move with ease whole collections of [books] to different
filesystems that use a different operating system than the one
under which the original certification was performed.
The \".cert\" extension of a book, if it exists, is presumed to contain
the most recent [certificate] for the book. See [certificate] (or,
if you are on the guided tour, wait until the tour gets there).
See [book-contents] to continue the guided tour.")
(BOOKDATA
(BOOKS)
"An optional tool for writing out small files with meta-data about the
books that are being certified.
ACL2 provides a primitive capability for writing out a file of data
associated with a book. This information might be useful, for
example, in building a database that allows you to search for name
conflicts. See [community-books] directory
books/tools/book-conflicts/ for an application of this capability
by Dave Greve. If you use this capability and have ideas for
enhancing it, please feel free to send them to the ACL2 developers.
If the book has the name BK, then the output file is named
BK__bookdata.out. That file is generated in the same directory as
BK, by certifying BK when [state] global 'write-bookdata has a
non-nil value, for example as follows.
(assign write-bookdata t)
(certify-book \"BK\" ...)
The resulting file will contain a single form of the following shape,
although not necessarily in the following order, according to the
description that follows below.
(\"...BK.lisp\"
:PKGS pkgs-val
:BOOKS book-val
:PORT-BOOKS port-book-val
:CONSTS consts-val
:PORT-CONSTS port-consts-val
:FNS fns-val
:PORT-FNS port-fns-val
:LABELS labels-val
:PORT-LABELS port-labels-val
:MACROS macros-val
:PORT-MACROS port-macros-val
:STOBJS stobjs-val
:PORT-STOBJS port-stobjs-val
:THEORIES theories-val
:PORT-THEORIES port-theories-val
:THMS thms-val
:PORT-THMS port-thms-val
)
The first entry in the form will always be the full book name (see
[full-book-name]) of the certified book, BK.
Subsequent values in the form are based on [events] introduced by
including BK. For various values of xxx as described below,
port-xxx-val is a list of values corresponding to [events]
introduced in the certification [world] for BK (see [portcullis]),
and xxx-val is a list of values corresponding to [events]
introduced non-[local]ly by BK. These lists include only
``top-level'' events, not those that are introduced by a book
included either in BK or its certification world.
pkgs-val is a list of names of packages introduced in the
certification world (at the top level, not in an included book).
Note that no packages are introduced in a book itself, so no
distinction is made between pkgs-val and port-pkgs-val. Both
port-book-val and book-val are lists of full book names (see
[full-book-name]) of included books. The values associated with the
other keywords are, themselves, association lists (see [alistp])
such that each key is a package name, which is associated with a
list of [symbol-name]s for symbols in that package that are
introduced for that keyword. For example, fns-val may be the alist
((\"ACL2\" \"F1\" \"F2\")
(\"MY-PKG\" \"G1\" \"G2\"))
if the function symbols introduced in the book are F1 and F2 in the
\"ACL2\" package, as well as G1 and G2 in the \"MY-PKG\" package.
We next explain what kinds of symbols are introduced for each keyword
:xxx. Each such symbol would be associated with either the keyword
:port-xxx or the keyword :xxx depending respectively on whether the
symbol is introduced at the top level of the certification world
for BK or BK itself.
:CONSTS
constant symbol introduced by defconst
:FNS
function symbol: introduced by defun, defuns, or defchoose; or
constrained (by an [encapsulate] event)
:LABELS
symbol introduced by deflabel
:MACROS
macro name introduced by defmacro
:STOBJS
stobj name introduced by defstobj or defabsstobj
:THEORIES
theory name introduced by deftheory
:THMS
theorem name, which may be introduced by defthm or a macro call
expanding to a call of defthm, such as see [defequiv] or
defaxiom; but may be introduced by [defpkg], for example, with
name \"MYPKG-PACKAGE\" if the package name is \"MYPKG\"
Our hope is that people in the ACL2 community will generate and use
this data to improve the ACL2 [community-books]. Here is an example
illustrating how to generate bookdata files for those books as a
byproduct of a regression run. Below, we write {DIR} as an
abbreviation for the ACL2 sources directory, and assume that this
command is run from that directory. Of course, you may wish to use
make options like -j 8 and make variable settings like
ACL2={DIR}/my-saved_acl2; see [books-certification] for details.
make regression-fresh \\
ACL2_CUSTOMIZATION={DIR}/acl2-customization-files/bookdata.lisp")
(BOOKS
(ACL2 NOTE1)
"Books are files of ACL2 [events]---they are the main way to split up
large ACL2 developments into separate modules.
This [documentation] topic is about ACL2 {source code |
https://en.wikipedia.org/wiki/Source_code} files. However, there
are also {traditional, paper books |
http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books}
published about ACL2 and its applications.
You will almost surely want to organize your own ACL2 work into
books. They facilitate reuse, allow you to reload proofs more
quickly, allow you to rebuild parts of your proof in parallel, and
so forth. You will also want to be aware of the many community
books, which provide useful tools and lemmas to build upon. See
[community-books] for more information, including how to
contribute.
Introduction
A book is a file of ACL2 forms. Books are prepared entirely by the
user of the system, i.e., they are source files not object files.
Some of the forms in a book are marked [local] and the others are
considered ``non-local.''
[Include-book] lets you load a book into any ACL2 [world]. A
successful include-book extends the logic of the host [world] by
adding just the non-local [events] in the book. Ordinarily, you
might include a variety of books to load all of their definitions
and rules.
Successful book inclusion is consistency preserving, provided that
the book itself is consistent, as discussed later. However,
[include-book] assumes the [events] in a book are valid, so if you
include a book that contains an inconsistency (e.g., an
inadmissible definition) then the resulting theory is inconsistent!
[Certify-book] lets you certify a book to guarantee that its
successful inclusion is consistency preserving. During
certification, both the [local] and non-local forms are processed.
This lets you mark as [local] any [events] you need for
certification, but that you want to hide from users of the
book---e.g., the hacks, crocks, and kludges on the way to a good
set of [rewrite] rules.
Certification can also [compile] a book to speed up the execution of
the functions defined within it. The desire to compile books is
largely responsible for the restrictions we put on the forms
allowed in books.
Extensive [documentation] is available on the various aspects of
books. We recommend that you read it all before using books. It has
been written so as to make sense when read in a certain linear
sequence, called the ``guided tour'', though in general you may
browse through it randomly. If you are on the guided tour, you
should next read [book-example].
Subtopics
[Bookdata]
An optional tool for writing out small files with meta-data about
the books that are being certified.
[Books-reference]
Reference guide for ACL2 functionality related to books, e.g.,
[include-book], [certify-book], [cbd], etc.
[Books-tour]
The guided tour of concepts related to ACL2 [books].
[Community-books]
Libraries of ACL2 [books] developed by the ACL2 community.
[Uncertified-books]
Invalid [certificate]s and uncertified [books]")
(BOOKS-CERTIFICATION
(COMMUNITY-BOOKS)
"Instructions for certifying the ACL2 [community-books].
Starting in ACL2 6.4 we recommend using the new Community Books make
system to certify the books. If you encounter problems using the
new system (described below) or need some feature that is no longer
available, please see [books-certification-alt] for alternate
instructions. We have not changed how make regression works from
the acl2-sources directory.
Prerequisites
We assume that you have already downloaded and installed ACL2 as per
the {ACL2 installation instructions |
http://www.cs.utexas.edu/users/moore/acl2/v7-2/HTML/installation/installation.html}
on the ACL2 home page.
We assume you know the path to your ACL2 executable. Typically this
is a script named saved_acl2 in your acl2-sources directory.
We assume the ACL2 [community-books] are installed in the books/
subdirectory of your ACL2 distribution, as is the case when you
have followed the ACL2 installation instructions above.
The instructions below are suitable for ACL2 and all of its
experimental extensions, e.g., ACL2(p) and ACL2(r).
A Basic Build
In previous versions of ACL2, building the Community Books could take
several hours. Starting in ACL2 6.4, the default build has been
made much faster by excluding many books by default.
The new default make target, called basic, now certifies only the
following, widely used books:
* arithmetic
* arithmetic-3
* arithmetic-5
* [ihs]
* misc
* tools
* [std]
* [xdoc]
* data-structures
To certify these books, you should be able to run make as follows.
The -j 2 part of this command is suitable for a computer with two
cores. If you have, e.g., a quad-core computer, you should probably
use -j 4 instead, and so on.
$ cd /path/to/acl2-sources/books
$ make ACL2=/path/to/acl2-sources/saved_acl2 -j 2 basic
If you configure your PATH so that you can launch ACL2 by typing
acl2, then you may omit the ACL2=... part.
Certifying Additional Books
We expect that most ACL2 users will want to certify at least the
basic books described above. But what if you also need other books?
One option is to do a full build (see below). But it is usually
much faster to simply tell make to build the books you actually
want to use.
There are make targets corresponding to most directory names. For
instance, to build the books under coi and rtl and cgen, you can
run:
$ cd /path/to/acl2-sources/books
$ make ACL2=/path/to/acl2-sources/saved_acl2 coi rtl cgen -j 2
For finer grained control, you can name individual books. This works
particularly well for libraries that have top books. For instance,
if you want the rtl/rel9 library, you could run:
$ cd /path/to/acl2-sources/books
$ make ACL2=/path/to/acl2-sources/saved_acl2 rtl/rel9/lib/top.cert -j 2
Books that Require ACL2 Extensions
Some books require experimental extensions to ACL2, such as ACL2(p)
(see [parallelism]) or ACL2(r) (see [real]) or their classic
variants, ACL2(cp) or ACL2(cr). Other books require certain
additional software.
The build system will automatically determine which kind of ACL2 you
are running (e.g., ACL2(c), ACL2(p), ACL2(r)) and, based on this,
may prevent incompatible books from being certified. The output of
make should explain which books are being excluded and why.
These kinds of book requirements are controlled by special
[build::cert_param] comments.
Books that Require Quicklisp
Some books, especially [interfacing-tools] like [oslib] and the ACL2
[bridge], require certain Common Lisp libraries.
These libraries are now bundled with ACL2 via [quicklisp], so you
should not need to download anything extra to use them. However,
since these libraries are not portable across all Lisps that can
run ACL2, you must explicitly enable Quicklisp by setting
USE_QUICKLISP=1 in your make command if you want to use them. For
instance:
make ACL2=... USE_QUICKLISP=1 doc/top.cert -j 4
Using Quicklisp should definitely work for CCL and SBCL. We have not
tested it with other Lisps, but there is some chance it will work
with Lisps such as Allegro, Lispworks, and CMUCL. It will almost
certainly not work for GCL.
Books that Require Additional Software
Some other books based on [satlink] and [gl] require a SAT solver,
typically Glucose, to be installed; see
[satlink::sat-solver-options] for installation options. The build
system should automatically determine if Glucose is installed on
your system, and will avoid trying to certify these books unless
Glucose is present.
Building the manual
If you just want to get a copy of the ACL2+Books manual for local
viewing, you probably don't need to build it yourself because you
can just {download | download/} a copy. If for some reason you do
want to build the manual yourself, you should be able to run, e.g.,
$ cd /path/to/acl2-sources/books
$ make manual USE_QUICKLISP=1 -j 4
Building the manual should work on at least CCL and SBCL on Linux and
Mac OS X. It may not work for some other OS/Lisp combinations. In
particular, building the manual requires some features from [oslib]
and [quicklisp] that may not be available on some other Lisps.
The resulting web-based manual may be found in:
acl2-sources/books/doc/manual/index.html
See also [ACL2-doc] for details about how to build your own
Emacs-based manual, and [xdoc::save] for general information about
how to build and distribute custom XDOC manuals, e.g., manuals that
additionally include your own unreleased books.
A Full Build
Building all of the books can take hours and is usually unnecessary.
That said, it is easy to do: just run make all, e.g.,
$ cd /path/to/acl2-sources/books
$ make ACL2=/path/to/acl2-sources/saved_acl2 -j 2 all
This actually still skips a few books that are very slow. If you
really need to certify absolutely everything, you can run make
everything, but this will likely add hours to your build!
Cleaning Up
If you want to delete generated files, you can run make clean to
remove certificates, compiled files, and build logs.
If you just want to remove the files in a particular subdirectory
(and its subdirectories), you can go into that directory and then
run the build/clean.pl script. This will delete, starting from your
current directory, recursively, all certificates, logs, compiled
files, etc.
Note that make clean doesn't remove some files, e.g., [xdoc] manuals.
To remove everything, try make moreclean.
Debugging Failed Certifications
If a book fails to certify, you may want to try certifying it in an
interactive session. The most reliable way to do this is to
replicate the environment and commands that the build system used.
This information can be found at the top of the [bookname].cert.out
file. For instance:
;; foo.cert.out
-*- Mode: auto-revert -*-
...
Environment variables:
ACL2_CUSTOMIZATION=NONE ;; <-- first configure your
ACL2_SYSTEM_BOOKS=/path/to/acl2/books ;; environment to match
ACL2=/path/to/saved_acl2 ;; these settings
...
Temp lisp file:
(acl2::value :q) ;; <--- then submit these commands to
(acl2::in-package \"ACL2\") ;; $ACL2 to debug the failure
... ;; interactively
--- End temp lisp file ---
Some other notes/tips:
* Make sure the ACL2 image you run is the same as the one listed as
ACL2 in those environment variables!
* You may wish to set the environment variables for only the duration
of your ACL2 session by using the \"env\" command.
* You may wish to edit some of the commands for better debugging
purposes; e.g. you may modify the [set-inhibit-output-lst]
command, or insert a [set-debugger-enable] command, etc.
* If you don't want your session to exit after a successful
certification, replace the last form (er-progn (time$
(certify-book ... with just the (time$ (certify-book ...))
part.
Further Resources
The build system is largely based on [build::cert.pl]. There is
considerable documentation about cert.pl, and we highly recommend
using it to manage your own ACL2 projects.
The main build script is books/GNUmakefile. There are many comments
at the start of this file, and you can also inspect it to see what
targets are available.
Please feel absolutely free to contact the [ACL2-help] mailing list
with any questions about building the community books.
Subtopics
[Books-certification-alt]
Alternate instructions for certifying the [community-books], from
the perspective of the acl2-sources directory.
[Books-certification-classic]
Classic ACL2 `make'-based certification of [books]
[Provisional-certification]
Certify a book in stages for improved book-level parallelism")
(BOOKS-CERTIFICATION-ALT
(BOOKS-CERTIFICATION)
"Alternate instructions for certifying the [community-books], from the
perspective of the acl2-sources directory.
WARNING: Parts of this documentation are probably obsolete, but parts
are still relevant. See [books-certification] as the primary source
of information on how to certify the [community-books].
For background on the ACL2 community books, see [community-books].
Here we explain how to certify those books, or some of those books,
with ACL2. We thank Bishop Brock, Jared Davis, and Sol Swords for
their substantial contributions to this methodology. See
books/GNUmakefile, in the community books, for more about ``Credits
and History'', and for additional technical details not covered in
this topic.
For more information about installing ACL2, see the {ACL2
installation instructions |
http://www.cs.utexas.edu/users/moore/acl2/v7-2/HTML/installation/installation.html}.
For information about so-called ``classic ACL2 `make'-based
certification'', which provides support for certifying directories
of books but may disappear in a future ACL2 release, see
[books-certification-classic].
The Basics
We make the following assumptions.
* Gnu `make' is available on your system via the `make' command (rather
than some other flavor of `make'). (Execute `make --version to
verify this.)
* You have built or obtained an ACL2 executable.
* The ACL2 [community-books] are installed in the books/ subdirectory
of your ACL2 distribution, as is the case when you have
followed the standard installation instructions.
Note: All commands shown below are issued in the top-level (ACL2
sources) directory of your ACL2 distribution.
By default the ACL2 executable is file saved_acl2 in your ACL2
sources directory, and you can issue the following command to the
shell in order to do a ``regression run'' that certifies all of the
community books using that executable.
make regression
Better yet, save a log file in case there are problems, for example
as follows.
(make regression) >& make-regression.log
or perhaps better yet:
(time nice make regression) >& make-regression.log
For the sake of brevity, below we'll skip mentioning any of `time',
`nice', or `>& make-regression.log'. But saving a log file, in
particular, is useful in case you encounter problems to report.
If you fetched the community books using git, then you will have a
directory books/workshops/ that is not necessary for certifying the
other books. If you want to skip certification of the books under
books/workshops/, use target `certify-books' instead of target
`regression', for example as follows.
(time nice make certify-books) >& make-certify-books.log
Whether you use target `regression' or target `certify-books', then
for each book foo.lisp whose certification is attempted, a file
foo.cert.out in the same directory will contain the output from the
book's certification attempt.
A regression run may take a few hours, but if you have a
multiprocessing computer, you can speed it up by certifying some
books in parallel, by providing a value for `make' option -j. For
example, if you have 8 hardware threads then you might want to
issue the following command.
make regression -j 8
Specifying the ACL2 Executable
If your ACL2 executable is not file saved_acl2 in the ACL2 sources
directory, then you will need to specify that executable. You can
do that by setting variable ACL2, either as an environment variable
or, as displayed below, as a `make' variable. Either way, you will
need to avoid relative pathnames. For example, the first two forms
below are legal, but the third is not, assuming that my-acl2 is on
your PATH in a Unix-like environment (e.g., linux or MacOS) and
that my-saved_acl2 is just a pathname relative to your ACL2 sources
directory, which is not on your path.
make regression -j 8 ACL2=my-acl2
make regression -j 8 ACL2=/u/smith/bin/acl2
# The following only works if my-saved_acl2 is on your path (see above).
make regression -j 8 ACL2=my-saved_acl2
Cleaning
You can delete files generated by book certification (including .cert
files, .out files, compiled files, and more) by issuing the
following command (again, in your ACL2 sources directory).
make clean-books
If you want to cause such deletion and then do a regression, simply
replace the `regression' or `certify-books' target by
`regression-fresh' or `certify-books-fresh', respectively, for
example as follows. follows.
make -j 4 regression-fresh
make -j 4 certify-books-fresh
If however you only want to clean up generated files residing under a
given directory (or its subdirectories, and recursively), you can
issue the following command while standing in that directory, where
DIR is a pathname of your books directory.
DIR/clean.pl
For example, to clean up generated files under books/arithmetic, you
could do the following.
cd books/arithmetic
../clean.pl
cd - # to return to the ACL2 sources directory, if you wish to do so
Restricting to Specific Directories and Books
You can specify which books you want certified by using any or all of
the variables EXCLUDED_PREFIXES, ACL2_BOOK_CERTS, or
ACL2_BOOK_DIRS. First, the set of desired .cert files is restricted
to those that do not start with any string that is one of the words
in the value of EXCLUDED_PREFIXES. Then ACL2_BOOK_CERTS and
ACL2_BOOK_DIRS, if supplied, specify which books should be
certified, as illustrated by the following example.
make -j 8 regression-fresh \\
ACL2_BOOK_DIRS=\"symbolic paco\" \\
ACL2_BOOK_CERTS=\" \\
workshops/2006/cowles-gamboa-euclid/Euclid/ed6a.cert \\
workshops/2006/cowles-gamboa-euclid/Euclid/ed4bb.cert \\
\"
Then all book in directories symbolic and paco will be certified, as
will the books workshops/2006/cowles-gamboa-euclid/Euclid/ed6a.lisp
and workshops/2006/cowles-gamboa-euclid/Euclid/ed4bb.lisp. Note
that all pathnames should be relative to your community books
directory; in particular, they should not be absolute pathnames.
Also notice the .cert extension used in files supplied for
ACL2_BOOK_CERTS.
Alternatively, you may wish to invoke books/cert.pl while standing in
a directory under which you want to certify books. This will
certify not only those books, but all supporting books --- even
those not under the current directory --- that do not have
up-to-date .cert files. The following is a simple command to invoke
that will certify all books in the current directory, where if the
books/ directory is not on your path, you will need to provide a
suitable filename, e.g. ../../cert.pl or ~/acl2/books/cert.pl.
cert.pl -j 4 *.lisp
Here is a more complex command, which illustrates a way to certify
books in subdirectories (as well as the current directory), the use
of provisional certification (see [provisional-certification]), and
`make'-level parallelism (in this case specifying four parallel
processes).
ACL2_PCERT=t cert.pl -j 4 `find . -name '*.lisp'`
Note that with this approach, unlike classic ACL2 `make'-based
certification (see [books-certification-classic], out-of-date .cert
files that are not under the current directory will also be built.
For documentation of cert.pl invoke:
cert.pl -h
See the top of cert.pl for authorship and copyright information.
Finally, we give a brief summary of how to use so-called ``classic
ACL2 `make'-based certification'' for community books; see
[books-certification-classic] for details. Note that support for
this approach might be eliminated in a future ACL2 release. We
welcome comments from the ACL2 community about whether or not that
would be a good thing to do. See the discussion above about
ACL2_BOOK_DIRS for the ``modern'' way to accomplish the same thing.
Many community book directories have a Makefile. If you modify books
only in such a directory, you can recertify by standing in that
directory and issuing a `make' command. This command can optionally
specify an ACL2 executable as well as parallelism, for example as
follows, where the first line (make clean) is optional.
make clean
(time nice make -j 8 ACL2=my-acl2)
ACL2 Customization Files
By default, your acl2-customization file (see [ACL2-customization])
is ignored by all flavors of ``make regression''. However, you can
specify the use of an acl2-customization file by setting the value
of environment variable ACL2_CUSTOMIZATION to the empty string,
indicating a default such file, or to the desired absolute
pathname. For example:
make regression ACL2_CUSTOMIZATION=''
make regression ACL2_CUSTOMIZATION='~/acl2-customization.lisp'
Regressions for Variants of ACL2
The discussion above also pertains to using ACL2(p) (see [parallel])
or ACL2(r) (see [real]), in which case the default is saved_acl2p
or saved_acl2r respectively, rather than saved_acl2. However, we
recommend that you use ACL2, not ACL2(p), for your regression. Then
you can use ACL2(p) for your own proof developments. However, if
you want to use ACL2(p) or for your regression, see
[waterfall-parallelism-for-book-certification].
Provisional Certification
To use provisional certification (see [provisional-certification]),
supply ACL2_PCERT=t with your `make' command. Here is an example.
time nice make regression -j 4 ACL2_BOOK_DIRS=deduction ACL2_PCERT=t
Miscellany
Other control of the certification process may be found by perusing
community books file books/make_cert. In particular, the INHIBIT
variable may be set to a call of [set-inhibit-output-lst], for
example as follows to obtain the output one would get by default in
an (interactive) ACL2 session.
time nice make regression -j 4 ACL2_BOOK_DIRS=arithmetic \\
INHIBIT='(set-inhibit-output-lst proof-tree)'
Troubleshooting
If you run into problems, you can get help by joining the acl2-help
email list (follow the link from the ACL2 home page) and sending a
message to that list. Also consider trying another version of GNU
`make'; for example, we have found that versions 3.81 and 3.82
sometimes cause errors on Linux where version 3.80 does not. Note
however that Version 3.80 does not print certain informational
messages that are printed by later versions.")
(BOOKS-CERTIFICATION-CLASSIC
(BOOKS-CERTIFICATION)
"Classic ACL2 `make'-based certification of [books]
This [documentation] topic explains an approach to certifying
directories of books, which we call ``classic ACL2 `make'-based
certification''.
Warning: The capability described in this section might be replaced
at any time by a capability based on corresponding support for
community books (see [books-certification]). If you think that
would be a hardship, please contact the ACL2 implementors.
This topic discusses a way to certify a directory of books other than
the ACL2 community books. See [books-certification] for how to
certify the set of ACL2 community [books]. There is also a section
in that [documentation] topic, ``Restricting to Specific
Directories and Books'', that provides an alternative to classic
ACL2 `make'-based certification (as discussed in the present topic)
for certifying specified sets of books.
We assume here a familiarity with Unix/Linux `make'. We also assume
that you are using GNU `make' rather than some other flavor of
`make'. And finally, we assume, as is typically the case by
following the standard installation instructions, that you install
the ACL2 community books in the books/ subdirectory of your ACL2
distribution. We will refer below to that directory as BOOKS.
In summary: to use `make' to certify [books] under a given directory,
you may create a simple Makefile in that directory (as explained
below) so that when you stand in that directory, you can submit the
command, `make', to certify those books. If you have a
multi-processor machine or the like, then you can use the `-j flag
`make'-level parallelism by specifying the number of concurrent
processes. For example:
make -j 4
For each book foo.lisp, a file foo.out in the same directory as
foo.lisp will contain the output from the corresponding
certification attempt. If you have previously executed such a
command, then you might first want to delete [certificate] files
and other generated files by executing the following command.
make clean
Note that when you run `make', then by default, the first error will
cause the process to stop. You can use make -i to force `make' to
ignore errors, thus continuing past them. Or, use make -k to keep
going, but skipping certification for any book that includes
another whose certification has failed.
By default, your acl2-customization file (see [ACL2-customization])
is ignored by such `make' commands. However, you can specify the
use of an acl2-customization file by setting the value of
environment variable ACL2_CUSTOMIZATION to the empty string,
indicating a default such file, or to the desired absolute
pathname. For example:
make ACL2_CUSTOMIZATION=''
make ACL2_CUSTOMIZATION='~/acl2-customization.lisp'
We now discuss how to create makefiles to support `make' commands as
discussed above.
First we give five steps for creating a Makefile to support
certification of a directory of books, without subdirectories. For
examples of such Makefiles you can look in community book
directories (which, however, might disappear in future versions of
ACL2).
1. Include the file Makefile-generic from the books/ subdirectory of
your ACL2 sources directory, but first perhaps define the
variable `ACL2'. Consider the following example.
ACL2 ?= /Users/john_doe/acl2/acl2-sources/saved_acl2
include /Users/john_doe/acl2/acl2-sources/books/Makefile-generic
In this example, you can omit the first line, because the default
ACL2 executable is file saved_acl2 in the directory immediately
above the directory of the specified Makefile-generic file.
Indeed, that is the common case. Note the use of ?= instead of
= or :=, so that ACL2 can instead be defined by the environment
or provided on the command line as part of the `make' command.
2. (Optional; usually skipped.) Set the INHIBIT variable if you want
to see more than the summary output. For example, if you want
to see the same output as you would normally see at the
terminal, put this line in your Makefile after the `include'
lines.
INHIBIT = (assign inhibit-output-lst (list (quote proof-tree)))
For other values to use for INHIBIT, see [set-inhibit-output-lst] and
see the original setting of INHIBIT in books/Makefile-generic.
3. Specify the books to be certified. Normally, every file with
extension .lisp will be a book that you want to certify, in
which case you can skip this step. Otherwise, put a line in
your Makefile after the ones above that specifies the books to
be certified. The following example, from an old version of
community books file books/finite-set-theory/osets/Makefile,
should make this clear.
BOOKS = computed-hints fast instance map membership outer primitives \\
quantify set-order sets sort
But better yet, use the extension .lsp for any Lisp or ACL2 files
that are not to be certified, so that the definition of BOOKS
can be omitted.
4. Create .acl2 files for books that are to be certified in other
than the initial ACL2 world (see [portcullis]). For example, if
you look in community books file
books/arithmetic/equalities.acl2 you will see [defpkg] forms
followed by a [certify-book] command, because it was determined
that [defpkg] forms were necessary in the certification world
in order to certify the equalities book. In general, for each
<book-name>.lisp whose certification requires a non-initial
certification world, you will need a corresponding
<book-name>.acl2 file that ends with the appropriate
[certify-book] command.
You also have the option of creating a file cert.acl2 that has a
special role. When file <book-name>.lisp is certified, if there
is no file <book-name>.acl2 but there is a file cert.acl2, then
cert.acl2 will be used as <book-name>.acl2 would have been
used, as described in the preceding paragraph, except that the
appropriate [certify-book] command will be generated
automatically. Thus, no certify-book command should occur in
cert.acl2.
It is actually allowed to put raw lisp forms in a .acl2 file
(presumably preceded by :q or (value :q) and followed by (lp)).
But this is not recommended; we make no guarantees about
certification performed any time after raw Lisp has been
entered in the ACL2 session.
5. Generally, the next step is to include the following line after
the `include' of Makefile-generic (see the first step above).
-include Makefile-deps
This will cause `make' to create and then include a file
Makefile-deps that contains ``dependency'' lines needed by
`make'. If those dependencies are somehow flawed, it may be
because you have [include-book] forms that are not truly
including books, for example in multi-line comments (#|..|#).
These will be ignored if preceded by a semicolon (;), or if you
add a line break after ``include-book.'' But instead of adding
the `-include' line above, you can create dependency lines
yourself by running the command
make dependencies
and pasting the result into the end of your Makefile, and editing as
you see fit.
This concludes the basic instructions for creating a Makefile in a
directory including books. Here are some other capabilities offered
by community books file books/Makefile-subdirs. Not included below
is a discussion of how to increase parallelism by avoiding the need
to certify included books before certifying a given book; see
[provisional-certification].
Subdirectory Support
There is support for using `make' to certify books in subdirectories.
Consider the following example.
DIRS = pass1 bind-free floor-mod
include ../Makefile-subdirs
This indicates that we are to run `make' in subdirectories pass1/,
bind-free/, and floor-mod/ of the current directory.
You can combine this subdirectory support with the support already
discussed for certifying books in the top-level directory. Here is
an example, which as of this writing is in community books file
books/arithmetic-3/Makefile contains the following lines.
arith-top: top all
all: top
DIRS = pass1 bind-free floor-mod
include ../Makefile-subdirs
include ../Makefile-generic
-include Makefile-deps
The `top' target is defined in ../Makefile-subdirs to call `make' in
each subdirectory specified in DIRS. We have set the default target
in the example above to a new name, arith-top, that makes that top
target before making the `all' target which, in turn, is the
default target in any Makefile-generic, and is responsible for
certifying books in the current directory as discussed in the five
steps displayed above.
Use Makefile-psubdirs instead of Makefile-subdirs if certification of
a book in a subdirectory never depends on certification of a book
in a different subdirectory, because then the -j option of `make'
can allow subdirectories to be processed in parallel.
Cleaning Up
We note that there is a clean target. Thus,
make clean
will remove generated files including .cert, .out files, and compiled
files.
System Books
An environment variable ACL2_SYSTEM_BOOKS is generally set
automatically, so you can probably skip reading the following
paragraph unless your attempt to certify books fails to locate
those books properly.
The environment variable ACL2_SYSTEM_BOOKS can be set to the
top-level directory of the ACL2 community books. A Unix-style
pathname, typically ending in books/ or books, is permissible. In
most cases, your ACL2 executable is a small script in which you can
set this environment variable just above the line on which the
actual ACL2 image is invoked, for example:
export ACL2_SYSTEM_BOOKS
ACL2_SYSTEM_BOOKS=/home/acl2/v3-2/acl2-sources/books
However, you can also set ACL2_SYSTEM_BOOKS as a `make' variable, by
setting it in your Makefile before the first target definition,
e.g.:
ACL2_SYSTEM_BOOKS ?= /home/acl2/v3-2/acl2-sources/books
Compilation Support
The file books/Makefile-generic provides support for compiling books
that are already certified (but see [compilation] for an
exception). For example, suppose that you have certified books
using GCL as the host Lisp, resulting in compiled files with the .o
extension. Now suppose you would like to compile the books for
Allegro Common Lisp, whose compiled files have the .fasl extension.
The following command will work if you have included
books/Makefile-generic in your Makefile.
make fasl
In general, the compiled file extension for a Lisp supported by ACL2
will be a target name for building compiled files for all your
books (after certifying the books, if not already up-to-date on
certification).
If you run into problems, you can get help by joining the acl2-help
email list (follow the link from the ACL2 home page) and sending a
message to that list. Also consider trying another version of GNU
`make'; for example, we have found that versions 3.81 and 3.82
sometimes cause errors on Linux where version 3.80 does not.")
(BOOKS-REFERENCE
(BOOKS)
"Reference guide for ACL2 functionality related to books, e.g.,
[include-book], [certify-book], [cbd], etc.
Subtopics
[Add-include-book-dir]
Link keyword for :dir argument of [ld] and [include-book]
[Add-include-book-dir!]
Non-[local]ly link keyword for :dir argument of [ld] and
[include-book]
[Book-compiled-file]
Creating and loading of compiled and expansion files for [books]
[Cbd]
Connected book directory string
[Certify-book]
How to produce a [certificate] for a book
[Delete-include-book-dir]
Unlink keyword for :dir argument of [ld] and [include-book]
[Delete-include-book-dir!]
Non-[local]ly unlink keyword for :dir argument of [ld] and
[include-book]
[Full-book-name]
Book naming conventions assumed by ACL2
[Include-book]
Load the [events] in a file
[Pathname]
Introduction to filename conventions in ACL2
[Set-cbd]
To set the connected book directory
[Set-write-ACL2x]
Cause [certify-book] to write out a .acl2x file")
(BOOKS-TOUR
(BOOKS)
"The guided tour of concepts related to ACL2 [books].
The tour begins with [book-example].
Subtopics
[Book-contents]
Restrictions on the forms inside [books]
[Book-example]
How to create, certify, and use a simple book
[Book-name]
Conventions associated with book names
[Certificate]
How a book is known to be admissible and where its [defpkg]s reside
[Certify-book]
How to produce a [certificate] for a book
[Include-book]
Load the [events] in a file
[Keep]
How we know if [include-book] read the correct files
[Portcullis]
The gate guarding the entrance to a certified book")
(BOOLE$
(NUMBERS ACL2-BUILT-INS)
"Perform a bit-wise logical operation on 2 two's complement integers
When integers x and y are viewed in their two's complement
representation, (boole$ op x y) returns the result of applying the
bit-wise logical operation specified by op. The following table is
adapted from documentation for the analogous Common Lisp function
{boole |
http://www.lispworks.com/documentation/HyperSpec/Body/f_boole.htm}
in the {Common Lisp Hyperspec |
http://www.lispworks.com/documentation/HyperSpec/}. Note that the
values of op for boole$ are ACL2 constants, rather than
corresponding values of op for the Common Lisp function boole.
op result
----------- ---------
*boole-1* x
*boole-2* y
*boole-andc1* and complement of x with y
*boole-andc2* and x with complement of y
*boole-and* and
*boole-c1* complement of x
*boole-c2* complement of y
*boole-clr* the constant 0 (all zero bits)
*boole-eqv* equivalence (exclusive nor)
*boole-ior* inclusive or
*boole-nand* not-and
*boole-nor* not-or
*boole-orc1* or complement of x with y
*boole-orc2* or x with complement of y
*boole-set* the constant -1 (all one bits)
*boole-xor* exclusive or
The guard of boole$ specifies that op is the value of one of the
constants above and that x and y are integers.
See any Common Lisp documentation for analogous information about
Common Lisp function boole.
Function: <boole$>
(defun boole$ (op i1 i2)
(declare (type (integer 0 15) op)
(type integer i1 i2))
(cond ((eql op *boole-1*) i1)
((eql op *boole-2*) i2)
((eql op *boole-and*) (logand i1 i2))
((eql op *boole-andc1*)
(logandc1 i1 i2))
((eql op *boole-andc2*)
(logandc2 i1 i2))
((eql op *boole-c1*) (lognot i1))
((eql op *boole-c2*) (lognot i2))
((eql op *boole-clr*) 0)
((eql op *boole-eqv*) (logeqv i1 i2))
((eql op *boole-ior*) (logior i1 i2))
((eql op *boole-nand*) (lognand i1 i2))
((eql op *boole-nor*) (lognor i1 i2))
((eql op *boole-orc1*) (logorc1 i1 i2))
((eql op *boole-orc2*) (logorc2 i1 i2))
((eql op *boole-set*) 1)
((eql op *boole-xor*) (logxor i1 i2))
(t 0)))")
(BOOLEAN-LISTP
(BOOLEANP LISTS ACL2-BUILT-INS)
"Recognizer for a true list of booleans
The predicate boolean-listp tests whether its argument is a
[true-listp] of objects each or which satisfyies [booleanp], i.e.,
is t or nil.
Function: <boolean-listp>
(defun boolean-listp (lst)
(declare (xargs :guard t))
(cond ((atom lst) (eq lst nil))
(t (and (or (eq (car lst) t) (eq (car lst) nil))
(boolean-listp (cdr lst))))))")
(BOOLEANP
(BASICS ACL2-BUILT-INS)
"Recognizer for booleans
(Booleanp x) is t if x is t or nil, and is nil otherwise.
See [generalized-booleans] for a discussion of a potential soundness
problem for ACL2 related to the question: Which Common Lisp
functions are known to return Boolean values?
Function: <booleanp>
(defun booleanp (x)
(declare (xargs :guard t))
(if (eq x t) t (eq x nil)))
Subtopics
[Boolean-listp]
Recognizer for a true list of booleans")
(BOUNDERS
(TAU-SYSTEM)
"Intervals, bounder functions, and bounder correctness
Bounder Forms 1 and 2:
(implies (and (tau-intervalp i1)
...
(or (equal (tau-interval-dom i1) 'dom1-1)
...)
...
(in-tau-intervalp x1 i1)
...)
(and (tau-intervalp (bounder-fn i1 ...))
(in-tau-intervalp target
(bounder-fn i1 ...))))
where target is either (fn x1 ... y1 ...) or (mv-nth 'n (fn x1 ... y1
...)), depending on whether we are in the Form 1 or Form 2 case,
respectively. However, the shape above is meant just as a reminder.
Details are given below.
This topic first explains the basic shape of Bounder Form 1. Then it
illustrates Bounder Form 2. Finally, it deals briefly with proving
bounder correctness theorems. The community book
tau-bounders/elementary-bounders contains bounders for various
elementary functions including [+], [*], [/], [floor], [mod],
[logand], [lognot], [logior], [logorc1], [logeqv], [logxor], and
[ash]. You might look at or include this book to see more example
theorems, to see how proofs of such theorems are managed, and to
experiment with their effects on proving theorems involving
arithmetic over finite or half-finite intervals.
A bounder correctness theorem establishes that bounder-fn is a
``bounder'' for the function fn. That means that when trying to
compute a tau for a call of fn (or, in the case of Form 2, for the
nth component of the multiple-value vector returned by a call of
fn) the tau system can call bounder-fn on the intervals containing
certain arguments of fn.
Let us start with an example. Let fn be the addition function, +
(actually, [binary-+]). Consider the target term (+ x y) and
contemplate the question: if you know intervals containing x and y,
say intx and inty respectively, what is an interval containing
their sum? The answer is pretty easy to state in English: the
domain of the answer interval is the less restrictive of the
domains of intx and inty. The lower bound of the answer interval is
the sum of the lower bounds of intx and inty, and the lower
relation is the stronger of the lower relations of intx and inty.
Analogous comments define the upper bound and relation of the
answer interval. So for example, if x is an INTEGERP such that 0 <=
x <= 10 and y is a RATIONALP such that 0 < y <= 20, then (+ x y) is
a RATIONALP such that 0 < (+ x y) <= 30.
Defining this precisely is more tedious than describing it in English
because one must make precise the notions of ``less restrictive''
domains, ``weaker'' relations, and the possibility that either or
both of the bounds could be ``infinite.'' But we can easily imagine
defining the function bounder-for-+ that returns the answer
interval described, given intx and inty.
Then the following Bounder Form 1 formula establishes the correctness
of bounder-for-+ and allows the tau system to use it to produce
bounds in the tau computed for +-expressions:
(implies (and (tau-intervalp intx)
(tau-intervalp inty)
(in-tau-intervalp x intx)
(in-tau-intervalp y inty))
(and (tau-intervalp (bounder-for-+ intx inty))
(in-tau-intervalp (+ x y)
(bounder-for-+ intx inty))))
For example, suppose we have a formula with the following hypotheses
(and (integerp a)
(<= 0 a)
(<= a 10)
(rationalp b)
(< 0 b)
(<= b 20))
and suppose the tau system encounters the term (+ a b). When the term
is enountered, the tau for a would include an INTEGERP interval
such that 0 <= a <= 10 and the tau for b would include a RATIONALP
interval such that 0 < b <= 20. In its most primitive
configuration, the tau system would only know that the tau for (+ a
b) includes the recognizer RATIONALP (and all that it is known to
imply). But after the bounder theorem above is proved and available
as a :tau-system rule the tau system would infer that (+ a b) was
in the RATIONALP interval such that 0 < (+ a b) <= 30.
Thus, by defining bounder functions and proving them correct the user
can give the tau system the ability to compute the bounds on
function calls as a function of the known bounds on their actuals.
It is sometimes useful to restrict the domains of the intervals to be
considered. For example, in bounding *-expressions it is
simplifying to restrict one's attention to intervals over the
integers or rationals (and thus exclude the complex rationals so
one need not think about the getting negative bounds by multiplying
two ``positive'' complex rationals or how to ``round up'' from
complex bounds to the rationals required by our intervals).
If we were to define bounder-for-* so that it works correctly to
bound *-expressions, but only for integer or rational arguments,
its correctness theorem would be:
(implies (and (tau-intervalp intx) ; (a)
(tau-intervalp inty)
(or (equal (tau-interval-dom intx) 'INTEGERP) ; (b)
(equal (tau-interval-dom intx) 'RATIONALP))
(or (equal (tau-interval-dom inty) 'INTEGERP)
(equal (tau-interval-dom inty) 'RATIONALP))
(in-tau-intervalp x intx) ; (c)
(in-tau-intervalp y inty))
(and (tau-intervalp (bounder-for-* intx inty)) ; (d)
(in-tau-intervalp (* x y) ; (e)
(bounder-for-* intx inty))))
In this case, bounder-for-* would be applied to the intervals for x
and y only if those intervals were over the integers or the
rationals.
The above theorem for bounder-for-* begins to suggest the general
form of a bounder theorem and we will use it to explain the general
form.
The hypotheses of a bounder theorem must be a conjunction and the
conjuncts must be partitionable into three parts, (a), (b), and
(c). The conclusion, must be a conjunction, must contain at least
two conjuncts, (d) and (e), and is allowed to contain others that
are simply ignored for purposes of bounders. (See the note below
about why we allow but ignore additional conjuncts in the
conclusion.)
Part (a) introduces some distinct ``interval variables,'' here called
``ivars,'' that are known to denote intervals; for the example
above, the ivars are intx and inty. Each hypothesis in part (a) is
of the form (TAU-INTERVALP ivar).
Part (b) allows us to restrict the domains of some of the intervals.
Each hypothesis in part (b) must be a disjunction and each of the
disjuncts must be of the form (EQUAL (TAU-INTERVAL-DOM ivar) 'dom),
where ivar is one of the interval variables and dom is one of
INTEGERP, RATIONALP, ACL2-NUMBERP, or NIL. It is not necessary to
restrict every interval variable. Indeed, part (b) may be empty, as
in the theorem for bounder-for-+ above.
Part (c) consists of a set of (IN-TAU-INTERVALP avar ivar) hypotheses
where each avar is a variable and no two hypotheses in part (c) use
the same avar or ivar. We call the set of all such avar the
``actual variables'' or ``avars.'' The avars and ivars must be
distinct. Part (c) sets up a correspondence between the avars and
the ivars, each avar is in an interval denoted by one ivar.
Part (d) introduces the name of the bounder function, here
bounder-for-*, and the order of its ivar arguments. We see that
bounder-for-* takes two arguments and they correspond, in order, to
the intervals containing x and y. Part (d) also establishes that
the bounder function always returns an interval under hypotheses
(a), (b), and (c). Note that it is sometimes useful to return the
``universal interval'' (one that contains everything) if you don't
want to compute a better interval for some case; see
[tau-intervalp] or [in-tau-intervalp].
Part (e) introduces the name of the function being bounded, here *,
and the order of its arguments. It establishes that the function
being bounded really is bounded by the interval computed by the
bounder function. In general, the function being bounded may take
additional arguments. It is possible that the function being
bounded takes some arguments that do not affect the bounds of its
output.
Thus, parts (c) and (e) together establish a mapping between the
actuals of a call of the function being bounded and the intervals
to be supplied to the bounder.
The parts identified above may be presented in any order and the
literals constituting those parts may be mingled. Thus, for
example, here is another version of the theorem above that
generates the same bounding information for the tau system. In this
version, the hypotheses and conclusions are rearranged,
bounder-for-* takes its arguments in the opposite order, and the
theorem includes an additional conclusion.
(implies (and (tau-intervalp intx) ; (a)
(or (equal (tau-interval-dom intx) 'INTEGERP) ; (b)
(equal (tau-interval-dom intx) 'RATIONALP))
(in-tau-intervalp x intx) ; (c)
(tau-intervalp inty) ; (a)
(or (equal (tau-interval-dom inty) 'INTEGERP) ; (b)
(equal (tau-interval-dom inty) 'RATIONALP))
(in-tau-intervalp y inty))
(and (in-tau-intervalp (* x y) ; (e)
(bounder-for-* inty intx))
(tau-intervalp (bounder-for-* inty intx)) ; (d)))
(or (equal (tau-interval-dom (bounder-for-* inty intx))
'INTEGERP)
(equal (tau-interval-dom (bounder-for-* inty intx))
'RATIONALP))
Note on why bounder forms allow additional conjuncts in the
conclusion: It is often the case that one creates bounders by
composing other bounders. To prove compositional bounds correct one
must often prove more than the mere correctness of the components.
For example, one might need to prove that the domain of the new
bounding interval is INTEGERP or otherwise restricted. We allow
such ``unnecessary'' conclusions simply to save the user the burden
of stating multiple theorems.
An Illustration of Bounder Form 2: Suppose (quad i) is defined so
that truncates the integer i to the largest multiple of 4 weakly
below i and, additionally, returns the remainder. For example,
(quad 26) returns (mv 24 2). Then here are bounders for each of its
return values:
(defun quad-bounds-0 (i)
(cond ((and (tau-interval-lo i)
(<= 0 (tau-interval-lo i)))
(make-tau-interval 'integerp nil 0 nil (tau-interval-hi i)))
(t (make-tau-interval nil nil nil nil nil))))
(defun quad-bounds-1 (i)
(cond ((and (tau-interval-lo i)
(<= 0 (tau-interval-lo i)))
(make-tau-interval 'integerp nil 0 nil 3))
(t (make-tau-interval nil nil nil nil nil))))
Note that the bounders assume i is an INTEGERP and return the
universal interval when i is not a natural.
As noted in the discussion below about how to prove bounder
correctness theorems, proving these bounders correct will require
an arithmetic book, e.g.,
(include-book \"arithmetic-5/top\" :dir :system)
Here then are two bounder correctness theorems of Form 2:
(defthm quad-bounds-0-correct
(implies (and (tau-intervalp i)
(equal (tau-interval-dom i) 'INTEGERP)
(in-tau-intervalp x i))
(and (tau-intervalp (quad-bounds-0 i))
(in-tau-intervalp (mv-nth 0 (quad x))
(quad-bounds-0 i))))
:rule-classes :tau-system)
(defthm quad-bounds-1-correct
(implies (and (tau-intervalp i)
(equal (tau-interval-dom i) 'INTEGERP)
(in-tau-intervalp x i))
(and (tau-intervalp (quad-bounds-1 i))
(in-tau-intervalp (mv-nth 1 (quad x)) (quad-bounds-1 i))))
:rule-classes :tau-system)
As noted above, if these bounders are to be used in constructing
other bounders, we might include (in the first theorem) an
additional concluding conjunct, such as
(equal (tau-interval-dom (quad-bounds-0 i)) 'INTEGERP)
so that we can keep quad-bounds-0 disabled to allow us to use
quad-bounds-0-correct as a :rewrite or other rule and still relieve
hypotheses about the domain of the interval it produces. These
hypotheses would arise if some other verified bounder was called on
the produced interval. In addition, as noted below, we might
replace the :rule-classes above with
:rule-classes
((:rewrite)
(:forward-chaining :trigger-terms ((quad-bounds-0 i))))
Since the theorem is being stored as some kind of rule and since it
satisfies the Bounder Form 2 shape, it will additionally be stored
as a :tau-system rule.
Note on proving bounder theorems: Proving bounder theorems is just
like proving any other arithmetic theorem and you will need
whatever libraries are appropriate for the problem domain you are
working in. Do not expect the tau system to be of much use in
proving bounder theorems. A typical bounder theorem might require
you to prove a subgoal like (< (fn x y) (g (tau-interval-hi int1)
int2)). But tau deals with inequalities relating terms to
constants, e.g., (< ... 16). A bounder theorem is a sort of
``metatheorem'' about how to construct bounded intervals from other
bounded intervals. So when you undertake to define a bounder and
prove it correct, go into the project with your eyes open!
But bounder functions can be broadly divided into two classes, those
defined in terms of arithmetic on the interval bounds and those
defined in terms of other bounders. For example, given that
(LOGXOR x y) = (LOGNOT (LOGEQV x y))
an interval for bounding LOGXOR can be constructed by composing the
constructions of intervals for LOGEQV and LOGNOT. So some bounder
correctness proofs will involve direct manipulation of arithmetic
inequalities and others might involve appeal to the correctness of
other bounders, depending on how the new bounder is defined.
Regardless of which style of bounder we are dealing with, we have
found it useful to prove the basic theorems relating the tau
interval accessors to [make-tau-interval], e.g.,
(equal (tau-interval-dom (make-tau-interval dom lo-rel lo hi-rel hi)) dom)
and then disable those functions to avoid seeing excessive cars and
cdrs.
When dealing with bounders defined in the direct, arithmetic style,
we tend to keep [tau-intervalp] and [in-tau-intervalp] enabled so
they unfold and expose the algebra.
When dealing with bounders defined compositionally in terms of other
verified bounders, we tend to keep [tau-intervalp] and
[in-tau-intervalp] disabled so we can rely on the previously proved
bounder theorems as rewrite and forward chaining rules.
Note that this last remark means that when you prove bounder
correctness theorems you should include corollaries that are useful
:rewrite and possibly :forward-chaining rules if you anticipate
using that bounder in more complex ones. We tend to trigger the
forward chaining with the bounder expression itself, rather than
one of the hypotheses. For example in the rule above for
bounder-for-* we would include (:forward-chaining :trigger-terms
((tau-bounder-expt2 int2))) and let the in-tau-intervalp hypotheses
select the free variables x and y.")
(BREAK$
(ERRORS ACL2-BUILT-INS)
"Cause an immediate Lisp break
ACL2 users are generally advised to avoid breaking into raw Lisp.
Advanced users may, on occasion, see the need to do so. Evaluating
(break$) will have that effect. (Exception: break$ is disabled
after evaluation of (set-debugger-enable :never); see
[set-debugger-enable].) Break$ returns nil.
Function: <break$>
(defun break$ nil (declare (xargs :guard t))
nil)")
(BREAK-LEMMA
(BREAK-REWRITE)
"A quick introduction to breaking rewrite rules in ACL2
Example:
:brr t ; if you haven't done that yet
:monitor (:rewrite lemma12) t ; to install a break point on the
; rule named (:rewrite lemma12)
ACL2 does not support Nqthm's break-lemma but supports a very similar
and more powerful break facility. Suppose some proof is failing;
apparently some particular rule is not being used and you wish to
learn why. Then you need the ACL2 [break-rewrite] facility. See
[break-rewrite] and all of its associated :[doc] topics for
details. The following basic steps are required.
(1) To enable the ``break rewrite'' feature, you must first execute
ACL2 !>:brr t
at the top-level of ACL2. Equivalently, evaluate (brr t).
[Break-rewrite] stays enabled until you disable it with (brr nil).
When [break-rewrite] is enabled the ACL2 rewriter will run slower
than normal but you will be able to [monitor] the attempts to apply
specified rules.
(2) Decide what [rune]s (see [rune]) you wish to [monitor]. For
example, you might want to know why (:rewrite lemma12 . 2) is not
being used in the attempted proof. That, by the way, is the name of
the second rewrite rule generated from the event named lemma12.
The command
ACL2 !>:monitor (:rewrite lemma12 . 2) t
will install an ``unconditional'' break point on that rule. The ``t''
at the end of the command means it is unconditional, i.e., a break
will occur every time the rule is tried. ACL2 supports conditional
breaks also, in which case the t is replaced by an expression that
evaluates to non-nil when you wish for a break to occur. See
[monitor]. The above keyword command is, of course, equivalent to
ACL2 !>(monitor '(:rewrite lemma12 . 2) t)
which you may also type. You may install breaks on as many rules as
you wish. You must use [monitor] on each rule. You may also change
the break condition on a rule with [monitor]. Use [unmonitor] (see
[unmonitor]) to remove a rule from the list of [monitor]ed rules.
(3) Then try the proof again. When a [monitor]ed rule is tried by the
rewriter you will enter an interactive break, called
[break-rewrite]. See [break-rewrite] for a detailed description.
Very simply, [break-rewrite] lets you inspect the context of the
attempted application both before and after the attempt. When
[break-rewrite] is entered it will print out the ``target'' term
being rewritten. If you type :go [break-rewrite] will try the rule
and then exit, telling you (a) whether the rule was applied, (b) if
so, how the target was rewritten, and (c) if not, why the rule
failed. There are many other commands. See [brr-commands].
(4) When you have finished using the [break-rewrite] feature you
should disable it to speed up the rewriter. You can disable it with
ACL2 !>:brr nil
The list of [monitor]ed rules and their break conditions persists but
is ignored. If you enable [break-rewrite] later, the list of
[monitor]ed rules will be displayed and will be used again by
rewrite.
You should disable the [break-rewrite] feature whenever you are not
intending to use it, even if the list of [monitor]ed rules is
empty, because the rewriter is slowed down as long as
[break-rewrite] is enabled.
If you get a stack overflow, see [cw-gstack].")
(BREAK-ON-ERROR
(TRACE ACL2-BUILT-INS)
"Break when encountering a hard or soft error caused by ACL2
General forms:
(break-on-error t) ; installs a trace causing a continuable error (break)
; when an error is invoked by ACL2.
(break-on-error) ; same as above
(break-on-error :all) ; same as above, but even when inside the prover
(break-on-error nil) ; uninstall any above trace
(Break-on-error) generates a suitable trace of error functions.
Evaluate (trace$) after (break-on-error) if you want to see the
specific trace forms (which you can modify and then submit directly
to trace$, if you wish). This [trace] should cause entry to the
Lisp debugger whenever ACL2 calls its error routines, except for
certain errors when inside the theorem prover, and also at those
times if option :all is supplied.
NOTE: For technical reasons, you may see some error messages more
than once.
Finally, note that you are welcome to define your own version of
break-on-error by modifying a copy of the source definition (search
for ``(defmacro break-on-error'' in ACL2 source file
other-events.lisp). Please feel free to send your version of
break-on-error to the ACL2 implementors, for possible inclusion
into ACL2.
Break-on-error is implmented using ACL2 [trace$]. See [trace!] if you
want an explanation of the ``TTAG NOTE'' that is printed.
The argument, if supplied, is evaluated and must evaluate to t, nil,
or :all.
Also see [set-debugger-enable] for how to get raw-Lisp backtrace
information when an error occurs as a result of break-on-error, or
even of a raw Lisp error, by calling set-debugger-enable with
argument :bt, :bt-break, or :break-bt. Note that for ACL2 errors
(as opposed to raw Lisp errors), i.e. errors affected by
break-on-error, all three of those keyword values are treated
equivalently (and, all are ignored for non-ANSI GCL; see
[set-debugger-enable]).")
(BREAK-REWRITE
(DEBUGGING)
"The read-eval-print loop entered to [monitor] rules
ACL2 allows the user to [monitor] the application of [rewrite],
[definition], and [linear] rules. When [monitor]ed rules are about
to be tried by the rewriter, an interactive break occurs and the
user is allowed to watch and, in a limited sense, control the
attempt to apply the rule. This interactive loop, which is
technically just a call of the standard top-level ACL2
read-eval-print loop, [ld], on a ``[wormhole] [state]'' (see
[wormhole]), is called ``break-rewrite.'' While in break-rewrite,
certain keyword commands are available for accessing information
about the context in which the lemma is being tried. These keywords
are called break-rewrite ``commands''; see [brr-commands].
For a related utility, see [dmr] (Dynamically Monitor Rewrites),
which allows you to watch progress of the rewriter in real time.
To abort from inside break-rewrite at any time, execute :[a!].
For further information, see the related :[doc] topics listed below.
It is possible to cause the ACL2 rewriter to [monitor] the attempted
application of selected rules. When such a rule is about to be
tried, the rewriter evaluates its break condition and if the result
is non-nil, break-rewrite is entered.
Break-rewrite permits the user to inspect the current [state] by
evaluating break-rewrite commands. Type :help in break-rewrite to
see what the break-rewrite commands are. However, break-rewrite is
actually just a call of the general ACL2 read-eval-print loop,
[ld], on a certain [state] and the break-rewrite commands are
simply aliases provided by ld-keyword-aliases [table] (see
[ld-keyword-aliases]). See [ld] for details about this
read-eval-print loop. Thus, with a few exceptions, anything you can
do at the ACL2 top-level can be done within break-rewrite. For
example, you can evaluate arbitrary expressions, use the keyword
command hack, access [documentation], print [events], and even
define functions and prove theorems. However, the ``certain
[state]'' upon which [ld] was called is a ``[wormhole] [state]''
(see [wormhole]) because break-rewrite is not allowed to have any
effect upon the behavior of rewrite. What this means, very roughly
but understandably, is that break-rewrite operates on a copy of the
[state] being used by rewrite and when break-rewrite exits the
[wormhole] closes and the [state] ``produced'' by break-rewrite
disappears. Thus, break-rewrite lets you query the state of the
rewriter and even do experiments involving proofs, etc., but these
experiments have no effect on the ongoing proof attempt. In
particular:
Note that the output from break-rewrite is sometimes abbreviated by
default, such as for the term causing the break. This can be
controlled by setting the :term evisc-tuple; see [set-evisc-tuple].
(Another option: use iprinting. See [set-iprint].) But as noted
above, if you use set-evisc-tuple from inside the break-rewrite
[wormhole], its effect will disappear when you exit the break. So
you might want to issue a set-evisc-tuple command from the top
level, outside break-rewrite.
When you first enter break-rewrite a simple herald is printed such
as:
(3 Breaking (:rewrite lemma12) on (delta a (+ 1 j)):
The integer after the open parenthesis indicates the depth of nested
break-rewrite calls. In this discussion we use 3 consistently for
this integer. Unless you abort or somehow enter unbalanced
parentheses into the script, the entire session at a given depth
will be enclosed in balanced parentheses, making it easy to skip
over them in Emacs.
You then will see the break-rewrite [prompt]:
3 ACL2 !>
The leading integer is, again, the depth. Because breaks often occur
recursively it is convenient always to know the level with which
you are interacting.
You may type arbitrary commands as in the top-level ACL2 loop. For
example, you might type:
3 ACL2 !>:help
or
3 ACL2 !>:pe lemma12
More likely than typing a history or [disabledp] command, upon
entering break-rewrite you will determine the context of the
attempted application. Here are some useful commands:
3 ACL2 >:target ; the term being rewritten
3 ACL2 >:unify-subst ; the unifying substitution
3 ACL2 >:path ; the stack of goals pursued by the rewriter
; starting at the top-level clause being simplified
; and ending with the current application
At this point in the interaction the system has not yet tried to
apply the [monitor]ed rule. That is, it has not tried to establish
the hypotheses, considered the heuristic cost of backchaining,
rewritten the right-hand side of the conclusion, etc. When you are
ready for it to try the rule you can type one of several different
``proceed'' commands. The basic proceed commands are :ok, :go, and
:eval.
:ok
exits break-rewrite without further interaction. When break-rewrite
exits it prints ``3)'', closing the parenthesis that opened the
level 3 interaction.
:go
exits break-rewrite without further interaction, but prints out the
result of the application attempt, i.e., whether the application
succeeded, if so, what the :target term was rewritten to, and if
not why the rule was not applicable.
:eval
causes break-rewrite to attempt to apply the rule but interaction at
this level of break-rewrite resumes when the attempt is complete.
When control returns to this level of break-rewrite a message
indicating the result of the application attempt (just as in :go)
is printed, followed by the [prompt] for additional user input.
Generally speaking, :ok and :go are used when the break in question
is routine or uninteresting and :eval is used when the break is one
that the user anticipates is causing trouble. For example, if you
are trying to determine why a lemma isn't being applied to a given
term and the :target of the current break-rewrite is the term in
question, you would usually :eval the rule and if break-rewrite
reports that the rule failed then you are in a position to
determine why, for example by carefully inspecting the
:[type-alist] of governing assumptions or why some hypothesis of
the rule could not be established.
It is often the case that when you are in break-rewrite you wish to
change the set of [monitor]ed [rune]s. This can be done by using
:[monitor] and :[unmonitor] as noted above. For example, you might
want to [monitor] a certain rule, say hyp-reliever, just when it is
being used while attempting to apply another rule, say main-lemma.
Typically then you would [monitor] main-lemma at the ACL2
top-level, start the proof-attempt, and then in the break-rewrite
in which main-lemma is about to be tried, you would install a
[monitor] on hyp-reliever. If during the ensuing :eval hyp-reliever
is broken you will know it is being used under the attempt to apply
main-lemma.
However, once hyp-reliever is being [monitor]ed it will be
[monitor]ed even after main-lemma has been tried. That is, if you
let the proof attempt proceed then you may see many other breaks on
hyp-reliever, breaks that are not ``under'' the attempt to apply
main-lemma. One way to prevent this is to :eval the application of
main-lemma and then :[unmonitor] hyp-reliever before exiting. But
this case arises so often that ACL2 supports several additional
``flavors'' of proceed commands.
:Ok!, :go!, and :eval! are just like their counterparts (:ok, :go,
and :eval, respectively), except that while processing the rule
that is currently broken no [rune]s are [monitor]ed. When
consideration of the current rule is complete, the set of
[monitor]ed [rune]s is restored to its original setting.
:Ok$, :go$, and :eval$ are similar but take an additional argument
which must be a list of [rune]s. An example usage of :eval$ is
3 ACL2 !>:eval$ ((:rewrite hyp-reliever))
These three commands temporarily install unconditional breaks on the
[rune]s listed, proceed with the consideration of the currently
broken rule, and then restore the set of [monitor]ed rules to its
original setting.
Thus, there are nine ways to proceed from the initial entry into
break-rewrite although we often speak as though there are two, :ok
and :eval, and leave the others implicit. We group :go with :ok
because in all their flavors they exit break-rewrite without
further interaction (at the current level). All the flavors of
:eval require further interaction after the rule has been tried.
To abort a proof attempt and return to the top-level of ACL2 you may
at any time type (a!) followed by a carriage return. If you are not
in a raw Lisp break, you may type :a! instead. The utility p! is
completely analogous to a! except that it pops up only one [ld]
level. If you have just entered the break-rewrite loop, this will
pop you out of that loop, back to the proof. See [a!] and see [p!].
We now address ourselves to the post-:eval interaction with
break-rewrite. As noted, that interaction begins with
break-rewrite's report on the results of applying the rule: whether
it worked and either what it produced or why it failed. This
information is also printed by certain keyword commands available
after :eval, namely :wonp, :rewritten-rhs or (for [linear] rules)
:poly-list, and :failure-reason. In addition, by using [brr@] you
can obtain this information in the form of ACL2 data objects. This
allows the development of more sophisticated ``break conditions'';
see [monitor] for examples. In this connection we point out the
macro form (ok-if term). See [ok-if]. This command exits
break-rewrite if term evaluates to non-nil and otherwise does not
exit. Thus it is possible to define macros that provide other kinds
of exits from break-rewrite. The only way to exit break-rewrite
after :eval is :ok (or, equivalently, the use of [ok-if]).
Note that when inside break-rewrite, all [history] commands, such as
:[pe], show the [enable]d status of rules with respect to the the
current point in the proof attempt. For example, if you break while
the prover is working on Subgoal 3, and the [hints] supplied for
the proof specify (\"Subgoal 3\" :in-theory (disable foo)) for some
rule foo, then :[pe] will indicate that foo is [disable]d: even
though foo may be enabled globally, it is shown as disabled because
it is disabled during Subgoal 3. See subtopics of [history] for a
list of all such history commands. In addition to those commands,
the function [disabledp] is also evaluated inside break-rewrite
with respect to the current enabled state of the prover.
ACL2 users who wish to know more about break-rewrite so that they can
develop more convenient ways to [monitor] rules are encouraged to
speak to J Moore.
The rest of this [documentation] discusses a few implementation
details of break-rewrite and may not be interesting to the typical
user.
There is no ACL2 function named break-rewrite. It is an illusion
created by appropriate calls to two functions named brkpt1 and
brkpt2. As previously noted, break-rewrite is [ld] operating on a
[wormhole] [state]. One might therefore wonder how break-rewrite
can apply a rule and then communicate the results back to the
rewriter running in the external [state]. The answer is that it
cannot. Nothing can be communicated through a [wormhole]. In fact,
brkpt1 and brkpt2 are each calls of [ld] running on [wormhole]
[state]s. Brkpt1 implements the pre-:eval break-rewrite and brkpt2
implements the post-:eval break-rewrite. The rewriter actually
calls brkpt1 before attempting to apply a rule and calls brkpt2
afterwards. In both cases, the rewriter passes into the [wormhole]
the relevant information about the current context. Logically
brkpt1 and brkpt2 are no-ops and [rewrite] ignores the nil they
return. But while control is in them, the execution of [rewrite] is
suspended and cannot proceed until the break-rewrite interactions
complete.
This design causes a certain anomoly that might be troubling. Suppose
that inside break-rewrite before :evaling a rule (i.e., in the
brkpt1 [wormhole] [state]) you define some function, foo. Suppose
then you :eval the rule and eventually control returns to
break-rewrite (i.e., to brkpt2 on a [wormhole] [state] with the
results of the application in it). You will discover that foo is no
longer defined! That is because the [wormhole] [state] created
during your pre-:eval interaction is lost when we exit the
[wormhole] to resume the proof attempt. The post-:eval [wormhole]
[state] is in fact identical to the initial pre-:eval [state]
(except for the results of the application) because [rewrite] did
not change the external [state] and both [wormhole] [state]s are
copies of it. A similar issue occurs with the use of [trace]
utilities: all effects of calling [trace$] and [untrace$] are
erased when you proceed from a break in the break-rewrite loop.
There is a lot more to know about break-rewrite, most of which is
fairly easy to learn from looking at the code, since it is all
expressed in ACL2. Feel free to ask questions of J Moore.
Subtopics
[Break-lemma]
A quick introduction to breaking rewrite rules in ACL2
[Brr]
To enable or disable the breaking of rewrite rules
[Brr-commands]
[Break-Rewrite] Commands
[Brr@]
To access context sensitive information within [break-rewrite]
[Cw-gstack]
Debug a rewriting loop or stack overflow
[Dmr]
Dynamically monitor rewrites and other prover activity
[Monitor]
To monitor the attempted application of a rule name
[Monitored-runes]
Print the [monitor]ed [rune]s and their break conditions
[Ok-if]
Conditional exit from break-rewrite
[Unmonitor]
To stop monitoring a rule name
[Why-brr]
An explanation of why ACL2 has an explicit [brr] mode
[With-brr-ens]
Inside [break-rewrite], evaluate with respect to the theory
currently installed in the prover")
(BREAKS
(ERRORS)
"Common Lisp breaks
Example:
Broken at PROVE. Type :H for Help.
>>:Q
ACL2 !>
You may interrupt the system by typing various control character
sequences. The precise sequences are determined by the host Lisp
and operating system environment. For example, in GCL and Allegro
Common Lisp, a console interrupt is caused by typing ``ctrl-c''.
If, however, the GCL or Allegro is running in an Emacs shell
buffer, one must type ``ctrl-c ctrl-c''.
If a break occurs, for example because of a bug in ACL2 or a user
interrupt, the break will run a Common Lisp read-eval-print loop,
not an ACL2 read-eval-print loop. This may not be obvious if the
[prompt]s in the two loops are similar. Because you are typing to a
Common Lisp evaluator, you must be careful. It is possible to
damage your ACL2 state in irreparable ways by executing non-ACL2
Common Lisp. It is even possible to disrupt and render inaccurate
the interrupted evaluation of a simple ACL2 expression.
For ACL2 built on most host Common Lisps, you will see the string
[RAW LISP] in the [prompt] at a break, to emphasize that one is
inside a break and hence should quit from the break. For some host
Common Lisps, the top-level prompt also contains the string [RAW
LISP]. See [prompt] for how to control printing of that string.
The most reliable way to return to the ACL2 top level is by executing
the following command: ([abort!]). Appropriate cleanup will then be
done, which should leave you in an appropriate state.
However, you may be able to quit from the break in the normal Lisp
manner (as with :q in GCL or CCL, :reset in Allegro CL, and q in
CMU CL). If this attempt to quit is successful, it will return you
to the innermost ACL2 read-eval-print loop, with appropriate
cleanup performed first. Note that if you are within a [brr]
environment when the break occurs, quitting from the break will
only return you to that environment, not to the top of ACL2's
read-eval-print loop.")
(BROKEN-LINK
(DOCUMENTATION)
"Placeholder for link to documentation that resides in the community
books
You may have attempted to access information about the ACL2
[community-books] while looking at the ACL2 User's Manual, which
contains [documentation] only about the ACL2 system, and does not
include documentation from the [community-books]. Please point your
browser at the {ACL2+Books Manual |
http://www.cs.utexas.edu/users/moore/acl2/v7-2/combined-manual/index.html}
(or if browsing in [ACL2-Doc], switch to that manual with meta-0 I)
to access the desired topic.
If you want information about the book where your missing topic is
defined, see [broken-link-table].
Subtopics
[Broken-link-table]
Map [documentation] topics to the community books that define them")
(BROKEN-LINK-TABLE
(BROKEN-LINK)
"Map [documentation] topics to the community books that define them
The table below maps topics to book locations that reside only in the
ACL2+Books combined manual, not the ACL2 User's Manual. For
example, the entry
(note-7-2-books \"[books]/doc/relnotes.lisp\")
signifies that the topic NOTE-7-2-BOOKS is documented in the
community book doc/relnotes.lisp.
((<< \"[books]/misc/total-order.lisp\")
(append-without-guard \"[books]/std/lists/flatten.lisp\")
(oslib::argv \"[books]/oslib/argv-logic.lisp\")
(arith-equivs \"[books]/centaur/misc/arith-equiv-defs.lisp\")
(arithmetic \"[books]/doc/more-topics.lisp\")
(arithmetic-1 \"[books]/arithmetic/top.lisp\")
(arithmetic/natp-posp \"[books]/arithmetic/natp-posp.lisp\")
(b* \"[books]/std/util/bstar.lisp\")
(bridge \"[books]/centaur/bridge/top.lisp\")
(build::cert.pl \"[books]/build/doc.lisp\")
(build::cert_param \"[books]/build/doc.lisp\")
(std::defaggregate \"[books]/std/util/defaggregate.lisp\")
(defconsts \"[books]/std/util/defconsts.lisp\")
(defdata \"[books]/acl2s/defdata/top.lisp\")
(define \"[books]/std/util/define.lisp\")
(fty::defprod \"[books]/centaur/fty/top.lisp\")
(getopt-demo::demo2 \"[books]/centaur/getopt/demo2.lisp\")
(do-not-hint \"[books]/tools/do-not.lisp\")
(fty \"[books]/centaur/fty/top.lisp\")
(getopt \"[books]/centaur/getopt/top.lisp\")
(gl \"[books]/centaur/gl/doc.lisp\")
(hacker \"[books]/hacking/hacking-xdoc.lisp\")
(ihs \"[books]/ihs/ihs-doc-topic.lisp\")
(include-raw \"[books]/tools/include-raw.lisp\")
(make-flag \"[books]/tools/flag.lisp\")
(str::natstr \"[books]/std/strings/decimal.lisp\")
(non-parallel-book \"[books]/std/system/non-parallel-book.lisp\")
(note-6-4-books \"[books]/doc/relnotes.lisp\")
(note-6-5-books \"[books]/doc/relnotes.lisp\")
(note-7-0-books \"[books]/doc/relnotes.lisp\")
(note-7-1-books \"[books]/doc/relnotes.lisp\")
(note-7-2-books \"[books]/doc/relnotes.lisp\")
(str::numbers \"[books]/std/strings/top.lisp\")
(oracle-timelimit \"[books]/tools/oracle-timelimit.lisp\")
(oslib \"[books]/oslib/top-logic.lisp\")
(patbind-the \"[books]/std/util/bstar.lisp\")
(build::pre-certify-book-commands \"[books]/build/doc.lisp\")
(str::pretty \"[books]/std/strings/pretty.lisp\")
(str::pretty-printing \"[books]/std/strings/pretty.lisp\")
(quicklisp \"[books]/centaur/quicklisp/top.lisp\")
(removable-runes \"[books]/tools/removable-runes.lisp\")
(satlink::sat-solver-options \"[books]/centaur/satlink/top.lisp\")
(satlink \"[books]/centaur/satlink/top.lisp\")
(xdoc::save \"[books]/xdoc/topics.lisp\")
(set-max-mem \"[books]/centaur/misc/memory-mgmt-logic.lisp\")
(spacewalk \"[books]/centaur/misc/spacewalk.lisp\")
(std \"[books]/std/top.lisp\")
(std/io \"[books]/std/io/top.lisp\")
(std/strings \"[books]/std/strings/top.lisp\")
(std/util \"[books]/std/util/top.lisp\")
(std::strict-list-recognizers \"[books]/std/util/deflist-base.lisp\")
(subseq-list \"[books]/std/lists/subseq.lisp\")
(unsound-read \"[books]/std/io/unsound-read.lisp\")
(untranslate-patterns \"[books]/misc/untranslate-patterns.lisp\")
(build::using-extended-acl2-images \"[books]/build/doc.lisp\")
(with-raw-mode \"[books]/hacking/hacking-xdoc.lisp\")
(with-redef-allowed \"[books]/hacking/hacking-xdoc.lisp\")
(with-timeout \"[books]/acl2s/cgen/with-timeout.lisp\")
(working-with-packages \"[books]/doc/practices.lisp\")
(xdoc \"[books]/xdoc/topics.lisp\"))")
(BRR
(BREAK-REWRITE)
"To enable or disable the breaking of rewrite rules
Example:
:brr t ; enable
:brr nil ; disable
General Form:
(brr flg)
where flg evaluates to t or nil. This function modifies [state] so
that the attempted application of certain rewrite rules are
``broken.'' ``Brr'' stands for ``break-rewrite'' and can be thought
of as a mode with two settings. The normal mode is ``disabled.''
For a more thorough introduction to the break rewrite system see
[break-rewrite].
When brr mode is ``enabled'' the ACL2 rewriter monitors the attempts
to apply certain rules and advises the user of those attempts by
entering an interactive wormhole break. From within this break the
user can watch selected application attempts. The user can also
interact with the system during brr breaks via [brr-commands].
The rules monitored are selected by using the [monitor] and
[unmonitor] commands. It is possible to break a rune
``conditionally'' in the sense that an interactive break will occur
only if a specified predicate is true of the environment at the
time of the attempted application. See [monitor] and see
[unmonitor].
Even if a non-empty set of rules has been selected, no breaks will
occur unless brr mode is enabled. Thus, the first time in a session
that you wish to monitor a rewrite rule, use :brr t to enable brr
mode. Thereafter you may select runes to be monitored with
[monitor] and [unmonitor] with the effect that whenever monitored
rules are tried (and their break conditions are met) an interactive
break will occur. Be advised that when brr mode is enabled the
rewriter is somewhat slower than normal. Furthermore, that
sluggishness persists even if no runes are monitored. You may
regain normal performance --- regardless of what runes are
monitored --- by disabling brr mode with :brr nil.
Why isn't brr mode disabled automatically when no runes are
monitored? More generally, why does ACL2 have brr mode at all? Why
not just test whether there are monitored runes? If you care about
the answers, see [why-brr].
BRR Mode and Console Interrupts: If the system is operating in brr
mode and you break into raw Lisp (as by causing a console interrupt
or happening upon a signalled Lisp error; see [breaks]), you can
return to the ACL2 top-level, outside any brr environment, by
executing ([abort!]). Otherwise, the normal way to quit from such a
break (for example :q in GCL, :reset in Allegro CL, and q in CMU
CL) will return to the innermost ACL2 read-eval-print loop, which
may or may not be the top-level of your ACL2 session! In
particular, if the break happens to occur while ACL2 is within the
brr environment (in which it is preparing to read [brr-commands]),
the abort will merely return to that brr environment. Upon exiting
that environment, normal theorem proving is continued (and the brr
environment may be entered again in response to subsequent
monitored rule applications). Before returning to the brr
environment, ACL2 ``cleans up'' from the interrupted brr
processing. However, it is not possible (given the current
implementation) to clean up perfectly. This may have two
side-effects. First, the system may occasionally print the
self-explanatory ``Cryptic BRR Message 1'' (or 2), informing you
that the system has attempted to recover from an aborted brr
environment. Second, it is possible that subsequent brr behavior in
that proof will be erroneous because the cleanup was done
incorrectly. The moral is that you should not trust what you learn
from brr if you have interrupted and aborted brr processing during
the proof. These issues do not affect the behavior or soundness of
the theorem prover.")
(BRR-COMMANDS
(BREAK-REWRITE)
"[Break-Rewrite] Commands
:a! abort to ACL2 top-level
:p! pop one level (exits a top-level break-rewrite loop)
:target term being rewritten
:unify-subst substitution making :lhs equal :target
:hyps hypotheses of the rule
:hyp i ith hypothesis of the rule
:lhs left-hand side of rule's conclusion
:rhs right-hand side of rule's conclusion
:type-alist type assumptions governing :target
:initial-ttree ttree before :eval (see [ttree])
:ancestors negations of backchaining hypotheses being pursued
:wonp indicates whether application succeeded (after :eval)
:rewritten-rhs rewritten :rhs (after :eval) of a rewrite rule
:poly-list list of polynomials (after :eval) of a linear rule,
where the leading term of each is enclosed in an extra set
of parentheses
:final-ttree ttree after :eval (see [ttree])
:failure-reason reason rule failed (after :eval)
:path rewriter's path from top clause to :target
:frame i ith frame in :path
:top top-most frame in :path
:btm bottom-most frame in :path
:ok exit break
:go exit break, printing result
:eval try rule and re-enter break afterwards
:ok! :ok but no recursive breaks
:go! :go but no recursive breaks
:eval! :eval but no recursive breaks
:ok$ runes :ok with runes monitored during recursion
:go$ runes :go with runes monitored during recursion
:eval$ runes :eval with runes monitored during recursion
:help this message
:standard-help :help message from ACL2 top-level
[Break-rewrite] is just a call of the standard ACL2 read-eval-print
loop, [ld], on a ``[wormhole]'' [state]. Thus, you may execute most
commands you might normally execute at the top-level of ACL2.
However, all [state] changes you cause from within [break-rewrite]
are lost when you exit or :eval the rule. You cannot modify
[stobj]s from within the break. See [break-rewrite] for more
details and see [ld] for general information about the standard
ACL2 read-eval-print loop. Also see [brr@] for a utility that can
return a value for many of the keywords above, instead of merely
printing to the screen.
Note that if you are breaking on a [monitor]ed [linear] rule, several
of the commands listed above do not apply: :lhs, :rhs,
:initial-ttree, and :final-ttree. Moreover, :rewritten-rhs also
does not apply, but instead, :poly-list shows the result of
applying the linear lemma as a list of polynomials, implicitly
conjoined. The leading term of each polynomial is enclosed in an
extra set of parentheses.
Subtopics
[With-brr-ens]
Inside [break-rewrite], evaluate with respect to the theory
currently installed in the prover")
(BRR@
(BREAK-REWRITE)
"To access context sensitive information within [break-rewrite]
Example:
(brr@ :target) ; the term being rewritten
(brr@ :unify-subst) ; the unifying substitution
General Form:
(brr@ :symbol)
where :symbol is one of the keywords displayed below. This utility
may be most useful for system hackers; see [brr-commands] for
queries that are more at a user level. In particular, keywords
marked below with * probably require an implementor's knowledge of
the system to use effectively. They are supported but not well
documented. More is said on this topic following the table.
:symbol (brr@ :symbol)
------- ---------------------
:target the term to be rewritten. This term is an
instantiation of the left-hand side of the
conclusion of the rewrite-rule being broken.
This term is in translated form! Thus, if
you are expecting (equal x nil) -- and your
expectation is almost right -- you will see
(equal x 'nil); similarly, instead of (cadr a)
you will see (car (cdr a)). In translated
forms, all constants are quoted (even nil, t,
strings and numbers) and all macros are
expanded.
:unify-subst the substitution that, when applied to :target,
produces the left-hand side of the rule being
broken. This substitution is an alist pairing
variable symbols to translated (!) terms.
:wonp t or nil indicating whether the rune was
successfully applied. (brr@ :wonp) returns
nil if evaluated before :EVALing the rule.
:rewritten-rhs the result of successfully applying the rewrite
rule or else nil if (brr@ :wonp) is nil. The
result of successfully applying the rule is
always a translated (!) term and is never nil.
:poly-list the result of successfully applying the linear
rule or else nil if (brr@ :wonp) is nil. This
result represents the list of polynomials
produced by the rule application. The leading
term of each polynomial is enclosed in an extra
set of parentheses.
:failure-reason some non-nil lisp object indicating why the rule
was not applied or else nil. Before the rule is
:EVALed, (brr@ :failure-reason) is nil. After
:EVALing the rule, (brr@ :failure-reason) is nil
if (brr@ :wonp) is t. Rather than document the
various non-nil objects returned as the failure
reason, we encourage you simply to evaluate
(brr@ :failure-reason) in the contexts of interest.
Alternatively, study the ACL2 function tilde-@-
failure-reason-phrase.
:lemma * the rewrite rule being broken. For example,
(access rewrite-rule (brr@ :lemma) :lhs) will
return the left-hand side of the conclusion
of the rule.
:type-alist * a display of the type-alist governing :target.
Elements on the displayed list are of the form
(term type), where term is a term and type
describes information about term assumed to hold in
the current context. (See also the documentation for
type-alist.) The type-alist may be used to determine
the current assumptions, e.g., whether A is a CONSP.
:ancestors * a stack of frames indicating the backchain history
of the current context. The theorem prover is in
the process of trying to establish each hypothesis
in this stack. Thus, the negation of each hypothesis
can be assumed false. Each frame also records the
rules on behalf of which this backchaining is being
done and the weight (function symbol count) of the
hypothesis. All three items are involved in the
heuristic for preventing infinite backchaining.
Exception: Some frames are ``binding hypotheses''
(equal var term) or (equiv var (double-rewrite term))
that bind variable var to the result of rewriting
term. The ACL2 source code has a definition
(defrec ancestor ...) that may provide some relevant
insight.
:initial-ttree * the initial and (after :EVAL) final tag trees,
:final-ttree respectively. (Tag trees are low-level data structures
that store lemmas used and other information, as
documented in topic TTREE.)
:gstack * the current goal stack. The gstack is maintained
by rewrite and is the data structure printed as the
current ``path.'' Thus, any information derivable
from the :path brr command is derivable from gstack.
For example, from gstack one might determine that
the current term is the second hypothesis of a
certain rewrite rule.
In general brr@-expressions are used in break conditions, the
expressions that determine whether interactive breaks occur when
[monitor]ed [rune]s are applied. See [monitor]. For example, you
might want to break only those attempts in which one particular
term is being rewritten or only those attempts in which the binding
for the variable a is known to be a [consp]. Such conditions can be
expressed using ACL2 system functions and the information provided
by brr@. Unfortunately, digging some of this information out of the
internal data structures may be awkward or may, at least, require
intimate knowledge of the system functions. But since conditional
expressions may employ arbitrary functions and macros, we
anticipate that a set of convenient primitives will gradually
evolve within the ACL2 community. It is to encourage this evolution
that brr@ provides access to the *'d data.")
(BUILDING-ACL2
(ABOUT-ACL2)
"How to build an ACL2 executable
To build an ACL2 executable, submit the following command while
standing in the main ACL2 directory, where <my-lisp> invokes your
Lisp executable (default: ccl).
make LISP=<my-lisp>
You should find \"Initialization SUCCEEDED.\" near the end the of the
log. Note: There may be ACL2 warnings, for example: \"ACL2 Warning
[Skip-proofs] in....\". These may be safely ignored.
Note that you will want to certify [books] in order to take full
advantage of ACL2. See [books-certification].")
(BUILT-IN-CLAUSE
(RULE-CLASSES)
"To build a clause into the simplifier
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Example:
(defthm acl2-count-abl
(and (implies (and (true-listp x)
(not (equal x nil)))
(< (acl2-count (abl x))
(acl2-count x)))
(implies (and (true-listp x)
(not (equal nil x)))
(< (acl2-count (abl x))
(acl2-count x))))
:rule-classes :built-in-clause)
A :built-in-clause rule can be built from any formula other than
propositional tautologies. Roughly speaking, the system uses the
list of built-in clauses as the first method of proof when
attacking a new goal. Any goal that is subsumed by a built in
clause is proved ``silently.''
ACL2 maintains a set of ``built-in'' clauses that are used to
short-circuit certain theorem proving tasks. We discuss this at
length below. When a theorem is given the rule class
:built-in-clause ACL2 flattens the [implies] and [and] structure of
the :[corollary] formula so as to obtain a set of formulas whose
conjunction is equivalent to the given corollary. It then converts
each of these to clausal form and adds each clause to the set of
built-in clauses.
The example above (regardless of the definition of abl) will build in
two clauses,
{(not (true-listp x))
(equal x nil)
(< (acl2-count (abl x)) (acl2-count x))}
and
{(not (true-listp x))
(equal nil x)
(< (acl2-count (abl x)) (acl2-count x))}.
We now give more background.
Recall that a clause is a set of terms, implicitly representing the
disjunction of the terms. Clause c1 is ``subsumed'' by clause c2 if
some instance of c2 is a subset c1.
For example, let c1 be
{(not (consp l))
(equal a (car l))
(< (acl2-count (cdr l)) (acl2-count l))}.
Then c1 is subsumed by c2, shown below,
{(not (consp x))
; second term omitted here
(< (acl2-count (cdr x)) (acl2-count x))}
because we can instantiate x in c2 with l to obtain a subset of c1.
Observe that c1 is the clausal form of
(implies (and (consp l)
(not (equal a (car l))))
(< (acl2-count (cdr l)) (acl2-count l))),
c2 is the clausal form of
(implies (consp l)
(< (acl2-count (cdr l)) (acl2-count l)))
and the subsumption property just means that c1 follows trivially
from c2 by instantiation.
The set of built-in clauses is just a set of known theorems in
clausal form. Any formula that is subsumed by a built-in clause is
thus a theorem. If the set of built-in theorems is reasonably
small, this little theorem prover is fast. ACL2 uses the ``built-in
clause check'' in four places: (1) at the top of the iteration in
the prover -- thus if a built-in clause is generated as a subgoal
it will be recognized when that goal is considered, (2) within the
simplifier so that no built-in clause is ever generated by
simplification, (3) as a filter on the clauses generated to prove
the termination of recursively [defun]'d functions and (4) as a
filter on the clauses generated to verify the guards of a function.
The latter two uses are the ones that most often motivate an
extension to the set of built-in clauses. Frequently a given
formalization problem requires the definition of many functions
which require virtually identical termination and/or guard proofs.
These proofs can be short-circuited by extending the set of
built-in clauses to contain the most general forms of the clauses
generated by the definitional schemes in use.
The attentive user might have noticed that there are some recursive
schemes, e.g., recursion by [cdr] after testing [consp], that ACL2
just seems to ``know'' are ok, while for others it generates
measure clauses to prove. Actually, it always generates measure
clauses but then filters out any that pass the built-in clause
check. When ACL2 is initialized, the clause justifying [cdr]
recursion after a [consp] test is added to the set of built-in
clauses. (That clause is c2 above.)
Note that only a subsumption check is made; no rewriting or
simplification is done. Thus, if we want the system to ``know''
that [cdr] recursion is ok after a negative [atom] test (which, by
the definition of [atom], is the same as a [consp] test), we have
to build in a second clause. The subsumption algorithm does not
``know'' about commutative functions. Thus, for predictability, we
have built in commuted versions of each clause involving
commutative functions. For example, we build in both
{(not (integerp x))
(< 0 x)
(= x 0)
(< (acl2-count (+ -1 x)) (acl2-count x))}
and the commuted version
{(not (integerp x))
(< 0 x)
(= 0 x)
(< (acl2-count (+ -1 x)) (acl2-count x))}
so that the user need not worry whether to write (= x 0) or (= 0 x)
in definitions.
:built-in-clause rules added by the user can be enabled and disabled.")
(BUTLAST
(LISTS ACL2-BUILT-INS)
"All but a final segment of a list
(Butlast l n) is the list obtained by removing the last n elements
from the true list l. The following is a theorem (though it takes
some effort, including lemmas, to get ACL2 to prove it).
(implies (and (integerp n)
(<= 0 n)
(true-listp l))
(equal (length (butlast l n))
(if (< n (length l))
(- (length l) n)
0)))
For related functions, see [take] and see [nthcdr].
The [guard] for (butlast l n) requires that n is a nonnegative
integer and lst is a true list.
Butlast is a Common Lisp function. See any Common Lisp documentation
for more information. Note: In Common Lisp the second argument of
butlast is optional, but in ACL2 it is required.
Function: <butlast>
(defun butlast (lst n)
(declare (xargs :guard (and (true-listp lst)
(integerp n)
(<= 0 n))))
(let ((lng (len lst)) (n (nfix n)))
(if (<= lng n)
nil (take (- lng n) lst))))")
(BY (POINTERS)
"See [hints] for keyword :by.")
(CAAAAR
(CONSES ACL2-BUILT-INS)
"[car] of the [caaar]
See any Common Lisp documentation for details.")
(CAAADR
(CONSES ACL2-BUILT-INS)
"[car] of the [caadr]
See any Common Lisp documentation for details.")
(CAAAR
(CONSES ACL2-BUILT-INS)
"[car] of the [caar]
See any Common Lisp documentation for details.")
(CAADAR
(CONSES ACL2-BUILT-INS)
"[car] of the [cadar]
See any Common Lisp documentation for details.")
(CAADDR
(CONSES ACL2-BUILT-INS)
"[car] of the [caddr]
See any Common Lisp documentation for details.")
(CAADR
(CONSES ACL2-BUILT-INS)
"[car] of the [cadr]
See any Common Lisp documentation for details.")
(CAAR
(CONSES ACL2-BUILT-INS)
"[car] of the [car]
See any Common Lisp documentation for details.")
(CADAAR
(CONSES ACL2-BUILT-INS)
"[car] of the [cdaar]
See any Common Lisp documentation for details.")
(CADADR
(CONSES ACL2-BUILT-INS)
"[car] of the [cdadr]
See any Common Lisp documentation for details.")
(CADAR
(CONSES ACL2-BUILT-INS)
"[car] of the [cdar]
See any Common Lisp documentation for details.")
(CADDAR
(CONSES ACL2-BUILT-INS)
"[car] of the [cddar]
See any Common Lisp documentation for details.")
(CADDDR
(CONSES ACL2-BUILT-INS)
"[car] of the [cdddr]
See any Common Lisp documentation for details.")
(CADDR
(CONSES ACL2-BUILT-INS)
"[car] of the [cddr]
See any Common Lisp documentation for details.")
(CADR
(CONSES ACL2-BUILT-INS)
"[car] of the [cdr]
See any Common Lisp documentation for details.")
(CALLING-LD-IN-BAD-CONTEXTS
(LD)
"Errors caused by calling [ld] in inappropriate contexts
The macro [ld] was designed to be called directly in the top-level
ACL2 loop, although there may be a few occasions for calling it
from functions. ACL2 cannot cope with invocations of [ld] during
the process of loading a compiled file for a book, so this is an
error.
To see how that can happen, consider the following book, where file
const.lsp contains the single form (defconst *foo* '(a b)).
(in-package \"ACL2\")
(defttag t)
(progn! (ld \"const.lsp\"))
An attempt to certify this book will cause an error, but that
particular error can be avoided, as discussed below. If the book is
certified, however, with production of a corresponding compiled
file (which is the default behavior for [certify-book]), then any
subsequent call of [include-book] that loads this compiled file
will cause an error. Again, this error is necessary because of how
ACL2 is designed; specifically, this [ld] call would interfere with
tracking of constant definitions when loading the compiled file for
the book.
Because including such a book (with a compiled file) causes an error,
then as a courtesy to the user, ACL2 arranges that the
certification will fail (thus avoiding a surprise later when trying
to include the book). The error in that case will look as follows.
ACL2 Error in LD: It is illegal to call LD in this context. See DOC
calling-ld-in-bad-contexts.
If you really think it is OK to avoid this error, you can get around
it by setting [state] global variable ld-okp to t: (assign ld-okp
t). You can then certify the book in the example above, but you
will still not be able to include it with a compiled file.")
(CANONICAL-PATHNAME
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"The true absolute filename, with soft links resolved
For the name fname of a file, the form (Canonical-pathname fname nil
state) evaluates to a Unix-style absolute filename representing the
same file as fname, but generally without any use of soft links in
the name. (Below, we explain the qualifier ``generally''.) If
however the file indicated by fname does not exist,
(canonical-pathname fname nil state) is nil. Thus,
canonical-pathname can be used as one would use the raw Lisp
function probe-file.
The specification of (Canonical-pathname fname dir-p state) when
dir-p is not nil is simlar, except that if the specified file
exists but is not a directory, then the result is nil.
The function canonical-pathname has a guard of t, though the second
argument must be the ACL2 [state]. This function is introduced with
the following properties.
(defthm canonical-pathname-is-idempotent
(equal (canonical-pathname (canonical-pathname x dir-p state) dir-p state)
(canonical-pathname x dir-p state)))
(defthm canonical-pathname-type
(or (equal (canonical-pathname x dir-p state) nil)
(stringp (canonical-pathname x dir-p state)))
:rule-classes :type-prescription)
We use the qualifier ``generally'', above, because there is no
guarantee that the filename will be canonical without soft links,
though we expect this to be true in practice. ACL2 attempts to
compute the desired result and then checks that the input and
result have the same Common Lisp ``truename''. This check is
expected to succeed, but if it fails then the input string is
returned unchanged, and to be conservative, the value returned is
nil in this case if dir-p is true.")
(CAR
(CONSES ACL2-BUILT-INS)
"Returns the first element of a non-empty list, else nil
Completion Axiom (completion-of-car):
(equal (car x)
(cond
((consp x)
(car x))
(t nil)))
[Guard]:
(or (consp x) (equal x nil))
Notice that in the ACL2 logic, car returns nil for every [atom].")
(CASE
(BASICS ACL2-BUILT-INS)
"Conditional based on if-then-else using [eql]
Example Form:
(case typ
((:character foo)
(open file-name :direction :output))
(bar (open-for-bar file-name))
(otherwise
(my-error \"Illegal.\")))
is the same as
(cond ((member typ '(:character foo))
(open file-name :direction :output))
((eql typ 'bar)
(open-for-bar file-name))
(t (my-error \"Illegal.\")))
which in turn is the same as
(if (member typ '(:character foo))
(open file-name :direction :output)
(if (eql typ 'bar)
(open-for-bar file-name)
(my-error \"Illegal.\")))
Notice the quotations that appear in the example above: '(:character
foo) and 'bar. Indeed, a case expression expands to a [cond]
expression in which each tested form is quoted, and [eql] is used
as the test.
General Forms:
(case expr
(x1 val-1)
...
(xk val-k)
(otherwise val-k+1))
(case expr
(x1 val-1)
...
(xk val-k)
(t val-k+1))
(case expr
(x1 val-1)
...
(xk val-k))
where each xi is either [eqlablep] or a true list of [eqlablep]
objects. The final otherwise or t case is optional.
Case is defined in Common Lisp. See any Common Lisp documentation for
more information.")
(CASE-MATCH
(BASICS ACL2-BUILT-INS)
"Pattern matching or destructuring
General Form:
(case-match x
(pat1 dcl1 body1)
...
(patk dclk bodyk))
where x is a variable symbol, the pati are structural patterns as
described below, the dcli are optional [declare] forms and the
bodyi are terms. Return the value(s) of the bodyi corresponding to
the first pati matching x, or nil if none matches.
Pattern Language:
With the few special exceptions described below, matching requires
that the [cons] structure of x be isomorphic to that of the
pattern, down to the [atom]s in the pattern. Non-symbol [atom]s in
the pattern match only themselves. Symbols in the pattern denote
variables which match anything and which are bound by a successful
match to the corresponding substructure of x. Variables that occur
more than once must match the same ([equal]) structure in every
occurrence.
Exceptions:
& Matches anything and is not bound. Repeated
occurrences of & in a pattern may match different
structures.
nil, t, *sym* These symbols cannot be bound and match only their
global values.
!sym where sym is a symbol that is already bound in the
context of the case-match, matches only the
current binding of sym.
'obj Matches only itself.
Some examples are shown below.
Below we show some sample patterns and examples of things they match
and do not match.
pattern matches non-matches
(x y y) (ABC 3 3) (ABC 3 4) ; 3 is not 4
(fn x . rst) (P (A I) B C) (ABC) ; NIL is not (x . rst)
(J (A I)) ; rst matches nil
('fn (g x) 3) (FN (H 4) 3) (GN (G X) 3) ; 'fn matches only itself
(& t & !x) ((A) T (B) (C)) ; provided x is '(C)
Consider the two binary trees that contain three leaves. They might
be described as (x . (y . z)) and ((x . y) . z), where x, y, and z
are atomic. Suppose we wished to recognize those trees. The
following case-match would do:
(case-match tree
((x . (y . z))
(and (atom x) (atom y) (atom z)))
(((x . y) . z)
(and (atom x) (atom y) (atom z))))
Suppose we wished to recognize such trees where all three tips are
identical. Suppose further we wish to return the tip if the tree is
one of those recognized ones and to return the number 7 otherwise.
(case-match tree
((x . (x . x))
(if (atom x) x 7))
(((x . x) . x)
(if (atom x) x 7))
(& 7))
Note that case-match returns nil if no pati matches. Thus if we must
return 7 in that case, we have to add as the final pattern the &,
which always matches anything.")
(CASE-SPLIT
(REWRITE LINEAR TYPE-PRESCRIPTION
DEFINITION META FORWARD-CHAINING)
"Like force but immediately splits the top-level goal on the
hypothesis
Case-split is an variant of [force], which has similar special
treatment in hypotheses of rules for the same [rule-classes] as for
force (see [force]). This treatment takes place for rule classes
:[rewrite], :[linear], :[type-prescription], :[definition], :[meta]
(actually in that case, the result of evaluating the hypothesis
metafunction call), and :[forward-chaining].
When a hypothesis of a conditional rule (of one of the classes listed
above) has the form (case-split hyp) it is logically equivalent to
hyp. However it affects the application of the rule generated as
follows: if ACL2 attempts to apply the rule but cannot establish
that the required instance of hyp holds in the current context, it
considers the hypothesis true anyhow, but (assuming all hypotheses
are seen to be true and the rule is applied) creates a subgoal in
which that instance of hyp is assumed false. (There are exceptions,
noted below.)
For example, given the rule
(defthm p1->p2
(implies (case-split (p1 x))
(p2 x)))
then an attempt to prove
(implies (p3 x) (p2 (car x)))
can give rise to a single subgoal:
(IMPLIES (AND (NOT (P1 (CAR X))) (P3 X))
(P2 (CAR X))).
Unlike [force], case-split does not delay the ``false case'' to a
forcing round but tackles it more or less immediately.
The special ``split'' treatment of case-split can be disabled by
disabling forcing: see [force] for a discussion of disabling
forcing, and also see [disable-forcing]. Finally, we should mention
that the rewriter is never willing to split when there is an [if]
term present in the goal being simplified. Since [and] terms and
[or] terms are merely abbreviations for [if] terms, they also
prevent splitting. Note that [if] terms are ultimately eliminated
using the ordinary flow of the proof (but see
[set-case-split-limitations]), so case-split will ultimately
function as intended.
When in the proof checker, case-split behaves like force.
Function: <case-split>
(defun case-split (x)
(declare (xargs :guard t))
x)")
(CASE-SPLIT-LIMITATIONS
(MISCELLANEOUS)
"A list of two ``numbers'' limiting the number of cases produced at
once
Examples:
ACL2 !>(case-split-limitations (w state))
(500 100)
With the setting above, clausify will not try subsumption/replacement
if more than 500 clauses are involved. Furthermore, the simplifier,
as it sweeps over a clause, will inhibit further case splits when
it has accumulated 100 subgoals. This inhibition is implemented by
continuing to rewrite subsequent literals but not splitting out
their cases. This can produce literals containing IFs.
See [set-case-split-limitations] for a more general discussion.")
(CASES (POINTERS)
"See [hints] for keyword :cases.")
(CBD
(BOOKS-REFERENCE PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Connected book directory string
Example:
ACL2 !>:cbd
\"/usr/home/smith/\"
The connected book directory is a nonempty string that specifies a
directory as an absolute pathname. (See [pathname] for a discussion
of file naming conventions.) When [include-book] is given a
relative book name it elaborates it into a full book name,
essentially by appending the connected book directory string to the
left and \".lisp\" to the right. (For details, see [book-name] and
also see [full-book-name].) Furthermore, [include-book] temporarily
sets the connected book directory to the directory string of the
resulting full book name so that references to inferior [books] in
the same directory may omit the directory. See [set-cbd] for how to
set the connected book directory string.
General Form:
(cbd)
This is a macro that expands into a term involving the single free
variable [state]. It returns the connected book directory string.
The connected book directory (henceforth called the ``cbd'') is used
by [include-book] to elaborate the supplied book name into a full
book name (see [full-book-name]). For example, if the cbd is
\"/usr/home/smith/\" then the elaboration of the [book-name]
\"project/task-1/arith\" (to the \".lisp\" extension) is
\"/usr/home/smith/project/task-1/arith.lisp\". That [full-book-name]
is what [include-book] opens to read the source text for the book.
The cbd may be changed using [set-cbd] (see [set-cbd]). Furthermore,
during the processing of the [events] in a book, [include-book]
sets the cbd to be the directory string of the [full-book-name] of
the book. Thus, if the cbd is \"/usr/home/smith/\" then during the
processing of [events] by
(include-book \"project/task-1/arith\")
the cbd will be set to \"/usr/home/smith/project/task-1/\". Note that
if \"arith\" recursively includes a sub-book, say \"naturals\", that
resides on the same directory, the [include-book] event for it may
omit the specification of that directory. For example, \"arith\"
might contain the event
(include-book \"naturals\").
In general, suppose we have a superior book and several inferior
[books] which are included by [events] in the superior book. Any
inferior book residing on the same directory as the superior book
may be referenced in the superior without specification of the
directory.
We call this a ``relative'' as opposed to ``absolute'' naming. The
use of relative naming is preferred because it permits [books] (and
their accompanying inferiors) to be moved between directories while
maintaining their [certificate]s and utility. Certified [books]
that reference inferiors by absolute file names are unusable (and
rendered uncertified) if the inferiors are moved to new
directories.
Technical Note and a Challenge to Users:
After elaborating the book name to a full book name, [include-book]
opens a channel to the file to process the [events] in it. In some
host Common Lisps, the actual file opened depends upon a notion of
``connected directory'' similar to our connected book directory.
Our intention in always elaborating book names into absolute
filename strings (see [pathname] for terminology) is to circumvent
the sensitivity to the connected directory. But we may have
insufficient control over this since the ultimate file naming
conventions are determined by the host operating system rather than
Common Lisp (though, we do check that the operating system
``appears'' to be one that we ``know'' about). Here is a question,
which we'll pose assuming that we have an operating system that
calls itself ``Unix.'' Suppose we have a file name, filename, that
begins with a slash, e.g., \"/usr/home/smith/...\". Consider two
successive invocations of CLTL's
(open filename :direction :input)
separated only by a change to the operating system's notion of
connected directory. Must these two invocations produce streams to
the same file? A candidate string might be something like
\"/usr/home/smith/*/usr/local/src/foo.lisp\" which includes some
operating system-specific special character to mean ``here insert
the connected directory'' or, more generally, ``here make the name
dependent on some non-ACL2 aspect of the host's state.'' If such
``tricky'' name strings beginning with a slash exist, then we have
failed to isolate ACL2 adequately from the operating system's file
naming conventions. Once upon a time, ACL2 did not insist that the
cbd begin with a slash and that allowed the string \"foo.lisp\" to be
tricky because if one were connected to \"/usr/home/smith/\" then
with the empty cbd \"foo.lisp\" is a full book name that names the
same file as \"/usr/home/smith/foo.lisp\". If the actual file one
reads is determined by the operating system's state then it is
possible for ACL2 to have two distinct ``full book names'' for the
same file, the ``real'' name and the ``tricky'' name. This can
cause ACL2 to include the same book twice, not recognizing the
second one as redundant.")
(CCL-UPDATES
(HONS-AND-MEMOIZATION)
"Updating Clozure Common Lisp (CCL)
Those who use ACL2 built on CCL, especially those who make
compute-intensive use of ACL2's [hons-enabled] features, are
advised to to stay plugged into the ``trunk'' or ``bleeding edge''
of CCL development. This is very easy to do by typing a few
commands to a shell, for example standing above the target
directory as follows, provided one has svn working.
For linux:
rm -rf ccl
svn co http://svn.clozure.com/publicsvn/openmcl/trunk/linuxx8664/ccl
For an x86 Macintosh running the Darwin OS:
svn co http://svn.clozure.com/publicsvn/openmcl/trunk/darwinx8664/ccl
To keep up to date, you may find it sufficient to do:
cd ccl
svn update
Whether obtaining a fresh CCL or just updating, finally issue these
commands.
./lx86cl64
(rebuild-ccl :full t)
(quit)
./lx86cl64
(rebuild-ccl :full t)
(quit)")
(CDAAAR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [caaar]
See any Common Lisp documentation for details.")
(CDAADR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [caadr]
See any Common Lisp documentation for details.")
(CDAAR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [caar]
See any Common Lisp documentation for details.")
(CDADAR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cadar]
See any Common Lisp documentation for details.")
(CDADDR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [caddr]
See any Common Lisp documentation for details.")
(CDADR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cadr]
See any Common Lisp documentation for details.")
(CDAR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [car]
See any Common Lisp documentation for details.")
(CDDAAR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cdaar]
See any Common Lisp documentation for details.")
(CDDADR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cdadr]
See any Common Lisp documentation for details.")
(CDDAR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cdar]
See any Common Lisp documentation for details.")
(CDDDAR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cddar]
See any Common Lisp documentation for details.")
(CDDDDR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cdddr]
See any Common Lisp documentation for details.")
(CDDDR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cddr]
See any Common Lisp documentation for details.")
(CDDR
(CONSES ACL2-BUILT-INS)
"[cdr] of the [cdr]
See any Common Lisp documentation for details.")
(CDR
(CONSES ACL2-BUILT-INS)
"Returns the second element of a [cons] pair, else nil
Completion Axiom (completion-of-cdr):
(equal (cdr x)
(cond
((consp x)
(cdr x))
(t nil)))
[Guard]:
(or (consp x) (equal x nil))
Notice that in the ACL2 logic, cdr returns nil for every [atom].")
(CEILING
(NUMBERS ACL2-BUILT-INS)
"Division returning an integer by truncating toward positive infinity
Example Forms:
ACL2 !>(ceiling 14 3)
5
ACL2 !>(ceiling -14 3)
-4
ACL2 !>(ceiling 14 -3)
-4
ACL2 !>(ceiling -14 -3)
5
ACL2 !>(ceiling -15 -3)
5
(Ceiling i j) is the result of taking the quotient of i and j and
returning the smallest integer that is at least as great as that
quotient. For example, the quotient of -14 by 3 is -4 2/3, and the
smallest integer at least that great is -4.
The [guard] for (ceiling i j) requires that i and j are rational
([real], in ACL2(r)) numbers and j is non-zero.
Ceiling is a Common Lisp function. See any Common Lisp documentation
for more information. However, note that unlike Common Lisp, the
ACL2 ceiling function returns only a single value,
Function: <ceiling>
(defun ceiling (i j)
(declare (xargs :guard (and (real/rationalp i)
(real/rationalp j)
(not (eql j 0)))))
(let* ((q (* i (/ j)))
(n (numerator q))
(d (denominator q)))
(cond ((= d 1) n)
((>= n 0)
(+ (nonnegative-integer-quotient n d)
1))
(t (- (nonnegative-integer-quotient (- n)
d))))))")
(CERTIFICATE
(BOOKS-TOUR)
"How a book is known to be admissible and where its [defpkg]s reside
A book, say \"arith\", is said to have a ``certificate'' if there is a
file named \"arith.cert\". Certificates are created by the function
[certify-book] and inspected by [include-book]. Check sums are used
to help ensure that certificates are legitimate and that the
corresponding book has not been modified since certification. But
because the file system is insecure and check sums are not perfect
it is possible for the inclusion of a book to cause inconsistency
even though the book carries an impeccable certificate.
The certificate includes the version number of the certifying ACL2. A
book is considered uncertified if it is included in an ACL2 with a
different [version] number.
The presence of a ``valid'' certificate file for a book attests to
two things: all of the [events] of the book are admissible in a
certain extension of the initial ACL2 logic, and the non-[local]
[events] of the book are independent of the [local] ones (see
[local-incompatibility]). In addition, the certificate contains the
[command]s used to construct the [world] in which certification
occurred. Among those [command]s, of course, are the [defpkg]s
defining the packages used in the book. When a book is included
into a host [world], that [world] is first extended by the
[command]s listed in the certificate for the book. Unless that
causes an error due to name conflicts, the extension ensures that
all the packages used by the book are identically defined in the
host [world].
Security:
Because the host file system is insecure, there is no way ACL2 can
guarantee that the contents of a book remain the same as when its
certificate was written. That is, between the time a book is
certified and the time it is used, it may be modified. Furthermore,
certificates can be counterfeited. Check sums (see [check-sum]) are
used to help detect such problems. But check sums provide imperfect
security: two different files can have the same check sum.
Therefore, from the strictly logical point of view, one must consider
even the inclusion of certified [books] as placing a burden on the
user:
The non-erroneous inclusion of a certified book is consistency
preserving provided (a) the objects read by [include-book] from
the certificate were the objects written there by a
[certify-book] and (b) the forms read by [include-book] from
the book itself are the forms read by the corresponding
[certify-book].
We say that a given execution of [include-book] is ``certified'' if a
certificate file for the book is present and well-formed and the
check sum information contained within it supports the conclusion
that the [events] read by the [include-book] are the ones checked
by [certify-book]. When an uncertified [include-book] occurs,
warnings are printed or errors are caused. But even if no warning
is printed, you must accept burdens (a) and (b) if you use [books].
These burdens are easier to live with if you protect your [books]
so that other users cannot write to them, you abstain from running
concurrent ACL2 jobs, and you abstain from counterfeiting
certificates. But even on a single user uniprocessor, you can shoot
yourself in the foot by using the ACL2 [io] primitives to fabricate
an inconsistent book and the corresponding certificate.
Note that part (a) of the burden described above implies, in
particular, that there are no guarantees when a certificate is
copied. When [books] are renamed (as by copying them), it is
recommended that their certificates be removed and the [books] be
recertified. The expectation is that recertification will go
through without a hitch if relative [pathname]s are used. See
[pathname], which is not on the guided tour.
Certificates essentially contain two parts, a [portcullis] and a
[keep]. There is a third part, an expansion-alist, in order to
record expansions if [make-event] has been used, but the user need
not be concerned with that level of detail.
See [portcullis] to continue the guided tour through [books].
Subtopics
[Check-sum]
Assigning ``often unique'' integers to files and objects")
(CERTIFY-BOOK
(BOOKS-REFERENCE BOOKS-TOUR)
"How to produce a [certificate] for a book
Examples:
(certify-book \"my-arith\") ; certify in a world with 0 commands
(certify-book \"my-arith\" 3) ; ... in a world with 3 commands
(certify-book \"my-arith\" ?) ; ... in a world without checking the
; number of commands
(certify-book \"my-arith\" 0 nil) ; ... without compilation
(certify-book \"my-arith\" 0 t) ; ... with compilation (default)
(certify-book \"my-arith\" 0 t :ttags (foo))
; ... allowing trust tag (ttag) foo
(certify-book \"my-arith\" 0 t :ttags :all)
; ... allowing all trust tags (ttags)
(certify-book \"my-arith\" t) ; ... from world of old certificate
(certify-book \"my-arith\" 0 nil :acl2x t)
; ... writing or reading a .acl2x file
General Form:
(certify-book book-name
k ; [default 0]
compile-flg ; [default t]
:defaxioms-okp t/nil ; [default nil]
:skip-proofs-okp t/nil ; [default nil]
:ttags ttags ; [default nil]
:acl2x t/nil ; [default nil]
:ttagsx ttags ; [default nil]
:pcert pcert ; [default nil]
:write-port t/nil ; [default t unless pcert is non-nil]
)
where book-name is a book name (see [book-name]), k is used to
indicate your approval of the ``certification [world],'' and
compile-flg can control whether the book is to be compiled. The
defaults for compile-flg, skip-proofs-okp, acl2x, write-port, and
pcert can be affected by environment variables. All of these
arguments are described in detail below, except for :pcert. (We
assume below that the value of :pcert is nil (and environment
variable ACL2_PCERT_ARG is unset or the empty string). For a
discussion of this argument, see [provisional-certification].)
Certification occurs in some logical [world], called the
``certification [world].'' That [world] must contain the [defpkg]s
needed to read and execute the forms in the book. The [command]s
necessary to recreate that [world] from the ACL2 initial [world]
are called the ``[portcullis] commands,'' and will be copied into
the [certificate] created for the book. Those [command]s will be
re-executed whenever the book is included, to ensure that the
appropriate packages (and all other names used in the certification
[world]) are correctly defined. Note that Step 1 of certify-book
will fail if a package mentioned in the book is not defined before
attempting the certification, i.e., defined by a portcullis command
in the certification world. For example, suppose that your book
contains the symbol FOO::X, but the package \"FOO\" is not currently
defined. Then an error message will likely complain either about a
missing package \"FOO\", or about a symbol FOO::X that is ``not in
any of the packages known to ACL2.'' A solution is to define the
package \"FOO\", perhaps directly using [defpkg] or by including a
book that defines this package, before attempting the
certification.
The certified book will be more often usable if the certification
[world] is kept to a minimal extension of the ACL2 initial [world]
(for example, to prevent name clashes with functions defined in
other books). Thus, before you call certify-book for the first time
on a book, you may wish to get into the initial ACL2 [world] (e.g.,
with :ubt 1 or just starting a new version of ACL2), [defpkg] the
desired packages, and then invoke certify-book.
The k argument to certify-book must be either a nonnegative integer
or else one of the symbols t or ? in any package. If k is an
integer, then it must be the number of [command]s that have been
executed after the initial ACL2 [world] to create the [world] in
which certify-book was called. One way to obtain this number is by
doing :pbt :start to see all the [command]s back to the first one.
If k is t (or any symbol whose [symbol-name] is \"T\"), it means that
certify-book should use the same [world] used in the last
certification of this book. K may have such a value only if you
call certify-book in the initial ACL2 [world] and there is a
[certificate] on file for the book being certified. (Of course, the
[certificate] is probably invalid.) In this case, certify-book
reads the old [certificate] to obtain the [portcullis] [command]s
and executes them to recreate the certification [world].
Finally, k may be ? (or any symbol whose [symbol-name] is \"?\"), in
which case there is no check made on the certification world. That
is, if k is such a value then no action related to the preceding
two paragraphs is performed, which can be a nice convenience but at
the cost of eliminating a potentially valuable check that the
certification [world] may be as expected.
We next describe the meaning of compile-flg and how it defaults. If
explicit compilation has been suppressed by (set-compiler-enabled
nil state), then compile-flg is coerced to nil; see [compilation].
Otherwise compile-flg may be given the value of t (or :all, which
is equivalent to t except during provisional certification; see
[provisional-certification]), indicating that the book is to be
compiled, or else nil. (Note that compilation initially creates a
compiled file with a temporary file name, and then moves that
temporary file to the final compiled file name obtained by adding a
suitable extension to the book name. Thus, a compiled file will
appear atomically in its intended location.) Finally, suppose that
compile-flg is not supplied (or is :default). If environment
variable ACL2_COMPILE_FLG is defined and not the empty string, then
its value should be T, NIL, or ALL after converting to upper case,
in which case compile-flg is considered to have value t, nil, or
:all (respectively). Otherwise compile-flg defaults to t. Note that
the value :all is equivalent to t except for during the Convert
procedure of provisional certification; see
[provisional-certification].
Two keyword arguments, :defaxioms-okp and :skip-proofs-okp, determine
how the system handles the inclusion of [defaxiom] events and
[skip-proofs] events, respectively, in the book. The value t allows
such events, but prints a warning message. The value nil causes an
error if such an event is found. Nil is the default unless keyword
argument :acl2x t is provided and state global 'write-acl2x is a
cons (see [set-write-ACL2x]), in which case the default is t.
The keyword argument :ttags may normally be omitted. A few
constructs, used for example if you are building your own system
based on ACL2, may require it. See [defttag] for an explanation of
this argument.
When book B is certified with value t (the default, unless the value
used for pcert is non-nil) for keyword argument :write-port, a file
B.port is written by certification process. This file contains all
of the [portcullis] [command]s for B, i.e., all user commands
present in the ACL2 logical [world] at the time certify-book is
called. if B.lisp later becomes uncertified, say because [events]
from that file or an included book have been edited, then
(include-book \"B\") will consult B.port to evaluate forms in that
file before evaluating the events in B.lisp. On the other hand,
B.port is ignored when including B if B is certified.
If you use [guard]s, please note certify-book is executed as though
(set-guard-checking nil) has been evaluated; see
[set-guard-checking]. If you want guards checked, consider using ld
instead, or in addition; see [ld].
For a general discussion of books, see [books]. Certify-book is akin
to what we have historically called a ``proveall'': all the forms
in the book are ``proved'' to guarantee their admissibility. More
precisely, certify-book (1) reads the forms in the book, confirming
that the appropriate packages are defined in the certification
[world]; (2) does the full admissibility checks on each form
(proving termination of recursive functions, proving theorems,
etc.), checking as it goes that each form is an embedded event form
(see [embedded-event-form]); (3) may roll back the [world] (how
far? ~-[] see below) and perform an [include-book] to check for
[local] incompatibilities (see [local-incompatibility]); (4) writes
a [certificate] recording not only that the book was certified but
also recording the [command]s necessary to recreate the
certification [world] (so the appropriate packages can be defined
when the book is included in other [world]s) and the check sums of
all the [books] involved (see [certificate]); (5) compiles the book
if so directed (and then loads the object file in that case). The
result of executing a certify-book [command] is the creation of a
single new event, which is actually an [include-book] event. If you
don't want its included [events] in your present [world], simply
execute :[ubt] :here afterwards.
Technical Remark. Step 3 above mentions rolling the logical [world]
back to check for local incompatibilies. For efficiency, this
retraction to an initial segment of the the world is skipped if a
local event is not encountered as described below; otherwise, the
world is rolled back to the point just before the first such event
was admitted. For this purpose, a relevant local event is one at
the top level of the book or under a sequences of [progn] calls in
the book. Here, we include forms generated by [make-event]. But
this category does not include local [events] within an
[encapsulate] event, since those are ignored in the final
processing of the encapsulate event. We also do not consider local
events within an [include-book] event. End of Technical Remark.
A utility is provided to assist in debugging failures of
certify-book; see [redo-flat].)
Certify-book requires that the default [defun-mode] (see
[default-defun-mode]) be :[logic] when certification is attempted.
If the mode is not :[logic], an error is signalled.
An error will occur if certify-book has to deal with any uncertified
book other than the one on which it was called. For example, if the
book being certified includes another book, that sub-book must
already have been certified; that is, that sub-book must have a
valid [certificate] file.
If you have a certified book that has remained unchanged for some
time you might well not remember the appropriate [defpkg]s for it,
though they are stored in the [certificate] file and (by default)
also in the .port file. If you begin to change the book, don't
throw away its [certificate] file just because it has become
invalid! It is an important historical document until the book is
re-certified. More important, don't throw away the .port file, as
it will provide the [portcullis] commands when including the book
as an uncertified book; see [include-book].
When certify-book is directed to produce a compiled file, it calls
the Common Lisp function compile-file on the original source file.
This creates a compiled file with an extension known to ACL2, e.g.,
if the book is named \"my-book\" then the source file is
\"my-book.lisp\" and the compiled file under GCL will be \"my-book.o\"
while under SBCL it will be \"my-book.fasl\". The compiled file is
then loaded. When [include-book] is used later on \"my-book\" it will
automatically load the compiled file, provided the compiled file
has a later write date than the source file. The only effect of
such [compilation] and loading is that the functions defined in the
book execute faster. See [guard] for a discussion of the issues,
and if you want more details about [books] and compilation, see
[book-compiled-file].
When certify-book is directed not to produce a compiled file, it will
delete any existing compiled file for the book, so as not to
mislead [include-book] into loading the now outdated compiled file.
Otherwise, certify-book will create a temporary ``expansion file''
to compile, obtained by appending the string \"@expansion.lsp\" to
the end of the book name. Remark: Users may ignore that file, which
is automatically deleted unless [state] global variable
'save-expansion-file has been set, presumably by a system
developer, to a non-nil value; see [book-compiled-file] for more
information about hit issue, including the role of environment
variable ACL2_SAVE_EXPANSION.
After execution of a certify-book form, the value of
[ACL2-defaults-table] is restored to what it was immediately before
that certify-book form was executed. See [ACL2-defaults-table].
Those who use the relatively advanced features of trust tags (see
[defttag]) and [make-event] may wish to know how to create a
[certificate] file that avoids dependence on trust tags that are
used only during [make-event] expansion. For this, including
documentation of the :acl2x and :ttagsx keyword arguments for
certify-book, see [set-write-ACL2x].
This completes the tour through the [documentation] of [books].
Subtopics
[Certify-book!]
A variant of [certify-book]")
(CERTIFY-BOOK!
(CERTIFY-BOOK)
"A variant of [certify-book]
Examples:
(certify-book! \"my-arith\" 3) ;Certify in a world with 3
; commands, starting in a world
; with at least 3 commands.
(certify-book! \"my-arith\") ;Certify in the initial world.
General Form:
(certify-book! book-name k compile-flg)
where book-name is a book name (see [book-name]), k is a nonnegative
integer used to indicate the ``certification [world],'' and
compile-flg indicates whether you wish to compile the (functions in
the) book.
This [command] is identical to [certify-book], except that the second
argument k may not be t in certify-book! and if k exceeds the
current [command] number, then an appropriate [ubt!] will be
executed first. See [certify-book] and see [ubt!].")
(CERTIFYING-BOOKS (POINTERS)
"See [books-certification].")
(CHANGE
(DEFREC ACL2-BUILT-INS)
"Mutator macro for [defrec] structures.
The change macro is built into ACL2, and allows you to \"modify\"
instances of structures that have been introduced with [defrec]. Of
course, since ACL2 is applicative, the original structure is not
actually changed---instead, a new structure is constructed, copying
some fields from the original structure and installing new values
for other fields.
For instance, suppose we first use [make] to create an employee
structure, e.g.,:
(defconst *jimmy* (make employee :name \"Jimmy\"
:salary 0
:position \"Unpaid Intern\")
Then we can use change to mutate this structure, e.g.,:
(change employee *jimmy* :salary 300000
:position \"Vice President\")
Produces a new employee structure where the name is still \"Jimmy\",
but where the salary and position have been updated to 300000 and
\"Vice President\", respectively.
See [defrec] for more information.")
(CHAR
(CHARACTERS ACL2-BUILT-INS)
"The [nth] element (zero-based) of a string
(Char s n) is the nth element of s, zero-based. If n is greater than
or equal to the length of s, then char returns nil.
(Char s n) has a [guard] that n is a non-negative integer and s is a
[stringp].
Char is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <char>
(defun char (s n)
(declare (xargs :guard (and (stringp s)
(integerp n)
(>= n 0)
(< n (length s)))))
(nth n (coerce s 'list)))")
(CHAR-CODE
(CHARACTERS NUMBERS ACL2-BUILT-INS)
"The numeric code for a given character
This function maps a character to its code, for example: (char-code
#\\A) evaluates to 65. See [code-char] for a sort of inverse
function, which maps a code to the corresponding character.
Completion Axiom (completion-of-char-code):
(equal (char-code x)
(if (characterp x)
(char-code x)
0))
[Guard] for (char-code x):
(characterp x)
This function maps all non-characters to 0.")
(CHAR-DOWNCASE
(CHARACTERS ACL2-BUILT-INS)
"Turn upper-case [characters] into lower-case [characters]
(Char-downcase x) is equal to #\\a when x is #\\A, #\\b when x is #\\B,
..., and #\\z when x is #\\Z, and is x for any other character.
The [guard] for char-downcase requires its argument to be a standard
character (see [standard-char-p]).
Char-downcase is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <char-downcase>
(defun char-downcase (x)
(declare (xargs :guard (and (characterp x)
(standard-char-p x))))
(let ((pair (assoc x
'((#\\A . #\\a)
(#\\B . #\\b)
(#\\C . #\\c)
(#\\D . #\\d)
(#\\E . #\\e)
(#\\F . #\\f)
(#\\G . #\\g)
(#\\H . #\\h)
(#\\I . #\\i)
(#\\J . #\\j)
(#\\K . #\\k)
(#\\L . #\\l)
(#\\M . #\\m)
(#\\N . #\\n)
(#\\O . #\\o)
(#\\P . #\\p)
(#\\Q . #\\q)
(#\\R . #\\r)
(#\\S . #\\s)
(#\\T . #\\t)
(#\\U . #\\u)
(#\\V . #\\v)
(#\\W . #\\w)
(#\\X . #\\x)
(#\\Y . #\\y)
(#\\Z . #\\z)))))
(cond (pair (cdr pair))
((characterp x) x)
(t (code-char 0)))))")
(CHAR-EQUAL
(CHARACTERS ACL2-BUILT-INS)
"Character equality without regard to case
For [characters] x and y, (char-equal x y) is true if and only if x
and y are the same except perhaps for their case.
The [guard] on char-equal requires that its arguments are both
standard [characters] (see [standard-char-p]).
Char-equal is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <char-equal>
(defun char-equal (x y)
(declare (xargs :guard (and (characterp x)
(standard-char-p x)
(characterp y)
(standard-char-p y))))
(eql (char-downcase x)
(char-downcase y)))")
(CHAR-UPCASE
(CHARACTERS ACL2-BUILT-INS)
"Turn lower-case [characters] into upper-case [characters]
(Char-upcase x) is equal to #\\A when x is #\\a, #\\B when x is #\\b,
..., and #\\Z when x is #\\z, and is x for any other character.
The [guard] for char-upcase requires its argument to be a standard
character (see [standard-char-p]).
Char-upcase is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <char-upcase>
(defun char-upcase (x)
(declare (xargs :guard (and (characterp x)
(standard-char-p x))))
(let ((pair (assoc x
'((#\\a . #\\A)
(#\\b . #\\B)
(#\\c . #\\C)
(#\\d . #\\D)
(#\\e . #\\E)
(#\\f . #\\F)
(#\\g . #\\G)
(#\\h . #\\H)
(#\\i . #\\I)
(#\\j . #\\J)
(#\\k . #\\K)
(#\\l . #\\L)
(#\\m . #\\M)
(#\\n . #\\N)
(#\\o . #\\O)
(#\\p . #\\P)
(#\\q . #\\Q)
(#\\r . #\\R)
(#\\s . #\\S)
(#\\t . #\\T)
(#\\u . #\\U)
(#\\v . #\\V)
(#\\w . #\\W)
(#\\x . #\\X)
(#\\y . #\\Y)
(#\\z . #\\Z)))))
(cond (pair (cdr pair))
((characterp x) x)
(t (code-char 0)))))")
(CHAR<
(CHARACTERS ACL2-BUILT-INS)
"Less-than test for [characters]
(char< x y) is true if and only if the character code of x is less
than that of y. See [char-code].
The [guard] for char< specifies that its arguments are [characters].
Char< is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <char<>
(defun char< (x y)
(declare (xargs :guard (and (characterp x) (characterp y))))
(< (char-code x) (char-code y)))")
(CHAR<=
(CHARACTERS ACL2-BUILT-INS)
"Less-than-or-equal test for [characters]
(char<= x y) is true if and only if the character code of x is less
than or equal to that of y. See [char-code].
The [guard] for char<= specifies that its arguments are [characters].
Char<= is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <char<=>
(defun char<= (x y)
(declare (xargs :guard (and (characterp x) (characterp y))))
(<= (char-code x) (char-code y)))")
(CHAR>
(CHARACTERS ACL2-BUILT-INS)
"Greater-than test for [characters]
(char> x y) is true if and only if the character code of x is greater
than that of y. See [char-code].
The [guard] for char> specifies that its arguments are [characters].
Char> is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <char>>
(defun char> (x y)
(declare (xargs :guard (and (characterp x) (characterp y))))
(> (char-code x) (char-code y)))")
(CHAR>=
(CHARACTERS ACL2-BUILT-INS)
"Greater-than-or-equal test for [characters]
(char>= x y) is true if and only if the character code of x is
greater than or equal to that of y. See [char-code].
The [guard] for char>= specifies that its arguments are [characters].
Char>= is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <char>=>
(defun char>= (x y)
(declare (xargs :guard (and (characterp x) (characterp y))))
(>= (char-code x) (char-code y)))")
(CHARACTER-ALISTP
(CHARACTERS ALISTS ACL2-BUILT-INS)
"Recognizer for association lists with characters as keys
(Character-alistp x) is true if and only if x is a list of pairs of
the form (cons key val) where key is a [characterp].
Function: <character-alistp>
(defun character-alistp (x)
(declare (xargs :guard t))
(cond ((atom x) (eq x nil))
(t (and (consp (car x))
(characterp (car (car x)))
(character-alistp (cdr x))))))")
(CHARACTER-ENCODING
(IO)
"How bytes are parsed into characters
When the Common Lisp reader comes across bytes in a file or at the
terminal, they are parsed into characters. The simplest case is
when each byte that is read is a standard character (see
[standard-char-p]). It is actually quite common that each byte that
is read corresponds to a single character. The parsing of bytes
into characters is based on a character encoding, that is, a
mapping that associates one or more bytes with each legal
character.
In order to help guarantee the portability of files (including
[books]), ACL2 installs a common character encoding for reading
files, often known as iso-8859-1 or latin-1. For some host Lisps
this character encoding is also used for reading from the terminal;
but, sadly, this may not hold for all host Lisps, and may not even
be possible for some of them.
The use of the above encoding could in principle cause problems if
one's editor produces files using an encoding other than
iso-8859-1, at least if one uses non-standard characters. In
particular, the default Emacs buffer encoding may be utf-8. If your
file has non-standard characters, then in Emacs you can evaluate
the form
(setq save-buffer-coding-system 'iso-8859-1)
before saving the buffer into a file. This will happen automatically
for users who load distributed file emacs/emacs-acl2.el into their
Emacs sessions.
For an example of character encodings in action, see the community
book books/misc/character-encoding-test.lisp.")
(CHARACTER-LISTP
(CHARACTERS LISTS ACL2-BUILT-INS)
"Recognizer for a true list of characters
The predicate character-listp tests whether its argument is a true
list of [characters].
Function: <character-listp>
(defun character-listp (l)
(declare (xargs :guard t))
(cond ((atom l) (equal l nil))
(t (and (characterp (car l))
(character-listp (cdr l))))))")
(CHARACTERP
(CHARACTERS ACL2-BUILT-INS)
"Recognizer for [characters]
(characterp x) is true if and only if x is a character.")
(CHARACTERS
(PROGRAMMING)
"Characters in ACL2 and operations on them
ACL2 accepts 256 distinct characters, which are the characters
obtained by applying the function [code-char] to each integer from
0 to 255. Among these, Common Lisp designates certain ones as
standard characters, namely those of the form (code-char n) where n
is from 33 to 126, together with #\\Newline and #\\Space. The actual
standard characters may be viewed by evaluating the [defconst]
*standard-chars*.
To be more precise, Common Lisp does not specify the precise
relationship between [code-char] and the standard characters.
However, we check that the underlying Common Lisp implementation
uses a particular relationship that extends the usual ASCII coding
of characters. We also check that Space, Tab, Newline, Page, and
Rubout correspond to characters with respective [char-code]s 32, 9,
10, 12, and 127.
[Code-char] has an inverse, [char-code]. Thus, when [char-code] is
applied to an ACL2 character, c, it returns a number n between 0
and 255 inclusive such that (code-char n) = c.
The preceding paragraph implies that there is only one ACL2 character
with a given character code. CLTL allows for ``attributes'' for
characters, which could allow distinct characters with the same
code, but ACL2 does not allow this.
The Character Reader
ACL2 supports the `#\\' notation for characters provided by Common
Lisp, with some restrictions. First of all, for every character c,
the notation
#\\c
may be used to denote the character object c. That is, the user may
type in this notation and ACL2 will read it as denoting the
character object c. In this case, the character immediately
following c must be one of the following ``terminating
characters'': a Tab, a Newline, a Page character, a space, or one
of the characters:
\" ' ( ) ; ` ,
Other than the notation above, ACL2 accepts alternate notation for
five characters.
#\\Space
#\\Tab
#\\Newline
#\\Page
#\\Rubout
Again, in each of these cases the next character must be from among
the set of ``terminating characters'' described in the
single-character case. Our implementation is consistent with
IS0-8859, even though we don't provide #\\ syntax for entering
characters other than that described above.
Finally, we note that it is our intention that any object printed by
ACL2's top-level-loop may be read back into ACL2. Please notify the
implementors if you find a counterexample to this claim.
Subtopics
[Alpha-char-p]
Recognizer for alphabetic characters
[Char]
The [nth] element (zero-based) of a string
[Char-code]
The numeric code for a given character
[Char-downcase]
Turn upper-case [characters] into lower-case [characters]
[Char-equal]
Character equality without regard to case
[Char-upcase]
Turn lower-case [characters] into upper-case [characters]
[Char<]
Less-than test for [characters]
[Char<=]
Less-than-or-equal test for [characters]
[Char>]
Greater-than test for [characters]
[Char>=]
Greater-than-or-equal test for [characters]
[Character-alistp]
Recognizer for association lists with characters as keys
[Character-listp]
Recognizer for a true list of characters
[Characterp]
Recognizer for [characters]
[Code-char]
The character corresponding to a given numeric code
[Coerce]
Coerce a character list to a string and a string to a list
[Digit-char-p]
The number, if any, corresponding to a given character
[Digit-to-char]
Map a digit to a character
[Explode-atom]
Convert any [atom] into a [character-listp] that contains its
printed representation, rendering numbers in your choice of
print base.
[Explode-nonnegative-integer]
The list of [characters] in the radix-r form of a number
[Lower-case-p]
Recognizer for lower case characters
[Make-character-list]
[coerce] to a list of characters
[Standard-char-listp]
Recognizer for a true list of standard characters
[Standard-char-p]
Recognizer for standard characters
[Upper-case-p]
Recognizer for upper case characters")
(CHECK-INVARIANT-RISK (POINTERS)
"See [set-check-invariant-risk].")
(CHECK-SUM
(CERTIFICATE)
"Assigning ``often unique'' integers to files and objects
A ``check sum'' is an integer in some fixed range computed from the
printed representation of an object, e.g., the sum, modulo 2**32,
of the ascii codes of all the [characters] in the printed
representation.
Ideally, you would like the check sum of an object to be uniquely
associated with that object, like a fingerprint. It could then be
used as a convenient way to recognize the object in the future: you
could remember the check sum (which is relatively small) and when
an object is presented to you and alleged to be the special one you
could compute its check sum and see if indeed it was. Alas, there
are many more objects than check sums (after all, each check sum is
an object, and then there's t). So you try to design a check sum
algorithm that maps similar looking objects far apart, in the hopes
that corruptions and counterfeits --- which appear to be similar to
the object --- have different check sums. Nevertheless, the best
you can do is a many-to-one map. If an object with a different
check sum is presented, you can be positive it is not the special
object. But if an object with the same check sum is presented, you
have no grounds for positive identification.
The basic check sum algorithm in ACL2 is called check-sum-obj, which
computes the check sum of an ACL2 object. Roughly speaking, we scan
the print representation of the object and, for each character
encountered, we multiply the ascii code of the character times its
position in the stream (modulo a certain prime) and then add
(modulo a certain prime) that into the running sum. This is
inaccurate in many senses (for example, we don't always use the
ascii code and we see numbers as though they were printed in base
127) but indicates the basic idea.
ACL2 uses check sums to increase security in the [books] mechanism;
see [certificate].")
(CHECKPOINT-FORCED-GOALS
(PROOF-TREE)
"Cause forcing goals to be checkpointed in proof trees
Example forms:
(checkpoint-forced-goals t)
(checkpoint-forced-goals nil)
Also see [proof-tree].
By default, goals are not marked as checkpoints by a proof tree
display (as described elsewhere; see [proof-tree]) merely because
they [force] some hypotheses, thus possibly contributing to a
forcing round. However, some users may want such behavior, which
will occur once the command (checkpoint-forced-goals t) has been
executed. To return to the default behavior, use the command
(checkpoint-forced-goals nil).")
(CLAUSE-IDENTIFIER
(GOAL-SPEC)
"The internal form of a [goal-spec]
To each goal-spec, str, there corresponds a clause-identifier
produced by (parse-clause-id str). For example,
(parse-clause-id \"[2]Subgoal *4.5.6/7.8.9'''\")
returns ((2 4 5 6) (7 8 9) . 3).
The function string-for-tilde-@-clause-id-phrase inverts
parse-clause-id in the sense that given a clause identifier it
returns the corresponding goal-spec.
As noted in the documentation for [goal-spec], each clause printed in
the theorem prover's proof attempt is identified by a name. When
these names are represented as strings they are called ``goal
specs.'' Such strings are used to specify where in the proof
attempt a given hint is to be applied. The function parse-clause-id
converts goal-specs into clause identifiers, which are cons-trees
containing natural numbers.
Examples of goal-specs and their corresponding clause identifiers are
shown below.
parse-clause-id
-->
\"Goal\" ((0) NIL . 0)
\"Subgoal 3.2.1'\" ((0) (3 2 1) . 1)
\"[2]Subgoal *4.5.6/7.8.9'''\" ((2 4 5 6) (7 8 9) . 3)
<--
string-for-tilde-@-clause-id-phrase
The caar of a clause id specifies the forcing round, the cdar
specifies the goal being proved by induction, the cadr specifies
the particular subgoal, and the cddr is the number of primes in
that subgoal.
Internally, the system maintains clause ids, not goal-specs. The
system prints clause ids in the form shown by goal-specs. When a
goal-spec is used in a hint, it is parsed (before the proof attempt
begins) into a clause id. During the proof attempt, the system
watches for the clause id and uses the corresponding hint when the
id arises. (Because of the expense of creating and garbage
collecting a lot of strings, this design is more efficient than the
alternative.)")
(CLAUSE-PROCESSOR
(RULE-CLASSES)
"Make or apply a :clause-processor rule (goal-level simplifier)
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
We will introduce clause-processor rules by way of the following
example. But note that the clause-processor utility is more general
than this example may suggest; for example, the second argument of
evl0 in the hypothesis need not be the same as its second argument
in the conclusion.
; Example (which we'll return to, below):
(defthm correctness-of-note-fact-clause-processor
(implies (and (pseudo-term-listp cl)
(alistp a)
(evl0 (conjoin-clauses
(note-fact-clause-processor cl term))
a))
(evl0 (disjoin cl) a))
:rule-classes :clause-processor)
We begin this documentation with an introduction, focusing on the
example above, and then conclude with a detailed general discussion
of clause-processor rules. You might find it most useful simply to
look at the examples in community books directory
books/clause-processors/; see file Readme.lsp in that directory.
Also see [define-trusted-clause-processor] for documentation of an
analogous utility that does not require the clause-processor to be
proved correct. But please read the present documentation before
reading about that utility. Both utilities designate functions as
``clause-processors''. Such functions must be executable --- hence
not constrained by virtue of being introduced in the [signature] of
an [encapsulate] --- and must respect [stobj] and output arity
restrictions. For example, something like (car (mv ...)) is
illegal; also see [signature].
INTRODUCTION
A :clause-processor rule installs a simplifier at the level of goals,
where a goal is represented as a clause: a list of [term]s that is
implicitly viewed as a disjunction (the application of [or]). For
example, if ACL2 prints a goal in the form (implies (and p q) r),
then the clause might be the one-element list containing the
internal representation of this term --- (implies (if p q 'nil) r)
--- but more likely, the corresponding clause is ((not p) (not q)
r). Note that the members of a clause are translated terms; see
[term] and [termp]. For example, they do not contain calls of the
macro AND, and constants are quoted. The result of running a
clause-processor must be a list of legal clauses; see [meta] for a
discussion of translated terms, and for related discussion about
``forbidden'' function symbols, [set-skip-meta-termp-checks].
Technically, the recognizer for a clause is the function [term-listp]
and the recognizer for a list of clauses is [term-list-listp].
Note that clause-processor simplifiers are similar to metafunctions,
and similar efficiency considerations apply. See [meta], in
particular the discussion on how to ``make a metafunction maximally
efficient.''
Unlike rules of class :[meta], rules of class :clause-processor must
be applied by explicit :clause-processor [hints]; they are not
applied automatically (unless by way of computed hints; see
[computed-hints]). But :clause-processor rules can be useful in
situations for which it is more convenient to code a simplifier
that manipulates the entire goal clause rather than individual
subterms of terms in the clause.
We begin with a simple illustrative example: a clause-processor that
assumes an alleged fact (named term in the example) and creates a
separate goal to prove that fact. We can extend the hypotheses of
the current goal (named cl in the example) with a term by adding
the negation of that term to the clause (disjunctive)
representation of that goal. So the following returns a list of two
clauses: the result of adding term as a hypothesis to the input
clause, as just described, and a second clause consisting only of
that term. This list of two clauses can be viewed as the
conjunction of the first clause and the second clause (where again,
each clause is viewed as a disjunction).
(defun note-fact-clause-processor (cl term)
(declare (xargs :guard t)) ; optional, for better efficiency
(list (cons (list 'not term)
cl)
(list term)))
As with :[meta] rules, we need to introduce a suitable evaluator; see
[defevaluator] if you want details. Since we expect to reason about
the function [not], because of its role in
note-fact-clause-processor as defined above, we include NOT in the
set of functions known to this evaluator. We also include IF, as is
often a good idea.
(defevaluator evl0 evl0-list
((not x) (if x y z)))
ACL2 can now prove the following theorem automatically. (This is the
example displayed at the outset of this [documentation] topic.) Of
course, :clause-processor rules about clause-processor functions
less trivial than note-fact-clause-processor may require lemmas to
be proved first! The function disjoin takes a clause and returns
its disjunction (the result of applying [or] to its members), and
conjoin-clauses applies disjoin to every element of a given list of
clauses and then conjoins (applies AND) to the corresponding list
of resulting terms.
(defthm correctness-of-note-fact-clause-processor
(implies (and (pseudo-term-listp cl)
(alistp a)
(evl0 (conjoin-clauses
(note-fact-clause-processor cl term))
a))
(evl0 (disjoin cl) a))
:rule-classes :clause-processor)
Now let us submit a silly but illustrative example theorem to ACL2,
to show how a corresponding :clause-processor hint is applied. The
hint says to apply the clause-processor function,
note-fact-clause-processor, to the current goal clause and a ``user
hint'' as the second argument of that function, in this case (equal
a a). Thus, a specific variable, clause, is always bound to the
current goal clause for the evaluation of the :clause-processor
hint, to produce a list of clauses. Since two subgoals are created
below, we know that this list contained two clauses. Indeed, these
are the clauses returned when note-fact-clause-processor is applied
to two arguments: the current clause, which is the one-element list
((equal (car (cons x y)) x)), and the user hint, (equal a a).
ACL2 !>(thm (equal (car (cons x y))
x)
:hints
((\"Goal\"
:clause-processor
(note-fact-clause-processor clause '(equal a a)))))
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
We now apply the verified :CLAUSE-PROCESSOR function NOTE-FACT-CLAUSE-
PROCESSOR to produce two new subgoals.
Subgoal 2
(IMPLIES (EQUAL A A)
(EQUAL (CAR (CONS X Y)) X)).
But we reduce the conjecture to T, by the :executable-counterpart of
IF and the simple :rewrite rule CAR-CONS.
Subgoal 1
(EQUAL A A).
But we reduce the conjecture to T, by primitive type reasoning.
Q.E.D.
Summary
Form: ( THM ...)
Rules: ((:EXECUTABLE-COUNTERPART IF)
(:EXECUTABLE-COUNTERPART NOT)
(:FAKE-RUNE-FOR-TYPE-SET NIL)
(:REWRITE CAR-CONS))
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Proof succeeded.
ACL2 !>
That concludes our introduction to clause-processor rules and hints.
We turn now to detailed documentation.
DETAILED DOCUMENTATION
The [signature] of a clause-processor function, CL-PROC, must have
one of the following forms. Here, each st_i is a [stobj] (possibly
state) while the other parameters and results are not stobjs (see
[stobj]). Note that there need not be input stobjs in [3] --- i.e.,
k can be 0 --- and even if there are, there need not be output
stobjs.
[1] ((CL-PROC cl) => cl-list)
[2] ((CL-PROC cl hint) => cl-list)
[3] ((CL-PROC cl hint st_1 ... st_k) => (mv erp cl-list st_i1 ... st_in))
In [3], we think of the first component of the result as an error
flag. Indeed, a proof will instantly abort if that error flag is
not nil.
We next discuss the legal forms of :clause-processor rules, followed
below by a discussion of :clause-processor [hints]. In the
discussion below, we use lower-case names to represent specific
symbols, for example implies, and we use upper-case names to
represent more arbitrary pieces of syntax (which we will describe),
for example, CL.
If a :[rule-classes] specification includes :clause-processor, then
the corresponding term must have the following form. (Additional
``meta-extract'' hypotheses, not shown or discussed below, may be
included as desired in order to use facts from the logical [world]
to help prove the rule; see [meta-extract] for explanation of this
advanced feature.)
; General Form (omitting possible meta-extract hypotheses)
(implies (and (pseudo-term-listp CL)
(alistp A)
(EVL (conjoin-clauses <CL-LIST>)
B))
(EVL (disjoin CL) A))
Here EVL is a known evaluator; CL and A are distinct non-stobj
variables; and <CL-LIST> is an expression representing the clauses
returned by the clause-processor function CL-PROC, whose form
depends on the [signature] of that function, as follows. Typically
B is A, but it can be any term (useful when generalization is
occurring; see the example ``Test generalizing alist'' in community
book books/clause-processors/basic-examples.lisp). For cases [1]
and [2] above, <CL-LIST> is of the form (CL-PROC CL) or (CL-PROC CL
HINT), respectively, where in the latter case HINT is a non-stobj
variable distinct from the variables CL and A. For case [3],
<CL-LIST> is of the form
(clauses-result (CL-PROC CL HINT st_1 ... st_k))
where the st_i are the specific stobj names mentioned in [3].
Logically, clauses-result returns the [cadr] if the [car] is NIL,
and otherwise (for the error case) returns a list containing the
empty (false) clause. So in the non-error case, clauses-result
picks out the second result, denoted cl-list in [3] above, and in
the error case the implication above trivially holds.
In the above theorem, we are asked to prove (EVL (disjoin CL) A)
assuming that the conjunction of all clauses produced by the clause
processor evaluates to a non-nil value under some alist B. In fact,
we can choose B so as to allow us to assume evaluations of the
generated clauses over many different alists. This technique is
discussed in the community book
books/clause-processors/multi-env-trick.lisp, which introduces some
macros that may be helpful in accomplishing proofs of this type.
The clause-processor function, CL, must have a guard that ACL2 can
trivially prove from the hypotheses that the first argument of CL
is known to be a pseudo-term-listp and any [stobj] arguments are
assumed to satisfy their stobj predicates.
Next we specify the legal forms for :clause-processor [hints]. These
depend on the signature as described in [1] through [3] above.
Below, as above, CL-PROC is the clause-processor function, and
references to ``clause'' refer to that exact variable (not, for
example, to cl). In each of the three cases, the forms shown for
that case are equivalent; in particular, the :function syntax is
simply a convenience for the final form in each case.
Signature [1], ((cl-proc cl) => cl-list):
:clause-processor CL-PROC
:clause-processor (:function CL-PROC)
:clause-processor (CL-PROC clause)
or any term macroexpanding to (CL-PROC clause).
Signature [2], ((cl-proc cl hint) => cl-list):
:clause-processor (:function CL-PROC :hint HINT)
:clause-processor (CL-PROC clause HINT)
or any term macroexpanding to (CL-PROC clause HINT), where HINT is
any term with at most CLAUSE free.
Signature [3], ((CL-PROC cl hint ...) => (mv erp cl-list ...))
:clause-processor (:function CL-PROC :hint HINT)
:clause-processor (CL-PROC clause HINT st_1 ... st_k)
or any term macroexpanding to (CL-PROC clause HINT st_1 ... st_k),
where HINT is any term with at most CLAUSE free.
A :clause-processor hint causes the proof to abort if the result,
val, returned by evaluating the suitable CL-PROC call, as above, is
not a list of clauses, i.e., a list of (translated) [term] lists
(see [term-list-listp]) in the current logical [world]. More
precisely, the proof aborts if (term-list-listp val (w state)) is
nil. This term-list-listp test is done explicitly every time a
clause processor is run unless a :[well-formedness-guarantee] has
been provided with the :clause-processor rule or
[set-skip-meta-termp-checks] has been used with an active trust tag
to skip the check at the user's risk.
The proof also aborts if in case [3] the first (erp) value returned
is not nil, in which case erp is used for printing an error message
as follows: if it is a string, then that string is printed; but if
it is a non-empty true list whose first element is a string, then
it is printed as though by (fmt ~@0 (list (cons #\\0 erp)) ...) (see
[fmt]). Otherwise, a non-nil erp value causes a generic error
message to be printed.
If there is no error as above, but the CL-PROC call returns clause
list whose single element is equal to the input clause, then the
hint is ignored since we are left with the goal with which we
started. In that case, the other prover processes are then applied
as usual.
You can see all current :clause-processor rules by issuing the
following command: (print-clause-processor-rules).
The following paper discusses ACL2 clause-processors at a high level
suitable for a non-ACL2 audience:
M. Kaufmann, J S. Moore, S. Ray, and E. Reeber, ``Integrating
External Deduction Tools with ACL2.'' Journal of Applied Logic
(Special Issue: Empirically Successful Computerized Reasoning),
Volume 7, Issue 1, March 2009, pp. 3--25. Also published online
(DOI 10.1016/j.jal.2007.07.002). Preliminary version in:
Proceedings of the 6th International Workshop on the
Implementation of Logics (IWIL 2006) (C. Benzmueller, B.
Fischer, and G. Sutcliffe, editors), {CEUR Workshop Proceedings
Vol. 212 | http://ceur-ws.org/Vol-212/}, Phnom Penh, Cambodia,
pp. 7-26, November 2006.
Subtopics
[Set-skip-meta-termp-checks]
Skip output checks for [meta] functions and [clause-processor]s
[Set-skip-meta-termp-checks!]
Skip output checks non-[local]ly for [meta] functions and
[clause-processor]s")
(CLEAR-HASH-TABLES
(MEMOIZE)
"Deprecated feature
Deprecated. Calls [clear-memoize-tables] and then [hons-clear] or
[hons-wash], whichever makes sense for the underlying Common Lisp.")
(CLEAR-MEMOIZE-STATISTICS
(MEMOIZE)
"Clears all profiling info displayed by ([memoize-summary])
Logically, this function just returns nil. It clears all profiling
info displayed by ([memoize-summary])
Function: <clear-memoize-statistics>
(defun clear-memoize-statistics
nil (declare (xargs :guard t))
nil)")
(CLEAR-MEMOIZE-TABLE
(MEMOIZE)
"Forget values remembered for the given function
This function returns its argument, fn, unchanged. The values
memoized for fn are forgotten.
Function: <clear-memoize-table>
(defun clear-memoize-table (fn)
(declare (xargs :guard t))
fn)")
(CLEAR-MEMOIZE-TABLES
(MEMOIZE)
"Forget values remembered for all the memoized functions
Clear-memoize-tables is a logical no-op. All memoized values are
forgotten. It returns nil, invoking [clear-memoize-table] for each
memoized function.
Function: <clear-memoize-tables>
(defun clear-memoize-tables
nil (declare (xargs :guard t))
nil)")
(CLOSE-INPUT-CHANNEL (POINTERS)
"See [io].")
(CLOSE-OUTPUT-CHANNEL (POINTERS)
"See [io].")
(CLOSE-TRACE-FILE
(TRACE)
"Stop redirecting trace output to a file
General Form:
(close-trace-file) ; trace output is no longer redirected to a file
Output from [trace$] normally goes to the screen, or more precisely,
[standard-co]. It can be redirected to a file; see
[open-trace-file]. Use close-trace-file to redirect trace output to
[standard-co].")
(CODE-CHAR
(CHARACTERS NUMBERS ACL2-BUILT-INS)
"The character corresponding to a given numeric code
This function maps a numeric code to the corresponding character, for
example: (code-char 65) evaluates to #\\A. See [char-code] for a
sort of inverse function, which maps a character to its code.
Completion Axiom (completion-of-code-char):
(equal (code-char x)
(if (and (integerp x)
(>= x 0)
(< x 256))
(code-char x)
(code-char 0)))
[Guard] for (code-char x):
(and (integerp x)
(>= x 0)
(< x 256))
ACL2 supports 8-bit [characters]. Inputs not between 0 and 255 are
treated as 0.")
(COERCE
(STRINGS CHARACTERS ACL2-BUILT-INS)
"Coerce a character list to a string and a string to a list
Completion Axiom (completion-of-coerce):
(equal (coerce x y)
(cond
((equal y 'list)
(if (stringp x)
(coerce x 'list)
nil))
(t
(coerce (make-character-list x) 'string))))
[Guard] for (coerce x y):
(if (equal y 'list)
(stringp x)
(if (equal y 'string)
(character-listp x)
nil))
Also see community book books/misc/fast-coerce.lisp, contributed by
Jared Davis, for a version of coerce that may be faster for Common
Lisp implementations other than CCL 1.3 or later, if the second
argument is 'list (for coercing a string to a list).
Logical Note
The function coerce can be viewed as the constructor for strings. As
discussed in Section 7 of \"{A Precise Description of the ACL2 Logic
| http://www.cs.utexas.edu/users/moore/publications/km97a.pdf}\"
(Matt Kaufmann and J Moore, April, 1998), a string may be built by
coercing its list of characters: for example, \"abc\" is (coerce
'(#\\a #\\b #\\c) 'string). More precisely, \"abc\" is an abbreviation
for (coerce '(#\\a #\\b #\\c) 'string), where even more pedantically,
'(#\\a #\\b #\\c) is an abbreviation for (cons '#\\a (cons '#\\b (cons
'#\\c 'nil))).")
(COMMAND
(HISTORY)
"Forms you type at the top-level, but...
...the word ``command'' usually refers to a top-level form whose
evaluation produces a new logical [world].
Typical commands are:
(defun foo (x) (cons x x))
(defthm consp-foo (consp (foo x)))
(defrec pair (hd . tl) nil)
The first two forms are examples of commands that are in fact
primitive [events]. See [events]. Defrec, on the other hand, is a
macro that expands into a [progn] of several primitive [events]. In
general, a [world] extending command generates one or more
[events].
Both [events] and commands leave landmarks on the [world] that enable
us to determine how the given [world] was created from the previous
one. Most of your interactions will occur at the command level,
i.e., you type commands, you print previous commands, and you undo
back through commands. Commands are denoted by command descriptors.
See [command-descriptor].")
(COMMAND-DESCRIPTOR
(HISTORY)
"An object describing a particular [command] typed by the user
Examples:
:max ; the command most recently typed by the user
:x ; synonymous with :max
(:x -1) ; the command before the most recent one
(:x -2) ; the command before that
:x-2 ; synonymous with (:x -2)
5 ; the fifth command typed by the user
1 ; the first command typed by the user
0 ; the last command of the system initialization
-1 ; the next-to-last initialization command
:min ; the first command of the initialization
:start ; the last command of the initial ACL2 logical world
fn ; the command that introduced the logical name fn
(:search (defmacro foo-bar))
; the first command encountered in a search from :max to
; 0 that either contains defmacro and foo-bar in the
; command form or contains defmacro and foo-bar in some
; event within its block.
The recorded [history] of your interactions with the top-level ACL2
[command] loop is marked by the [command]s you typed that changed
the logical [world]. Each such [command] generated one or more
[events], since the only way for you to change the logical [world]
is to execute an event function. See [command] and see [events]. We
divide [history] into ``[command] blocks,'' grouping together each
[world] changing [command] and its [events]. A ``[command]
descriptor'' is an object that can be used to describe a particular
[command] in the [history] of the ongoing session.
Each [command] is assigned a unique integer called its ``[command]
number'' which indicates the [command]'s position in the
chronological ordering of all of the [command]s ever executed in
this session (including those executed to initialize the system).
We assign the number 1 to the first [command] you type to ACL2. We
assign 2 to the second and so on. The non-positive integers are
assigned to ``prehistoric'' [command]s, i.e., the [command]s used
to initialize the ACL2 system: 0 is the last [command] of the
initialization, -1 is the one before that, etc.
The legal [command] descriptors are described below. We use n to
denote any integer, sym to denote any logical name (see
[logical-name]), and cd to denote, recursively, any [command]
descriptor.
command command
descriptor described
:max -- the most recently executed command (i.e., the one with
the largest command number)
:x -- synonymous with :max
:x-k -- synonymous with (:x -k), if k is an integer and k>0
:min -- the earliest command (i.e., the one with the smallest
command number and hence the first command of the system
initialization)
:start -- the last command when ACL2 starts up
n -- command number n (If n is not in the
range :min<=n<=:max, n is replaced by the nearest of :min
and :max.)
sym -- the command that introduced the logical name sym
(cd n) -- the command whose number is n plus the command number of
the command described by cd
(:search pat cd1 cd2)
In this command descriptor, pat must be either an atom or
a true list of atoms and cd1 and cd2 must be command
descriptors. We search the interval from cd1 through cd2
for the first command that matches pat. Note that if cd1
occurs chronologically after cd2, the search is
``backwards'' through history while if cd1 occurs
chronologically before cd2, the search is ``forwards''. A
backwards search will find the most recent match; a
forward search will find the chronologically earliest
match. A command matches pat if either the command form
itself or one of the events in the block contains pat (or
all of the atoms in pat if pat is a list).
(:search pat)
the command found by (:search pat :max 0), i.e., the most
recent command matching pat that was part of the user's
session, not part of the system initialization.")
(COMMAND-LINE
(INTERFACING-TOOLS)
"Handling of command-line arguments when ACL2 is invoked
You may provide command-line arguments when invoking ACL2, which are
passed to the host Lisp. For more information on this topic, along
with a discussion of how to save an ACL2 executable that avoids
passing command-line arguments to the host Lisp, see [save-exec].
Subtopics
[Save-exec]
Save an executable image and a wrapper script")
(COMMON-LISP
(ABOUT-ACL2)
"Relation to Common Lisp, including deviations from the spec
ACL2 is a logic, a theorem prover, and a programming language based
on Common Lisp. A connection with Common Lisp is established with
guards (see [guard]).
However, here we document potential deviations from Common Lisp
semantics even in the presence of verified guards. Our view is that
these deviations are extremely unlikely to manifest; indeed, as of
this writing we are unaware of any cases in which these issues
arise in practice. However, we feel obligated to acknowledge their
possibility, which could result in surprises during evaluation or
even proof.
The Common Lisp spec allows certain predicates to return what it
calls ``generalized Booleans,'' which are really arbitrary values
that are to be viewed as either nil or non-nil. However, in ACL2
these functions are assumed to return nil or t. For details,see
[generalized-booleans].
The execution of forms with :[program] mode functions can result in
calls of functions on arguments that do not satisfy their [guard]s.
In practice, this simply causes hard Lisp errors. But in principle
one could imagine a damaged Lisp image that operates incorrectly.
See [defun-mode-caveat].
The Common Lisp spec, specifically Section {Section 3.2.2.3 |
http://www.lispworks.com/documentation/HyperSpec/Body/03_bbc.htm}
of the {Common Lisp Hyperspec |
http://www.lispworks.com/documentation/HyperSpec/Front}, allows for
undefined results when a function is ``multiply defined'' in a
compiled file. ACL2 allows redundant [defun]s in a book, and in
general [books] are compiled by certify-book (but see
[certify-book] and see [compilation] for how to control such
compilation). Moreover, ACL2 provides a redefinition capability
(see [ld-redefinition-action] and see [redef]), and the above
section also allows for undefined results when a function is
defined in a compiled file and then redefined, presumably (for
example) because of inlining.
Subtopics
[Defun-mode-caveat]
Potential soundness issue for functions with [defun-mode] :[program]
[Escape-to-common-lisp]
Escaping to Common Lisp
[Generalized-booleans]
Potential soundness issues related to ACL2 predicates")
(COMMON_LISP
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Common Lisp
[{IMAGE}]
{IMAGE}
The logic of ACL2 is based on Common Lisp.
Common Lisp is the standard list processing programming language. It
is documented in: Guy L. Steele, {Common Lisp The Language | },
Digital Press, 12 Crosby Drive, Bedford, MA 01730, 1990.
ACL2 formalizes only a subset of Common Lisp. It includes such
familiar Lisp functions as cons, car and cdr for creating and
manipulating list structures, various arithmetic primitives such as
+, *, expt and <=, and intern and symbol-name for creating and
manipulating symbols. Control primitives include cond, case and if,
as well as function call, including recursion. New functions are
defined with defun and macros with defmacro. See [programming]
[{ICON}] for a list of the Common Lisp primitives supported by
ACL2.
ACL2 supports five of Common Lisp's datatypes:
* the precisely represented, unbounded numbers (integers, rationals,
and the complex numbers with rational components, called the
``complex rationals'' here),
* the characters with ASCII codes between 0 and 255
* strings of such characters
* symbols (including packages)
* conses
ACL2 is a very small subset of full Common Lisp. ACL2 does not
include the Common Lisp Object System (CLOS), higher order
functions, circular structures, and other aspects of Common Lisp
that are non-applicative. Roughly speaking, a language is
applicative if it follows the rules of function application. For
example, f(x) must be equal to f(x), which means, among other
things, that the value of f must not be affected by ``global
variables'' and the object x must not change over time.
[{IMAGE}]")
(COMMON_LISP_AS_A_MODELING_LANGUAGE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Common Lisp as a Modeling Language
{IMAGE}
In ACL2 we have adopted Common Lisp as the basis of our modeling
language. If you have already read our brief note on Common Lisp
and recall the example of app, please proceed. Otherwise click
[here] for an exceedingly brief introduction to Common Lisp and
then come back here.
In Common Lisp it is very easy to write systems of formulas that
manipulate discrete, inductively constructed data objects. In
building a model you might need to formalize the notion of
sequences and define such operations as concatenation, length,
whether one is a permutation of the other, etc. It is easy to do
this in Common Lisp. Furthermore, if you have a Common Lisp
``theory of sequences'' you can run the operations and relations
you define. That is, you can execute the functions on concrete data
to see what results your formulas produce.
If you define the function app as shown above and then type
(app '(A B) '(C D E))
in any Common Lisp, the answer will be computed and will be (A B C D
E).
The executable nature of Common Lisp and thus of ACL2 is very handy
when producing models.
But executability is not enough for a modeling language because the
purpose of models is to permit analysis.
Click [here] to continue.")
(COMMUNITY-BOOKS
(BOOKS)
"Libraries of ACL2 [books] developed by the ACL2 community.
ACL2 [books] are files of ACL2 [events] like definitions and
theorems.
The ACL2 Community Books are the canonical set of open-source books
for ACL2, developed since the early 1990s by members of the ACL2
community. They include libraries for reasoning in many domains,
macro libraries for more quickly writing and documenting code,
interfacing tools for connecting ACL2 to other systems,
productivity tools for better proof automation and debugging, and
specialty libraries for areas like hardware verification.
From the {github ACL2 project | https://github.com/acl2/acl2/} web
site you can:
* Download the Community Books;
* Learn how to contribute books to the ACL2 community; and
* Obtain updates between ACL2 releases.
See [git-quick-start] for information about how to download the
``bleeding edge'' ACL2 system and community books.
Subtopics
[Books-certification]
Instructions for certifying the ACL2 [community-books].")
(COMP
(COMPILATION EVENTS ACL2-BUILT-INS)
"Compile some ACL2 functions
NOTE: Comp is a no-op if explicit compilation is suppressed; see
[compilation]. The documentation here assumes that this is not the
case.
Examples:
:comp t ; compile all uncompiled ACL2 functions
(comp t) ; same as above, but can be put into a book
(comp :exec) ; compile all uncompiled logic (``*1*'') definitions
:comp foo ; compile the defined function foo
:comp (:raw foo) ; compile the raw Lisp version of the defined function foo
but not the corresponding logic definition
:comp (foo bar) ; compile the defined functions foo and bar
:comp (foo (:raw bar)) ; compile the defined functions foo and bar, but for
; bar do not compile the corresponding logic definition
General Form:
:comp specifier
where specifier is one of the following:
t compile all user-defined ACL2 functions that are
currently uncompiled (redefined built-in functions
are not recompiled)
:exec same as t, except that only logic versions are
compiled (see below), not raw Lisp definitions
:raw same as t, except that only raw Lisp definitions are
compiled, not logic version (see below)
(name-1 ... name-k) a non-empty list of names of functions defined by
DEFUN in ACL2, except that each name-i can be of
the form (:raw sym) or (:exec sym), where sym is
the name of such a function
name same as (name)
When you define a function in ACL2, you are really causing two
definitions to be made ``under the hood'' in Common Lisp: the
definition is submitted explicitly to raw Lisp, but so is a
corresponding ``logic definition''. If guards have not been
verified, then only the logic definition will be evaluated; see
[guards-and-evaluation], in particular the section titled ``Guards
and evaluation V: efficiency issues''.
Thus, if you are not verifying [guard]s and you want the benefit of
Lisp compilation for speed and space efficiency, then you may want
to place the form (comp :exec) in your [books].
Generally it is not necessary to place the form (comp t), or the form
(comp :raw), in a book, because [certify-book] compiles the raw
Lisp definitions anyhow, by default. But you may wish to put (comp
t) or (comp fn1 fn2 ... fnk) in a book when such a form precedes
expensive calls of functions, for example for proofs involving
calls of functions on large constants, or to support
computationally expensive macroexpansion.
As suggested by the examples above, if a function specifier is of the
form (:raw fn), then fn will be compiled in raw Common Lisp but its
corresponding logic definition will not be compiled; and for (:exec
fn), it's the other way around.
The use of :comp may create various files whose names start with
``TMP*'', but it then deletes them. If you want to save these
files, evaluate (assign keep-tmp-files t).
Also see [set-compile-fns] for a way to compile each function as it
is defined. But note that set-compile-fns is ignored during
[include-book].
Note that if functions are traced (see [trace$]), then comp will
first untrace the functions that are to be compiled, then will do
the compile(s), and finally will re-trace the functions that it
untraced (using their original trace specs). In particular, if you
have traced a function and then you compile it using :comp, the
resulting traced function will be compiled as well unless you
specified :compile nil in your trace spec; and after you untrace
the function it will definitely run compiled.
We conclude with a technical remark only for those who use trust tags
to write raw Lisp code. :Comp generally creates files to compile
unless it is given a single function to compile. Those files
contain the ACL2 definitions of all functions to compile, omitting
those in the lists obtained by evaluating the forms (@
logic-fns-with-raw-code) and (@ program-fns-with-raw-code). :Comp
skips compilation for functions that are already compiled, as is
typically the case when you redefine functions in raw Lisp using
[include-raw]. But if you define interpreted (as opposed to
compiled) functions with raw Lisp code, say by using trust tags
(see [defttag]) and [progn!], then you are advised to add all such
symbols to one of the lists stored in the two [state] globals
above: to logic-fns-with-raw-code if the function symbol is in
:[logic] mode, else to program-fns-with-raw-code. Then, instead of
the corresponding ACL2 definition (without raw Lisp code) being
written to a file, the function symbol will be passed directly to
the Lisp compile function. Note that the above two state globals
are both untouchable, so you may need to deal with that before
modifying them, for example as follows (also see
[remove-untouchable]).
(defttag t)
(state-global-let*
((temp-touchable-vars t set-temp-touchable-vars))
(progn! (f-put-global 'logic-fns-with-raw-code
(cons 'my-fn (@ logic-fns-with-raw-code))
state)))")
(COMP-GCL
(COMPILATION ACL2-BUILT-INS)
"Compile some ACL2 functions leaving .c and .h files
Comp-gcl is for use by experts who want to examine the results of GCL
compilation, and it may only be used with ACL2 implementations
built on top of GCL. It takes exactly the same arguments as [comp],
and has the same basic functionality (see [comp]), but has two
additional effects. First, files \"TMP.lisp\" and \"TMP1.lisp\" are
always created, even when a single function is specified. Second,
comp-gcl always leaves files \"TMP.c\", \"TMP.h\", \"TMP1.c\", and
\"TMP1.h\" when compilation is complete.")
(COMPILATION
(PROGRAMMING)
"Compiling ACL2 functions
ACL2 has several mechanisms to speed up the evaluation of function
calls by compiling functions: see [comp], see [set-compile-fns],
and see [certify-book]. The intention is that compilation never
changes the value returned by a function call, though it could
cause the call to succeed rather than fail, for example by avoiding
a stack overflow.
The [state] global variable 'compiler-enabled is set automatically
when the system is built, and may depend on the underlying Lisp
implementation. (In order to disable the compiler at build time,
which will defeat the speed-up but usually be pretty harmless when
the host Lisp is CCL or SBCL, see the discussion of
ACL2_COMPILER_DISABLED in distributed file GNUmakefile.) The value
of 'compiler-enabled, as returned by (@ compiler-enabled), can be
t, :books, or nil. If the value is nil, then [include-book] and
[certify-book] coerce their arguments :load-compile-file and
compile-flg arguments (respectively) to nil. Otherwise, the value
is :books or t and there is no such coercion; but if the value is
not t, then [comp] and [set-compile-fns] are no-ops, which is
probably desirable for Lisps such as CCL and SBCL that compile
on-the-fly even when the compiler is not explicitly invoked.
However, you may have reason to want to change the above (default)
behavior. To enable compilation by default for [certify-book] and
[include-book] but not for [comp] or [set-compile-fns]:
(set-compiler-enabled :books state)
To enable compilation not only as above but also for [comp] and
[set-compile-fns]:
(set-compiler-enabled t state)
To suppress compilation and loading of compiled files by
[include-book] (for example, if you get a raw Lisp error such as
``Wrong FASL version''):
(set-compiler-enabled nil state)
Remark for users of [make-event]. If set-compiler-enabled is invoked
during make-event expansion, its effect on [state] global variable
'compiler-enabled will persist after evaluation completes for that
make-event form. So for example, one might use the following idiom
in a book so that for all books included on behalf of a given
[include-book] form, no compiled files are loaded, but (optionally)
no such effect takes place for later include-book forms in that
book.
(make-event
(pprogn (f-put-global 'saved-compiler-enabled (@ compiler-enabled) state)
(set-compiler-enabled nil state)
(value '(value-triple nil)))
:check-expansion t)
(include-book \"my-book\")
; optional
(make-event
(pprogn (set-compiler-enabled (@ saved-compiler-enabled) state)
(value '(value-triple nil)))
:check-expansion t)
Upon completion of an invocation of [include-book] or [certify-book],
the value of [state] global variable 'compiler-enabled is restored
to the value it had immediately before that invocation.
See [book-compiled-file] for more discussion about compilation and
[books].
We close with a discussion of a feature that allows control over the
loading of .port files in close analogy to how loading of compiled
files is controlled by set-compiler-enabled, as described above.
(See [uncertified-books] for a discussion of .port files.) A
[state] global variable, 'port-file-enabled exists for this
purpose, and it is set as follows.
(set-port-file-enabled t state) ; permit loading of .port files (default)
(set-port-file-enabled nil state) ; skip loading of .port files
Just as described above for state global compiler-enabled, the value
of 'port-file-enabled persists after [make-event] expansion and is
restored after [certify-book] and [include-book]. The idiom
displayed above, for avoiding loading of compiled files, can be
modified or extended in the obvious way to avoid loading of .port
files.
Subtopics
[Comp]
Compile some ACL2 functions
[Comp-gcl]
Compile some ACL2 functions leaving .c and .h files
[Disassemble$]
Disassemble a function
[Set-compile-fns]
Have each function compiled as you go along.
[Set-compiler-enabled]
Disable [compilation].
[The]
The is a special form that can be used to optimize the execution
efficiency of [guard]-verified ACL2 definitions, or (less
frequently) to carry out a low-level run-time type checks.
(Advanced)")
(COMPILING-ACL2P
(PARALLELISM)
"Compiling ACL2(p)
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
See [parallelism-tutorial] for an introduction to parallel
programming in ACL2.
You can build an experimental version of ACL2 that supports parallel
execution in the following host Common Lisp implementations:
* CCL (OpenMCL)
* Lispworks 6.0
* SBCL with threads (feature :sb-thread)
The command below will compile ACL2 to support parallel execution,
including parallel execution during proofs. Any non-empty string
may be used in place of t, and the value of LISP (shown here as
ccl) is any Lisp executable on which one can build ACL2(p) (see
[parallelism]).
make ACL2_PAR=t LISP=ccl
So for example, to make an executable image and also documentation
(which will appear in subdirectories doc/EMACS and doc/HTML), using
the Lisp executable ccl:
make large DOC ACL2_PAR=t LISP=ccl")
(COMPLEX
(NUMBERS ACL2-BUILT-INS)
"Create an ACL2 number
Examples:
(complex x 3) ; x + 3i, where i is the principal square root of -1
(complex x y) ; x + yi
(complex x 0) ; same as x, for rational numbers x
The function complex takes two rational number arguments and returns
an ACL2 number. This number will be of type (complex rational) [as
defined in the Common Lisp language], except that if the second
argument is zero, then complex returns its first argument. The
function [complex-rationalp] is a recognizer for complex rational
numbers, i.e. for ACL2 numbers that are not rational numbers.
The reader macro #C (which is the same as #c) provides a convenient
way for typing in complex numbers. For explicit rational numbers x
and y, #C(x y) is read to the same value as (complex x y).
The functions [realpart] and [imagpart] return the real and imaginary
parts (respectively) of a complex (possibly rational) number. So
for example, (realpart #C(3 4)) = 3, (imagpart #C(3 4)) = 4,
(realpart 3/4) = 3/4, and (imagpart 3/4) = 0.
The following built-in axiom may be useful for reasoning about
complex numbers.
(defaxiom complex-definition
(implies (and (real/rationalp x)
(real/rationalp y))
(equal (complex x y)
(+ x (* #c(0 1) y))))
:rule-classes nil)
A completion axiom that shows what complex returns on arguments
violating its [guard] (which says that both arguments are rational
numbers) is the following, named completion-of-complex.
(equal (complex x y)
(complex (if (rationalp x) x 0)
(if (rationalp y) y 0)))")
(COMPLEX-RATIONALP
(NUMBERS ACL2-BUILT-INS)
"Recognizes complex rational numbers
Examples:
(complex-rationalp 3) ; nil, as 3 is rational, not complex rational
(complex-rationalp #c(3 0)) ; nil, since #c(3 0) is the same as 3
(complex-rationalp t) ; nil
(complex-rationalp #c(3 1)) ; t, as #c(3 1) is the complex number 3 + i
See [complex] for more about complex rationals in ACL2.")
(COMPLEX/COMPLEX-RATIONALP
(NUMBERS ACL2-BUILT-INS)
"Recognizer for complex numbers
For most ACL2 users, this is a macro abbreviating complex-rationalp;
see [complex-rationalp]. In ACL2(r) (see [real]), a complex number
x may have irrational real and imaginary parts. This macro
abbreviates the predicate complexp in ACL2(r), which holds for such
x. Most ACL2 users can ignore this macro and use
[complex-rationalp] instead. Some community books use
complex/complex-rationalp so that they are suitable for ACL2(r) as
well.")
(COMPOUND-RECOGNIZER
(RULE-CLASSES)
"Make a rule used by the typing mechanism
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Examples:
(defthm alistp-implies-true-listp-compound-recognizer
(implies (alistp x) ; When (alistp x) is assumed true, add
(true-listp x)) ; the additional hypothesis that x is
:rule-classes :compound-recognizer) ; of primitive type true-listp.
(defthm natp-compound-recognizer ; See discussion below.
(equal (natp x)
(and (integerp x)
(<= 0 x)))
:rule-classes :compound-recognizer)
Before presenting the General Forms, we start with a motivating
example: the second [defthm] form above, which provides a nice
example of a :compound-recognizer rule that is built into ACL2. To
see how this rule might be useful, consider the following
(admittedly very simple) [events].
(defun triple (x)
(* 3 x))
(defthm triple-preserves-integerp
(implies (integerp x)
(integerp (triple x))))
(in-theory (disable triple natp))
If the above :compound-recognizer rule is disabled, then the
following trivial theorem fails as shown; we explain below.
(thm (implies (natp x)
(integerp (triple x)))
:hints ((\"Goal\" :in-theory (disable natp-compound-recognizer))))
The problem is that when ACL2 tries to rewrite the term (integerp
(triple x)) using the :[rewrite] rule triple-preserves-integerp, it
needs to rewrite the hypothesis (integerp x) to t, but instead what
is known is (natp x). If we remove the hint, then the proof
succeeds because the above :compound-recognizer rule tells ACL2
that when assuming (natp x) to be true, it should actually assume
both (integerp x) and (<= 0 x) to be true.
General Forms:
(implies (fn x) concl) ; (1)
(implies (not (fn x)) concl) ; (2)
(and (implies (fn x) concl1) ; (3)
(implies (not (fn x)) concl2))
(if (fn x) concl1 concl2) ; (4)
(iff (fn x) concl) ; (5)
(equal (fn x) concl) ; (6)
where fn is a Boolean valued function of one argument, x is a
variable symbol, and the system can deduce some restriction on the
primitive type of x from the assumption that concl holds. The last
restriction is vague but one way to understand it is to weaken it a
little to ``and concl is a non-tautological conjunction or
disjunction of the primitive type recognizers listed below.''
The primitive ACL2 types and a suitable primitive recognizing
expression for each are listed below.
type suitable primitive recognizer
zero (equal x 0)
negative integers (and (integerp x) (< x 0))
positive integers (and (integerp x) (> x 0))
negative ratio (and (rationalp x)
(not (integerp x))
(< x 0))
positive ratio (and (rationalp x)
(not (integerp x))
(> x 0))
complex rational (complex-rationalp x)
nil (equal x nil)
t (equal x t)
other symbols (and (symbolp x)
(not (equal x nil))
(not (equal x t)))
proper conses (and (consp x)
(true-listp x))
improper conses (and (consp x)
(not (true-listp x)))
strings (stringp x)
characters (characterp x)
Thus, a suitable concl to recognize the naturals would be (or (equal
x 0) (and (integerp x) (> x 0))) but it turns out that we also
permit (and (integerp x) (>= x 0)). Similarly, the true-lists could
be specified by
(or (equal x nil) (and (consp x) (true-listp x)))
but we in fact allow (true-listp x). When time permits we will
document more fully what is allowed or implement a macro that
permits direct specification of the desired type in terms of the
primitives.
There are essentially four forms of :compound-recognizer rules, as
the forms labeled (3) and (4) above are equivalent, as are those
labeled (5) and (6). We explain how such rules are used by
considering the individual forms.
Consider form (1), (implies (fn x) concl). The effect of such a rule
is that when the rewriter assumes (fn x) true, as it would while
diving through (if (fn x) xxx ...) to rewrite xxx, it restricts the
type of x as specified by concl. For example, if concl is the term
(integerp x), then when rewriting xxx, x will be assumed to be an
integer. However, when assuming (fn x) false, as necessary in (if
(fn x) ... xxx), the rule permits no additional assumptions about
the type of x. For example, if fn is primep, i.e., the predicate
that recognizes prime numbers, then (implies (primep x) (and
(integerp x) (>= x 0))) is a compound recognizer rule of the first
form. When (primep x) is assumed true, the rewriter gains the
additional information that x is a natural number. When (primep x)
is assumed false, no additional information is gained --- since x
may be a non-prime natural or may not even be a natural.
Form (2) is the symmetric case, when assuming (fn x) false permits
type restrictions on x but assuming (fn x) true permits no such
restrictions. For example, if we defined exprp to be the recognizer
for well-formed expressions for some language in which all symbols,
numbers, character objects and strings were well-formed --- e.g.,
the well-formedness rules only put restrictions on expressions
represented by [consp]s --- then the theorem (implies (not (exprp
x)) (consp x)) is a rule of the second form. Assuming (exprp x)
true tells us nothing about the type of x; assuming it false tells
us x is a [consp].
Forms (3) and (4), which are really equivalent, address themselves to
the case where one type may be deduced from (fn x) and a generally
unrelated type may be deduced from its negation. If we modified the
expression recognizer above so that character objects are illegal,
then rules of the forms (3) and (4) are
(and (implies (exprp x) (not (characterp x)))
(implies (not (exprp x)) (or (consp x) (characterp x)))).
(if (exprp x)
(not (characterp x))
(or (consp x) (characterp x)))
Finally, rules of forms (5) and (6) address the case where fn
recognizes all and only the objects whose type is described. In
these cases, fn is really just a new name for some ``compound
recognizers.'' The classic example is (booleanp x), which is just a
handy combination of two primitive types:
(iff (booleanp x) (or (equal x t) (equal x nil))).
Often it is best to disable fn after proving that it is a compound
recognizer, since otherwise the term (fn x) will be expanded and
thus disappear.
Every time you prove a new compound recognizer rule about fn it
overrides all previously proved compound recognizer rules about fn.
Thus, if you want to establish the type implied by (fn x) and you
want to establish the type implied by (not (fn x)), you must prove
a compound recognizer rule of the third, fourth, fifth, or sixth
forms. Proving a rule of the first form followed by one of the
second only leaves the second fact in the database.
Compound recognizer rules can be disabled with the effect that older
rules about fn, if any, are exposed.
If you prove more than one compound recognizer rule for a function,
you may see a warning message to the effect that the new rule is
not as ``restrictive'' as the old. That is, the new rules do not
give the rewriter strictly more type information than it already
had. The new rule is stored anyway, overriding the old, if enabled.
You may be playing subtle games with enabling or rewriting. But two
other interpretations are more likely, we think. One is that you
have forgotten about an earlier rule and should merely print it out
to make sure it says what you intend, and then discard your new
rule. The other is that you meant to give the system more
information and the system has simply been unable to extract the
intended type information from the term you placed in the
conclusion of the new rule. Given our lack of specificity in saying
how type information is extracted from rules, you can hardly blame
yourself for this problem. Sorry. If you suspect you've been burned
this way, you should rephrase the new rule in terms of the
primitive recognizing expressions above and see if the warning is
still given. It would also be helpful to let us see your example so
we can consider it as we redesign this stuff.
Compound recognizer rules are similar to :[forward-chaining] rules in
that the system deduces new information from the act of assuming
something true or false. If a compound recognizer rule were stored
as a forward chaining rule it would have essentially the same
effect as described, when it has any effect at all. The important
point is that :[forward-chaining] rules, because of their more
general and expensive form, are used ``at the top level'' of the
simplification process: we forward chain from assumptions in the
goal being proved. But compound recognizer rules are built in at
the bottom-most level of the simplifier, where type reasoning is
done.
All that said, compound recognizer rules are a rather fancy,
specialized mechanism. It may be more appropriate to create
:[forward-chaining] rules instead of :compound-recognizer rules.")
(COMPRESS1
(ARRAYS ACL2-BUILT-INS)
"Remove irrelevant pairs from a 1-dimensional array
Example Form:
(compress1 'delta1 a)
General Form:
(compress1 name alist)
where name is a symbol and alist is a 1-dimensional array, generally
named name. See [arrays] for details. Logically speaking, this
function removes irrelevant pairs from alist, possibly shortening
it. The function returns a new array, alist', with the same
[header] (including name and dimension) as alist, that, under
[aref1], is everywhere equal to alist. That is, (aref1 name alist'
i) is (aref1 name alist i), for all legal indices i. Alist' may be
shorter than alist and the non-irrelevant pairs may occur in a
different order than in alist.
Practically speaking, this function plays an important role in the
efficient implementation of [aref1]. In addition to creating the
new array, alist', compress1 makes that array the ``semantic
value'' of name and allocates a raw lisp array to name. For each
legal index, i, that raw lisp array contains (aref1 name alist' i)
in slot i. Thus, subsequent [aref1] operations can be executed in
virtually constant time provided they are given name and the alist'
returned by the most recently executed compress1 or [aset1] on
name. See [arrays].
In general, compress1 returns an alist whose [cdr] is an association
list whose keys are nonnegative integers in ascending order.
However, if the [header] specifies an :order of > then the keys
will occur in descending order, and if the :order is :none or nil
then the keys will not be sorted, i.e., compress1 is logically the
identity function (though it still attaches an array under the
hood). Note however that a [compress1] call is replaced by a hard
error if the header specifies an :order of :none or nil and the
array's length exceeds the [maximum-length] field of its [header].
Function: <compress1>
(defun
compress1 (name l)
(declare (xargs :guard (array1p name l)))
(case
(array-order (header name l))
(< (cons (header name l)
(compress11 name l 0 (car (dimensions name l))
(default name l))))
(> (cons (header name l)
(reverse (compress11 name l 0 (car (dimensions name l))
(default name l)))))
(t
(prog2$
(and
(> (length l) (maximum-length name l))
(hard-error
'compress1
\"Attempted to compress a one-dimensional array named ~
~x0 whose header specifies :ORDER ~x1 and whose ~
length, ~x2, exceeds its maximum-length, ~x3.\"
(list (cons #\\0 name)
(cons #\\1 nil)
(cons #\\2 (length l))
(cons #\\3 (maximum-length name l)))))
l))))")
(COMPRESS2
(ARRAYS ACL2-BUILT-INS)
"Remove irrelevant pairs from a 2-dimensional array
Example Form:
(compress2 'delta1 a)
General Form:
(compress2 name alist)
where name is a symbol and alist is a 2-dimensional array, generally
named name. See [arrays] for details. Logically speaking, this
function removes irrelevant pairs from alist, possibly shortening
it. The function returns a new array, alist', with the same
[header] (including name and dimension) as alist, that, under
[aref2], is everywhere equal to alist. That is, (aref2 name alist'
i j) is (aref2 name alist i j), for all legal indices i and j.
Alist' may be shorter than alist and the non-irrelevant pairs may
occur in a different order in alist' than in alist.
Practically speaking, this function plays an important role in the
efficient implementation of [aref2]. In addition to creating the
new array, alist', compress2 makes that array the ``semantic
value'' of name and allocates a raw lisp array to name. For all
legal indices, i and j, that raw lisp array contains (aref2 name
alist' i j) in slot i,j. Thus, subsequent [aref2] operations can be
executed in virtually constant time provided they are given name
and the alist' returned by the most recently executed compress2 or
[aset2] on name. See [arrays].
Function: <compress2>
(defun compress2 (name l)
(declare (xargs :guard (array2p name l)))
(cons (header name l)
(compress21 name l 0 (car (dimensions name l))
(cadr (dimensions name l))
(default name l))))")
(COMPUTED-HINTS
(HINTS)
"Computing advice to the theorem proving process
General Form of :hints:
(hint1 hint2 ... hintk)
Each element, hinti, must be either a common hint or a computed hint.
A common hint is of the form
(goal-spec :key1 val1 ... :keyn valn)
where goal-spec is as specified in [goal-spec] and each :keyi and
vali is as specified in [hints]. Among the ``common hints'' we
include both the primitive hints and user-defined custom keyword
hints (see [custom-keyword-hints]).
A computed hint may be a function symbol, fn, of three, four or seven
arguments. Otherwise, a computed hint is a term with the following
properties:
(a) the only free variables allowed in the term are ID, CLAUSE,
WORLD, STABLE-UNDER-SIMPLIFICATIONP, HIST, PSPV, CTX, and [state];
(b) the output signature of the term is either (MV * * STATE), which
is to be treated as an error triple (see below), or is *, denoting
a single non-[stobj] value; and
(c) in the former case of (b) above, the term is single-threaded in
[state].
If a computed hint is a function symbol fn, whose arity n is
therefore three, four, or seven, then it is treated as the term
resulting from applying that fn to the first n variables shown in
(a) above. Notice that it must then return a single non-[stobj]
value, not an error triple, since state is not one of the first
seven variables shown in (a).
Note: Error triples are an ACL2 idiom for implementing ``errors'';
see [error-triple]. If a computation returns (mv erp val state) in
a context in which ACL2 is respecting the error triple convention
(see [ld-error-triples] and see [ld-error-action]), then an error
is deemed to have occurred if erp is non-nil. The computation is
expected to have printed an appropriate error message to [state]
and further computation is aborted. On the other hand, if a
computation returns an error triple in which erp is nil, then
``value'' of the computation is taken to be the second component,
val, of the triple (along with the possibly modified [state]), and
computation continues. For more information about programming with
error triples, see [programming-with-state].
The function symbol cases are treated as abbreviations of the term
(fn ID CLAUSE WORLD), (fn ID CLAUSE WORLD
STABLE-UNDER-SIMPLIFICATIONP), or (fn ID CLAUSE WORLD
STABLE-UNDER-SIMPLIFICATIONP HIST PSPV CTX) as appropriate for the
arity of fn. (Note that this tells you which argument of fn is
which.) Moreover, in these cases the value returned must be a
single ordinary (non-[stobj]) value, not an error triple. In the
discussion below we assume all computed hints are of the term form.
Indeed, we almost assume all computed hints are of the 3 and 4
argument forms. We only comment briefly on the 7 argument form in
[using-computed-hints-8].
The semantics of a computed hint term is as follows. On every
subgoal, the term is evaluated in an environment in which the
variables mentioned in (a) above are bound to context-sensitive
values explained below. Either the computed hint signals an error,
in which the proof attempt aborts, or else it returns a value, val
and a new state, [state]. Any changes to those parts of [state]
that affect logical soundness are undone; more specifically, the
values of symbols (sometimes called ``state global variables'') in
the list *protected-system-state-globals* in the global table of
the state (see [state]) are restored when changed during
evaluation. The value, val, of a non-erroneous computed hint
calculation is either nil, which means the computed hint did not
apply to the subgoal in question, or it is an alternating list of
:keyi vali pairs as specified in [hints]. With one exception, those
new hints are applied to the given subgoal as though the user had
typed them explicitly.
The exception is that the first keyword in the returned val is
allowed to be :COMPUTED-HINT-REPLACEMENT. Its value should be nil,
t, or a list of terms. If this keyword is not present, the default
value of nil is provided. We explain :COMPUTED-HINT-REPLACEMENT
below.
The evaluation of a hint term is done with guard checking turned off
(see [set-guard-checking]); e.g., the form (car 23) in a computed
hint returns nil as per the axioms.
When a non-nil value is returned, the keyword/value pairs (other than
the optional :COMPUTED-HINT-REPLACEMENT) are used as the hint for
the subgoal in question. Thus, your job as the programmer of
computed hints is either to cause an error, typically by invoking
[er], or to return a non-erroneous value triple whose value is the
list of keys and values you would have typed had you supplied a
common hint for the subgoal. (In particular, any theory expressions
in it are evaluated with respect to the global current-theory, not
whatever theory is active at the subgoal in question.) If the
generated list of keywords and values is illegal, an error will be
signaled and the proof attempt will be aborted.
The purpose of the :COMPUTED-HINT-REPLACEMENT keyword and its value,
chr, is to change the list of hints. If chr is nil, then the hint
which was applied is removed from the list of hints that is passed
down to the children of the subgoal in question. This is the
default. If chr is t, then the hint is left in the list of hints.
This means that the same hint may act on the children of the
subgoal. Otherwise, chr must be a list of terms, each of which is
treated as a computed hint. The hint which was applied is deleted
from the list of hints and the hints in chr are added to the list
of hints passed to the children of the subgoal. The ability to
compute new hints and pass them down allows strange and wonderful
behavior.
For these purposes, the goals produced by induction and the top-level
goals of forcing rounds are not considered children; all original
hints are available to them.
Only the first hint applicable to a goal, as specified in the
user-supplied list of :hints followed by the [default-hints-table],
will be applied to that goal. (For an advanced exception, see
[override-hints].)
It remains only to describe the bindings of the free variables.
Suppose the theorem prover is working on some clause, clause, named
by some [goal-spec], e.g., \"Subgoal *1/2'''\" in some logical world,
world. Corresponding to the printed goal-spec is an internal data
structure called a ``clause identifier'' id. See
[clause-identifier].
In the case of a common hint, the hint applies if the goal-spec of
the hint is the same as the goal-spec of the clause in question.
In the case of a computed hint, the variable ID is bound to the
clause id, the variable CLAUSE is bound to the (translated form of
the) clause, and the variable WORLD is bound to the current ACL2
world. The variable STABLE-UNDER-SIMPLIFICATIONP is bound to t or
nil. It is bound to t only if the clause is known to be stable
under simplification. That is, the simplifier has been applied to
the clause and did not change it. Such a clause is sometimes known
as a ``simplification checkpoint.'' It is frequently useful to
inject hints (e.g., to enable a rule or provide a :use hint) only
when the goal in question has stabilized. If a hint is provided,
the processing of the clause starts over with simplification.
As for CTX and [state], they are provided so that you can pass them
to the [er] macro to print error messages. We recommend not writing
computed hints that otherwise change [state]!
The remaining variables, HIST and PSPV are not documented yet. Only
users familiar with the internals of ACL2 are likely to need them
or understand their values.
For some instruction about how to use computed hints, see
[using-computed-hints].
Subtopics
[Using-computed-hints]
How to use computed hints")
(CONCATENATE
(LISTS STRINGS ACL2-BUILT-INS)
"Concatenate lists or strings together
Examples:
(concatenate 'string \"ab\" \"cd\" \"ef\") ; equals \"abcdef\"
(concatenate 'string \"ab\") ; equals \"ab\"
(concatenate 'list '(a b) '(c d) '(e f)) ; equals '(a b c d e f)
(concatenate 'list) ; equals nil
General Form:
(concatenate result-type x1 x2 ... xn)
where n >= 0 and either: result-type is '[string] and each xi is a
string; or result-type is '[list] and each xi is a true list.
Concatenate simply concatenates its arguments to form the result
string or list. Also see [append] and see [string-append]. (The
latter immediately generates a call to concatenate when applied to
strings.)
Note: We do *not* try to comply with the Lisp language's insistence
that concatenate copies its arguments. Not only are we in an
applicative setting, where this issue shouldn't matter for the
logic, but also we do not actually modify the underlying lisp
implementation of concatenate; we merely provide a definition for
it.
Concatenate is a Common Lisp function. See any Common Lisp
documentation for more information.
Macro: <concatenate>
(defmacro concatenate
(result-type &rest sequences)
(declare (xargs :guard (or (equal result-type ''string)
(equal result-type ''list))))
(cond ((equal result-type ''string)
(cond ((and sequences (cdr sequences)
(null (cddr sequences)))
(list 'string-append
(car sequences)
(cadr sequences)))
(t (list 'string-append-lst
(cons 'list sequences)))))
((endp sequences) nil)
(t (cons 'append
(append sequences (list nil))))))")
(COND
(BASICS ACL2-BUILT-INS)
"Conditional based on if-then-else
Cond is the construct for IF, THEN, ELSE IF, ... The test is against
nil. The argument list for cond is a list of ``clauses'', each of
which is a list. In ACL2, clauses must have length 1 or 2.
Cond is a Common Lisp macro. See any Common Lisp documentation for
more information.
Macro: <cond>
(defmacro cond (&rest clauses)
(declare (xargs :guard (cond-clausesp clauses)))
(cond-macro clauses))
Function: <cond-macro>
(defun cond-macro (clauses)
(declare (xargs :guard (cond-clausesp clauses)))
(if (consp clauses)
(if (and (eq (car (car clauses)) t)
(eq (cdr clauses) nil))
(if (cdr (car clauses))
(car (cdr (car clauses)))
(car (car clauses)))
(if (cdr (car clauses))
(list 'if
(car (car clauses))
(car (cdr (car clauses)))
(cond-macro (cdr clauses)))
(list 'or
(car (car clauses))
(cond-macro (cdr clauses)))))
nil))")
(CONGRUENCE
(RULE-CLASSES)
"The relations to maintain while simplifying arguments
See [rule-classes] for a general discussion of rule classes and how
they are used to build rules from formulas. An example :[corollary]
formula from which a :congruence rule might be built, assuming that
set-equal is a known [equivalence] relation, is:
Example:
(defthm set-equal-implies-iff-memb-2
(implies (set-equal x y)
(iff (memb e x) (memb e y)))
:rule-classes :congruence)
Also see [defcong] and see [equivalence].
NOTE: This topic discusses so-called ``classic'' congruence rules. A
more general class of rules, so-called ``patterned'' congruence
rules, is supported. We discuss only classic congruence rules
below; for a discussion of patterned congruence rules, first read
the present topic and then see [patterned-congruence].
General Form:
(implies (equiv1 xk xk-equiv)
(equiv2 (fn x1... xk ...xn)
(fn x1... xk-equiv ...xn)))
where equiv1 and equiv2 are known equivalence relations, fn is an
n-ary function symbol other than if, and the xi and xk-equiv are
all distinct variables. The effect of such a rule is to record that
the equiv2-equivalence of fn-expressions can be maintained if,
while rewriting the kth argument position, equiv1-equivalence is
maintained. See [equivalence] for a general discussion of the
issues. We say that equiv2, above, is the ``outside equivalence''
in the rule and equiv1 is the ``inside equivalence for the kth
argument.''
The macro form (defcong equiv1 equiv2 (fn x1 ... x1) k) is an
abbreviation for a [defthm] of rule-class :congruence that attempts
to establish that equiv2 is maintained by maintaining equiv1 in
fn's kth argument. The [defcong] macro automatically generates the
general formula shown above. See [defcong].
The memb example above tells us that (memb e x) is propositionally
equivalent to (memb e y), provided x and y are set-equal. The
outside equivalence is [iff] and the inside equivalence for the
second argument is set-equal. If we see a memb expression in a
propositional context, e.g., as a literal of a clause or test of an
[if] (but not, for example, as an argument to [cons]), we can
rewrite its second argument maintaining set-equality. For example,
a rule stating the commutativity of [append] (modulo set-equality)
could be applied in this context. Since equality is a refinement of
all equivalence relations, all equality rules are always available.
See [refinement].
All known :congruence rules about a given outside equivalence and fn
can be used independently. That is, consider two :congruence rules
with the same outside equivalence, equiv, and about the same
function fn. Suppose one says that equiv1 is the inside equivalence
for the first argument and the other says equiv2 is the inside
equivalence for the second argument. Then (fn a b) is equiv (fn a'
b') provided a is equiv1 to a' and b is equiv2 to b'. This is an
easy consequence of the transitivity of equiv. It permits you to
think independently about the inside equivalences.
Furthermore, it is possible that more than one inside equivalence for
a given argument slot will maintain a given outside equivalence.
For example, (length a) is equal to (length a') if a and a' are
related either by list-equal or by [string-equal]. You may prove
two (or more) :congruence rules for the same slot of a function.
The result is that the system uses a new, ``generated'' equivalence
relation for that slot with the result that rules of both (or all)
kinds are available while rewriting.
:Congruence rules can be disabled. For example, if you have two
different inside equivalences for a given argument position and you
find that the :[rewrite] rules for one are unexpectedly preventing
the application of the desired rule, you can disable the rule that
introduced the unwanted inside equivalence.
Remark on Replacing IFF by EQUAL. You may encounter a warning
suggesting that a congruence rule ``can be strengthened by
replacing the second equivalence relation, IFF, by EQUAL.'' Suppose
for example that this warning occurs when you submit the following
rule:
(defcong equiv1 iff (fn x y) 2)
which is shorthand for the following:
(defthm equiv1-implies-iff-fn-2
(implies (equiv1 y y-equiv)
(iff (fn x y) (fn x y-equiv)))
:rule-classes (:congruence))
The warning is telling you that ACL2 was able to deduce that fn
always returns a Boolean, and hence a trivial but useful
consequence is obtained by replacing [iff] by [equal] ---
(defcong equiv1 equal (fn x y) 2)
--- which is shorthand for the following:
(defthm equiv1-implies-equal-fn-2
(implies (equiv1 y y-equiv)
(equal (fn x y) (fn x y-equiv)))
:rule-classes (:congruence))
If you have difficulty proving the latter directly, you can derive it
from the former by giving a suitable hint, minimally as follows.
(defcong equiv1 equal (fn x y) 2
:hints ((\"Goal\"
:use equiv1-implies-iff-fn-2
:in-theory
(union-theories '((:type-prescription fn))
(theory 'minimal-theory)))))
By heeding this warning, you may avoid unnecessary [double-rewrite]
warnings later. We now explain why, but see [double-rewrite] for
relevant background material.
For example, suppose you have proved the ``iff'' version of the
congruence rule above, and later you submit the following rewrite
rule.
(defthm equal-list-perm
(implies (equiv1 x y)
(fn x y)))
Since fn is known to return a Boolean, ACL2 performs an optimization
that stores this rule as though it were the following.
(defthm equal-list-perm
(implies (equiv1 x y)
(equal (fn x y) t)))
Thus, if ACL2's rewriter sees a term (fn a b) in a context where the
equivalence relation [iff] is not being maintained, then it cannot
use rule equiv1-implies-iff-fn-2, so it rewrites argument a without
the benefit of knowing that it suffices to maintain equiv1; and
then it caches the result. When ACL2 subsequently attempts to
relieve the hypothesis (equiv1 x y), it will rewrite x simply by
returning the rewritten value of a from the result cache. This is
unfortunate if a could have been rewritten more completely under
maintainance of the equivalence relation equiv1 --- which is legal
in the hypothesis since a is an argument of equiv1, which is an
[equivalence] relation. The user who observes the warning from rule
equiv1-implies-iff-fn-2, and replaces it with
equiv1-implies-equal-fn-2, will avoid this unfortunate case.")
(CONJUGATE
(NUMBERS ACL2-BUILT-INS)
"Complex number conjugate
Conjugate takes an ACL2 number as an argument, and returns its
complex conjugate (i.e., the result of negating its imaginary
part.).
Conjugate is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <conjugate>
(defun conjugate (x)
(declare (xargs :guard (acl2-numberp x)))
(if (complex/complex-rationalp x)
(complex (realpart x) (- (imagpart x)))
x))")
(CONS
(CONSES ACL2-BUILT-INS)
"Pair and list constructor
(cons x y) is a pair whose first component is x and second component
is y. If y is a list, then (cons x y) is a list that has an
additional element x on the front.")
(CONS-SUBTREES
(FAST-ALISTS ACL2-BUILT-INS)
"Build a fast alist whose keys are the subtrees of X
(cons-subtrees x nil) builds a fast alist that associates each
subtree of X with T, without duplication.
Function: <cons-subtrees>
(defun
cons-subtrees (x al)
(declare (xargs :guard t))
(cond ((atom x) al)
((hons-get x al) al)
(t (cons-subtrees (car x)
(cons-subtrees (cdr x)
(hons-acons x t al))))))")
(CONSERVATIVITY-OF-DEFCHOOSE
(DEFCHOOSE)
"Proof of conservativity of [defchoose]
This documentation topic provides underlying theory. It is of
theoretical interest only; it has no relationship to the effective
use of ACL2.
The argument below for the conservativity of [defchoose] replaces the
terse and somewhat misleading reference to a forcing argument in
Appendix B of the paper by ACL2 authors Kaufmann and Moore,
``Structured Theory Development for a Mechanized Logic'' (Journal
of Automated Reasoning 26, no. 2 (2001), pp. 161-203).
Our basic idea is to to take a (countable) first-order structure for
ACL2, M, together with a function symbol, f, introduced by
[defchoose], and find a way to expand M with an interpretation of f
(without changing the universe of M) so that e0-induction continues
to hold in the expansion. A remark at the end of this documentation
topic shows why care is necessary. A concept called ``forcing'',
originally introduced by Paul Cohen for set theory, has long since
been adapted by logicians (in a simplified form) to model theory.
This simplified model-theoretic forcing provides the means for
making our careful expansion.
The forcing argument presented below is intended to be completely
self-contained for those familiar with basic first-order logic and
ACL2; in particular, see [defchoose]. No background in forcing
(model-theoretic or otherwise) is expected, though we do expect a
rudimentary background in first-order logic and familiarity with
the following.
Preliminaries. We write s[p<-p0] to denote the result of extending or
modifying the assignment s by binding p to p0. Now let A be a
subset of the universe U of a first-order structure M. A is said to
be ``first-order definable with parameters'' in M if for some
formula phi, variable x, and assignment s binding the free
variables of phi except perhaps for x, A = {a \\in U: M |=
phi[s[x<-a]]}. Note that we are writing ``\\in'' to denote set
membership. Finally, we indicate the end of a proof (or of a
theorem statement, when the proof is omitted) with the symbol
``-|''.
We gratefully acknowledge very helpful feedback from John Cowles, who
found several errors in a draft of this note and suggested the
exercises. We also thank Ruben Gamboa for helpful feedback, and we
thank Jim Schmerl for an observation that led us directly to this
proof in the first place.
We are given a consistent first-order theory T, extending the ACL2
ground-zero theory, that satisfies the e0-induction scheme. We wish
to show that the extension of T by the following arbitrary
defchoose event is conservative, where g is a new function symbol.
(defchoose g <bound-vars> <free-vars> <body>)
Note that by ``the extension of T'' here we mean the extension of T
by not only the new defchoose axiom displayed just below, but also
the addition of e0-induction axioms for formulas in the expanded
language obtained by including the new defchoose function symbol,
g.
<body> -> (LET <bound-vars> = g(<free-vars>) in <body>)
By definition of conservativity, since proofs are finite, it clearly
suffices to consider an arbitrary finite subset of T. Then by the
completeness, soundness, and downward Lowenheim-Skolem theorems of
first-order logic, it suffices to show that an arbitrary countable
model of T can be expanded (i.e., by interpreting the new symbol g
without changing the universe of the model) to a model of the
corresponding defchoose axiom above, in which all e0-induction
axioms hold in the language of that model (i.e., the expanded
language).
Below, we will carry out a so-called forcing construction, which
allows us to expand any countable model M of T to a model M[G] for
the expanded language that satisfies e0-induction (in the expanded
language) and also satisfies the axiom displayed above, generated
from the defchoose event. The ideas in this argument are standard
in model theory; no novelty is claimed here.
Fix a countable model M of a theory T that satisfies e0-induction for
its countable language and extends the ACL2 ground-zero theory.
Also fix the above defchoose axiom, where g is not in the language
of T.
We start by defining a partial order P as follows. Let Nb and Nf be
the lengths of <bound-vars> and <free-vars>, respectively. P
consists of all fn in M such that the following formula is true in
M. Roughly speaking, it says that fn is a finite function that
witnesses, on its domain, the requirement above for g.
alistp(fn) &
no-duplicatesp-equal(strip-cars(fn)) &
(forall <bound-vars>, <free-vars> .
(member-equal(cons(<free-vars>,<bound-vars>), fn) ->
(length(<bound-vars>) = Nb &
length(<free-vars>) = Nf &
((exists <bound-vars> . <body>) ->
(LET <bound-vars> = g(<free-vars>) in <body>)))))
P is ordered by subset, i.e., we say that p2 extends p1 if p1 is a
subset (not necessarily proper) of p2 (more precisely, M |=
subsetp-equal(p1,p2)).
Remark. The original argument in Appendix B of the aforementioned
paper can essentially be salvaged, as we now show. The key
observation is that the particular choice of P is nearly irrelevant
for the argument that follows below. In particular, we can instead
define P to consist of finite one-one functions with domain
contained in the set of natural numbers. More precisely, consider
the following definitions.
(defun function-p (fn)
(and (alistp fn)
(no-duplicatesp-equal (strip-cars fn))))
(defun nat-function-p (x)
(and (function-p x)
(nat-listp (strip-cars x))))
and define an inverse function on alists as follows.
(defun inverse (fn)
(if (endp fn)
nil
(cons (cons (cdar fn) (caar fn))
(inverse (cdr fn)))))
Then P may instead be defined to consist of those fn for which
nat-function-p(fn) & function-p(inverse(fn)). With this alternate
definition of P, the argument below then goes through virtually
unchanged, and we get an expansion M[G] of M in which there is a
definable enumeration of the universe. The conservativity of
defchoose then follows easily because the function being introduced
can be defined explicitly using that enumeration (namely, always
pick the least witness in the sense of the enumeration).
End of Remark.
Next we present the relevant forcing concepts from model theory.
A dense subset of P is a subset D of P such that for every p \\in P,
there is d \\in D such that d extends p. A subset G of P is generic
with respect to a collection Ds of dense subsets of P, also written
``G is Ds-generic,'' if G is closed under subset (if p2 \\in G and
p2 extends p1 then p1 \\in G), G is pairwise compatible (the
union-equal of any two elements of G is in G), and every set in Ds
has non-empty intersection with G.
For p \\in P, we say that a subset D of P is dense beyond p if for all
p1 extending p there exists p2 extending p1 such that p2 \\in D.
This notion makes sense even for D not a subset of P if we treat
elements of D not in P as nil.
Proposition 1. For any partial order P and countable collection Ds of
dense subsets of P, there is a Ds-generic subset of P.
Proof. Let Ds = {D0,D1,D2,...}. Define a sequence <p_0,p_1,...> such
that for all i, p_i \\in Di and p_(i+1) extends p_i. Let G = {p \\in
P: for some i, pi extends p}. Then G is Ds-generic. -|
Note that P is first-order definable (with parameters) in M. Let Df
be the set of dense subsets of P that are first-order definable
(with parameters) in M. A standard argument shows there are only
countably many first-order definitions with parameters in a
countable model M whose language is countable --- for example, we
can Goedel number all terms and then all formulas --- hence, Df is
countable.
By Proposition 1, let G be Df-generic. Notice that for any list x of
length Nf in M, the set of elements f of P for which x is in the
domain of f is dense and first-order definable. We may thus define
a function g0 as follows: g0(x_1,...,x_Nf) = y if there is some
element of G containing the pair ((x_1 ... x_Nf) . y). It is easy
to see that g0 is a total function on M. Let L be the language of T
and let L[g] be the union of L with a set containing a single new
function symbol, g. Let M[G] be the expansion of M to L[g] obtained
by interpreting g to be g0 (see also Proposition 5 below).
So now we have fixed M, P, Df, G, and g0, where G is Df-generic.
Proposition 2. Let Df be the set of dense subsets of P that are
first-order definable (with parameters) in M. Suppose that p \\in G
and D \\in Df. Then for some q \\in G extending p, q \\in D.
Proof. Let D0 be the set of p' \\in D that either extend p or have no
extension in D that extends p. We leave it as a straightforward
exercise to show that D0 is dense, and D0 is clearly first-order
definable (with parameters) in M. So by genericity of G, we may
pick q \\in D0 such that q \\in G. Thus q \\in D. By definition of
generic, some extension q1 of both p and q belongs to G. Pick q2
\\in D extending q1; thus q has an extension in D that extends p
(namely, q2), so by definition of D0, q extends p. -|
Definition of forcing. Let phi(x1,...,xk) be a first-order formula in
L[g] and let p \\in P. We define a formula of L, denoted ``p ||-
phi'' (``p forces phi''), by recursion on phi (in the metatheory)
as follows. (Here, we view ``or'' and ``forall'' as abbreviations.)
If phi is atomic, then let phi'(A) be the result of replacing,
inside-out, each subterm of the form g(x_1,...,x_Nb) with the
term (cdr (assoc-equal (list x_1 ... x_Nb) A)), where A is
neither p nor a variable occurring in phi. Then p ||- phi is
defined as follows: ``The set {A \\in P: A extends p and
phi'(A)} is dense beyond p''. That is, p ||- phi is the
following formula:
(forall p1 \\in P extending p)
(exists p2 \\in P extending p1) phi'(p2).
p ||- ~phi is: (forall p' \\in P extending p) ~(p' ||- phi)
p ||- phi_1 & phi_2 is: (p ||- phi_1) & (p ||- phi_2)
p ||- (exists x) phi is: (exists x) (p ||- phi)
We will need the following definition later.
Definition. p ||-w phi (p weakly forces phi) is an abbreviation for p
||- ~~phi.
The following exercises were suggested by John Cowles as a means for
gaining familiarity with the definition of forcing.
Exercise 1. Consider the formula (phi_1 OR phi_2) as an abbreviation
for ~(~phi_1 & ~phi_2), Show that p ||- (phi_1 OR phi_2) is
equivalent to the following.
(forall p' \\in P extending p) (exists p'' \\in P extending p')
((p'' ||- phi_1) OR (p'' ||- phi_2))
Exercise 2. Consider the formula (forall x)phi as an abbreviation for
~(exists x)~phi, Show that p ||- (forall x)phi is equivalent to the
following.
(forall x)
(forall p1 \\in P extending p)
(exists p2 \\in P extending p1) (p2 ||- phi).
Exercise 3. Prove that p ||-w phi is equivalent to the following.
(forall p' \\in P extending p)
(exists p'' \\in P extending p') (p'' ||- phi).
Exercise 4. Let phi be a formula of L[g]. Prove: M |= (p ||-
phi)[s[p<-p0]] implies M |= (p ||-w phi)[s[p<-p0]].
Exercise 5. Let phi be a formula of L[g]. Prove: M |= (p ||-
~phi)[s[p<-p0]] iff M |= (p ||-w ~phi)[s[p<-p0]].
[End of exercises.]
The definition of forcing stipulates how to view ``p ||-
phi(x1,...,xk)'' as a new formula theta(p,x1,...,xk). That is,
``||-'' transforms formulas, so for any first-order formula phi,
``p ||- phi'' is just another first-order formula. That observation
shows that a formula such as ((p ||- phi) OR (p ||- ~phi)) is
really just another first-order formula. The following proposition
thus follows easily.
Proposition 3. For any formula phi of L[g], {p0: M |= ((p ||- phi) OR
(p ||- ~phi))[s[p<-p0]]]} is a dense subset of P, which (since it
is first-order definable with parameters in M) intersects G. -|
The following proposition is easily proved by a structural induction
on phi, and is left to the reader.
Proposition 4. Let phi be a formula of L[g]. Suppose p0 \\in P, p1 \\in
P,
M |= (p ||- phi)[s[p<-p0]],
and p1 extends p0. Then
M |= (p ||- phi)[s[p<-p1]]. -|
We will also need the following.
Proposition 5. The following is dense for any finite set S of
Nf-tuples: {p \\in P: for some <x_1 ... x_Nf> \\in S, (list x_1 ...
x_Nf) \\in strip-cars(p)}. Thus, the function g0 is a total
function. -|
The next lemma tells us that the sentences true in M[G] are those
that are forced by an element of G.
Truth Lemma. Let phi be a formula in L[g], let s be an assignment to
the free variables of phi, and let p be a variable not in the
domain of s. Then M[G] |= phi[s] iff for some p0 \\in G, M |= (p ||-
phi)[s[p<-p0]].
Proof. The proof is by induction on the structure of phi. First
suppose phi is atomic. Let D* be the set of elements p0 \\in P such
that every assoc-equal evaluation from the definition of forcing
phi returns a pair when A is bound to p0. (Intuitively, this means
that p0 is a sufficiently large approximation from any G containing
p0 to make sense of phi in M[G].) We make the following claim.
(*) For all p0 \\in G such that p0 \\in D*,
M[G] |= phi[s] iff M |= (p ||- phi)[s[p<-p0]].
To prove the claim, fix p0 in both G and D*, and recall the function
g0 constructed from G in the definition of M[G]. Suppose that t_1,
..., t_Nf are terms and g(t_1, ..., t_Nf) is a subterm of phi. Then
s assigns a value in M to each of the t_i. Let a_i be the value
assigned by s to t_i. Then g0(a_1, ..., a_Nf) = (cdr (assoc-equal
(list a_1 ... a_Nf) p0)), as the assoc-equal is a pair (since p0
\\in D*) and has the indicated value (because p0 \\in G). It follows
by the definition of formula phi' in the definition of forcing:
M[G] |= phi[s] iff M |= phi'(p)[s[p<-p0]]
Moreover, because p0 \\in D* it is clear that this holds if p0 is
replaced by an arbitrary extension of p0. Then (*) easily follows.
By Proposition 5, D* is dense, so there is some p0 in the
intersection of D* and G. The forward direction of the conclusion
then follows by (*). The reverse direction is clear from (*) by
application of Proposition 2 to D* and Proposition 4.
Next, suppose M[G] |= ~phi[x]. Then it is not the case that M[G] |=
phi, so by the inductive hypothesis, there is no p0 \\in G for which
M |= (p ||- phi)[s[p<-p0]]. By Proposition 3, there is p0 \\in G for
which M |= (p ||- ~phi)[s[p<-p0]]. For the other direction, suppose
it is not the case that M[G] |= ~phi[s]. So M[G] |= phi[s], and by
the inductive hypothesis, there is p0 \\in G for which M |= (p ||-
phi)[s[p<-p0]]. It follows that there is no p1 \\in G for which M |=
(p ||- ~phi)[s[p<-p1]], since from such p1 we can find a common
extension p2 of p0 and p1 (since G is generic), and since p2
extends p0 then by Proposition 4, M |= (p ||- phi)[s[p<-p2]],
contradicting (by definition of forcing) M |= (p ||-
~phi)[s[p<-p1]] since p2 extends p1.
The case (phi_1 & phi_2) follows easily from the inductive
hypothesis. For the forward direction, apply Proposition 4 and the
observation that by genericity, if p0 \\in G and p1 \\in G then p0
and p1 they have a common extension in G.
Finally, the case (exists x) phi follows trivially from the inductive
hypothesis. -|
Truth Lemma Corollary. The Truth Lemma holds with ||-w replacing ||-.
Proof. This is clear by applying the Truth Lemma to ~~phi. -|
Here is our main theorem. Recall that all first-order theories in our
ACL2 context satisfy the e0-induction scheme.
Theorem. M[G] satisfies e0-induction.
Proof. We consider an arbitrary instance of e0-induction in L[g],
stated using a strict well-founded relation <| and a formula phi.
We write phi(y) to indicate that y may be among the free variables
of phi, and phi(y<-x) to denote the result of substituting x for y
in phi.
theta: (forall y) [((forall x <| y) phi(y<-x)) -> phi(y)]
-> (forall y) phi(y)
Our goal is to prove that theta holds in M[G].
Below, we abuse notation by leaving assignments implicit and by
writing ``p ||- phi(y0)'' to signify that the formula (p ||-
phi(y)) is true in M under the extension of the explicit assignment
that binds y to y0. We believe that the intended meaning will be
clear.
Consider the following set D.
D = {p \\in P: either p ||-w phi(y0) for all y0,
or else
for some y0, p ||- ~phi(y0) and
for all y1 <| y0 p ||-w phi(y1)}.
The set D is clearly first-order definable (with parameters) in M. We
claim that D is a dense subset of P. For suppose p0 \\in P; we find
p1 \\in D extending p0, as follows. If p0 ||-w phi(y0) for all y0,
then we may take p1 to be p0. Otherwise, by definition of ||-w and
||-, there is some y0 such that for some extension p0' of p0, p0'
||- ~phi(y0). Pick a <|-minimal such y0, and correspondingly pick
p1 so that p1 extends p0 and p1 ||- ~phi(y0). In order to show that
p1 \\in D, it remains to show that for all y1 <| y0, p1 ||-w
phi(y1), i.e., there is no q extending p1 such that q ||- ~phi(y1).
This is indeed the case since otherwise q and y1 would contradict
the <|-minimality of y0.
Applying the genericity of G and just-proved density of D, pick p0
\\in G such that p0 \\in D. If p0 ||-w phi(y0) for all y0, then by
the Truth Lemma Corollary, M[G] |= phi(y0) for all y0, and thus
M[G] |= theta. Otherwise, since p0 \\in D we may choose y0 such that
p0 ||- ~phi(y0) and for all y1 <| y0, p0 ||-w phi(y1). By the Truth
Lemma and its corollary, since p0 \\in G we have:
(1) M[G] |= ~phi(y0).
(2) For all y1 <| y0, M[G] |= phi(y1).
It follows that the antecedent of theta is false in M[G], as
witnessed by y = y0; thus M[G] |= theta. -|
Remark. We close by returning, as promised above, to the question of
why so much care is necessary in constructing an expansion of M. We
assume familiarity here with the notion of a ``non-standard''
natural number of M, i.e., one that is greater than the
interpretation of any term that has the form (+ 1 1 1 ... 1). Here
is a very simple example that illustrates the need for some care.
Consider the following event, which introduces a function foo with
the following property: for all x, if natp(x) then natp(foo(x)).
(defchoose foo (y) (x)
(implies (natp x) (natp y)))
Certainly we can build a model of the above property from a model M
of the ground-zero theory, by interpreting foo so that for all x
for which M satisfies natp(x), foo(x) is also a natp in M. But
suppose we start with a non-standard model M of the ground-zero
theory, and we happen to define foo(x) to be 1 for all non-standard
natural numbers x and 0 for all other x. The resulting expansion of
M will not satisfy the e0-induction scheme or even the ordinary
natural number induction scheme: foo(0)=0 holds in that expansion
as does the implication foo(n)=0 => foo(n+1)=0 for every natural
number n of M, standard or not; and yet foo(k)=0 fails for every
non-standard natural number k of M.")
(CONSES
(PROGRAMMING)
"A cons is an ordered pair. In ACL2, data structures like [lists],
[alists], etc., are made up of conses.
Subtopics
[Atom]
Recognizer for atoms
[Caaaar]
[car] of the [caaar]
[Caaadr]
[car] of the [caadr]
[Caaar]
[car] of the [caar]
[Caadar]
[car] of the [cadar]
[Caaddr]
[car] of the [caddr]
[Caadr]
[car] of the [cadr]
[Caar]
[car] of the [car]
[Cadaar]
[car] of the [cdaar]
[Cadadr]
[car] of the [cdadr]
[Cadar]
[car] of the [cdar]
[Caddar]
[car] of the [cddar]
[Cadddr]
[car] of the [cdddr]
[Caddr]
[car] of the [cddr]
[Cadr]
[car] of the [cdr]
[Car]
Returns the first element of a non-empty list, else nil
[Cdaaar]
[cdr] of the [caaar]
[Cdaadr]
[cdr] of the [caadr]
[Cdaar]
[cdr] of the [caar]
[Cdadar]
[cdr] of the [cadar]
[Cdaddr]
[cdr] of the [caddr]
[Cdadr]
[cdr] of the [cadr]
[Cdar]
[cdr] of the [car]
[Cddaar]
[cdr] of the [cdaar]
[Cddadr]
[cdr] of the [cdadr]
[Cddar]
[cdr] of the [cdar]
[Cdddar]
[cdr] of the [cddar]
[Cddddr]
[cdr] of the [cdddr]
[Cdddr]
[cdr] of the [cddr]
[Cddr]
[cdr] of the [cdr]
[Cdr]
Returns the second element of a [cons] pair, else nil
[Cons]
Pair and list constructor
[Consp]
Recognizer for [cons] pairs
[Listp]
Recognizer for (not necessarily proper) lists
[Subst]
A single substitution into a tree")
(CONSP
(CONSES ACL2-BUILT-INS)
"Recognizer for [cons] pairs
(consp x) is true if and only if x is a [cons] pair.")
(CONSTRAINT
(ENCAPSULATE)
"Restrictions on certain functions introduced in [encapsulate]
[events]
Suppose that a given theorem, thm, is to be functionally instantiated
using a given functional substitution, alist. (See
[lemma-instance], or for an example, see
[functional-instantiation-example].) What is the set of proof
obligations generated? It is the set obtained by applying alist to
all terms, tm, such that (a) tm mentions some function symbol in
the domain of alist, and (b) either (i) tm arises from the
``constraint'' on a function symbol ancestral in thm or in some
[defaxiom] or (ii) tm is the body of a [defaxiom]. Here, a function
symbol is ``ancestral'' in thm if either it occurs in thm, or it
occurs in the definition of some function symbol that occurs in
thm, and so on.
The remainder of this note explains what we mean by ``constraint'' in
the words above.
In a certain sense, function symbols are introduced in essentially
two ways. The most common way is to use [defun] (or when there is
mutual recursion, [mutual-recursion] or [defuns]). There is also a
mechanism for introducing ``witness functions''; see [defchoose].
The documentation for these [events] describes the axioms they
introduce, which we will call here their ``definitional axioms.''
These definitional axioms are generally the constraints on the
function symbols that these axioms introduce.
However, when a function symbol is introduced in the scope of an
[encapsulate] event, its constraints may differ from the
definitional axioms introduced for it. For example, suppose that a
function's definition is [local] to the [encapsulate]; that is,
suppose the function is introduced in the [signature] of the
[encapsulate]. Then its constraints include, at the least, those
non-[local] theorems and definitions in the [encapsulate] that
mention the function symbol.
Actually, it will follow from the discussion below that if the
[signature] is empty for an [encapsulate], then the constraint on
each of its new function symbols is exactly the definitional axiom
introduced for it. Intuitively, we view such encapsulates just as
we view [include-book] [events]. But the general case, where the
[signature] is not empty, is more complicated.
In the discussion that follows we describe in detail exactly which
constraints are associated with which function symbols that are
introduced in the scope of an [encapsulate] event. In order to
simplify the exposition we make two cuts at it. In the first cut we
present an over-simplified explanation that nevertheless captures
the main ideas. In the second cut we complete our explanation by
explaining how we view certain [events] as being ``lifted'' out of
the [encapsulate], resulting in a possibly smaller [encapsulate],
which becomes the target of the algorithm described in the first
cut.
At the end of this note we present an example showing why a more
naive approach is unsound.
Finally, before we start our ``first cut,'' we note that any
information you want ``exported'' outside an [encapsulate] event
must be there as an explicit definition or theorem. For example,
even if a function foo has output type (mv t t) in its [signature],
the system will not know (true-listp (foo x)) merely on account of
this information. Thus, if you are using functions like foo
(constrained [mv] functions), then you may find it useful to prove
(inside the encapsulate, to be exported) a :[type-prescription]
rule for the constrained function, for example, the
:[type-prescription] rule (true-listp (foo x)).
First cut at constraint-assigning algorithm. Quite simply, the
formulas introduced in the scope of an [encapsulate] are conjoined,
and each function symbol introduced by the [encapsulate] is
assigned that conjunction as its constraint.
Clearly this is a rather severe algorithm. Let us consider two
possible optimizations in an informal manner before presenting our
second cut.
Consider the (rather artificial) event below. The function before1
does not refer at all, even indirectly, to the locally-introduced
function sig-fn, so it is unfortunate to saddle it with constraints
about sig-fn.
(encapsulate
(((sig-fn *) => *))
(defun before1 (x)
(if (consp x)
(before1 (cdr x))
x))
(local (defun sig-fn (x) (cons x x)))
(defthm sig-fn-prop
(consp (sig-fn x)))
)
We would like to imagine moving the definition of before1 to just in
front of this [encapsulate], as follows.
(defun before1 (x)
(if (consp x)
(before1 (cdr x))
x))
(encapsulate
(((sig-fn *) => *))
(local (defun sig-fn (x) (cons x x)))
(defthm sig-fn-prop
(consp (sig-fn x)))
)
Thus, we will only assign the constraint (consp (sig-fn x)), from the
theorem sig-fn-prop, to the function sig-fn, not to the function
before1.
More generally, suppose an event in an [encapsulate] event does not
mention any function symbol in the [signature] of the
[encapsulate], nor any function symbol that mentions any such
function symbol, and so on. (We might say that no function symbol
from the [signature] is an ``ancestor'' of any function symbol
occurring in the event.) Then we imagine moving the event, so that
it appears in front of the [encapsulate]. We don't actually move
it, but we pretend we do when it comes time to assign constraints.
Thus, such definitions only introduce definitional axioms as the
constraints on the function symbols being defined. In the example
above, the event sig-fn-prop introduces no constraints on function
before1.
Once this first optimization is performed, we have in mind a set of
``constrained functions.'' These are the functions introduced in
the [encapsulate] that would remain after moving some of them in
front, as indicated above. Consider the collection of all formulas
introduced by the [encapsulate], except the definitional axioms,
that mention these constrained functions. So for example, in the
event below, no such formula mentions the function symbol after1.
(encapsulate
(((sig-fn *) => *))
(local (defun sig-fn (x) (cons x x)))
(defthm sig-fn-prop
(consp (sig-fn x)))
(defun after1 (x)
(sig-fn x))
)
We can see that there is really no harm in imagining that we move the
definition of after1 out of the [encapsulate], to just after the
[encapsulate].
Many subtle aspects of this rearrangement process have been omitted.
For example, suppose the function fn uses sig-fn, the latter being
a function in the signature of the encapsulation. Suppose a formula
about fn is proved in the encapsulation. Then from the discussion
above fn is among the constrained functions of the encapsulate: it
cannot be moved before the encapsulate and it cannot be moved after
the encapsulation. But why is fn constrained? The reason is that
the theorem proved about fn may impose or express constraints on
sig-fn. That is, the theorem proved about fn may depend upon
properties of the witness used for sig-fn. Here is a simple
example:
(encapsulate
(((sig-fn *) => *))
(local (defun sig-fn (x) (declare (ignore x)) 0))
(defun fn (lst)
(if (endp lst)
t
(and (integerp (sig-fn (car lst)))
(fn (cdr lst)))))
(defthm fn-always-true
(fn lst)))
In this example, there are no [defthm] events that mention sig-fn
explicitly. One might therefore conclude that it is completely
unconstrained. But the witness we chose for it always returns an
integer. The function fn uses sig-fn and we prove that fn always
returns true. Of course, the proof of this theorem depends upon the
properties of the witness for sig-fn, even though those properties
were not explicitly ``called out'' in theorems proved about sig-fn.
It would be unsound to move fn-always-true after the encapsulate.
It would also be unsound to constrain sig-fn to satisfy just
fn-always-true without including in the constraint the relation
between sig-fn and fn. Hence both sig-fn and fn are constrained by
this encapsulation and the constraint imposed on each is the same
and states the relation between the two as characterized by the
equation defining fn as well as the property that fn always returns
true. Suppose, later, one proved a theorem about sig-fn and wished
to functionally instantiate it. Then one must also functionally
instantiate fn, even if it is not involved in the theorem, because
it is only through fn that sig-fn inherits its constrained
properties.
This is a pathological example that illustrate a trap into which one
may easily fall: rather than identify the key properties of the
constrained function the user has foreshadowed its intended
application and constrained those notions. Clearly, the user
wishing to introduce the sig-fn above would be well-advised to use
the following instead:
(encapsulate
(((sig-fn *) => *))
(local (defun sig-fn (x) (declare (ignore x)) 0))
(defthm integerp-sig-fn
(integerp (sig-fn x))))
(defun fn (lst)
(if (endp lst)
t
(and (integerp (sig-fn (car lst)))
(fn (cdr lst)))))
(defthm fn-always-true
(fn lst)))
Note that sig-fn is constrained merely to be an integer. It is the
only constrained function. Now fn is introduced after the
encapsulation, as a simple function that uses sig-fn. We prove that
fn always returns true, but this fact does not constrain sig-fn.
Future uses of sig-fn do not have to consider fn at all.
Sometimes it is necessary to introduce a function such as fn within
the encapsulate merely to state the key properties of the undefined
function sig-fn. But that is unusual and the user should understand
that both functions are being constrained.
Another subtle aspect of encapsulation that has been brushed over so
far has to do with exactly how functions defined within the
encapsulation use the signature functions. For example, above we
say ``Consider the collection of all formulas introduced by the
encapsulate, except the definitional axioms, that mention these
constrained functions.'' We seem to suggest that a definitional
axiom which mentions a constrained function can be moved out of the
encapsulation and considered part of the ``post-encapsulation''
extension of the logical [world], if the defined function is not
used in any non-definitional formula proved in the encapsulation.
For example, in the encapsulation above that constrained sig-fn and
introduced fn within the encapsulation, fn was constrained because
we proved the formula fn-always-true within the encapsulation. Had
we not proved fn-always-true within the encapsulation, fn could
have been moved after the encapsulation. But this suggests an
unsound rule because whether such a function can be moved after the
encapsulate depend on whether its admission used properties of the
witnesses! In particular, we say a function is ``subversive'' if
any of its governing tests or the actuals in any recursive call
involve a function in which the signature functions are ancestral.
See [subversive-recursions].
(Aside: The definition of fn in the first enapsulation above that
defines fn, i.e., the encapsulation with fn-always-true inside, is
subversive because the call of the macro [and] expands to a call of
IF that governs a recursive call of fn, in this case:
(defun fn (lst)
(if (endp lst)
t
(if (integerp (sig-fn (car lst)))
(fn (cdr lst))
nil))).
If we switch the order of conjuncts in fn, then the definition of fn
is no longer subversive, but it still ``infects'' the constraint
generated for the encapsulation, hence for sig-fn, because
fn-always-true blocks the definition of fn from being moved back
(to after the encapsulation). If we both switch the order of
conjuncts and drop fn-always-true from the encapsulation, then the
definition of fn is in essence moved back to after the
encapsulation, and the constraint for sig-fn no longer includes the
definition of fn. End of aside.)
Another aspect we have not discussed is what happens to nested
encapsulations when each introduces constrained functions. We say
an encapsulate event is ``trivial'' if it introduces no constrained
functions, i.e., if its signatures is nil. Trivial encapsulations
are just a way to wrap up a collection of events into a single
event.
From the foregoing discussion we see we are interested in exactly how
we can ``rearrange'' the events in a non-trivial encapsulation --
moving some ``before'' the encapsulation and others ``after'' the
encapsulation. We are also interested in which functions introduced
by the encapsulation are ``constrained'' and what the
``constraints'' on each are. We may summarize the observations
above as follows, after which we conclude with a more elaborate
example.
Second cut at constraint-assigning algorithm. First, we focus only on
non-trivial encapsulations that neither contain nor are contained
in non-trivial encapsulations. (Nested non-trivial encapsulations
are not rearranged at all: do not put anything in such a nest
unless you mean for it to become part of the constraints
generated.) Second, in what follows we only consider the non-local
events of such an encapsulate, assuming that they satisfy the
restriction of using no locally defined function symbols other than
the signature functions. Given such an encapsulate event, move, to
just in front of it and in the same order, all definitions and
theorems for which none of the signature functions is ancestral.
Now collect up all formulas (theorems) introduced in the
[encapsulate] other than definitional axioms. Add to this set any
of those definitional equations that is either subversive or
defines a function used in a formula in the set. The conjunction of
the resulting set of formulas is called the ``constraint'' and the
set of all the signature functions of the encapsulate together with
all function symbols defined in the encapsulate and mentioned in
the constraint is called the ``constrained functions.'' Assign the
constraint to each of the constrained functions. Move, to just
after the encapsulate, the definitions of all function symbols
defined in the encapsulate that have been omitted from the
constraint.
Implementation note. In the implementation we do not actually move
[events], but we create constraints that pretend that we did.
Here is an example illustrating our constraint-assigning algorithm.
It builds on the preceding examples.
(encapsulate
(((sig-fn *) => *))
(defun before1 (x)
(if (consp x)
(before1 (cdr x))
x))
(local (defun sig-fn (x) (cons x x)))
(defthm sig-fn-prop
(consp (sig-fn x)))
(defun during (x)
(if (consp x)
x
(cons (car (sig-fn x))
17)))
(defun before2 (x)
(before1 x))
(defthm before2-prop
(atom (before2 x)))
(defthm during-prop
(implies (and (atom x)
(before2 x))
(equal (car (during x))
(car (sig-fn x)))))
(defun after1 (x)
(sig-fn x))
(defchoose after2 (x) (u)
(and (< u x) (during x)))
)
Only the functions sig-fn and during receive extra constraints. The
functions before1 and before2 are viewed as moving in front of the
[encapsulate], as is the theorem before2-prop. The functions after1
and after2 are viewed as being moved past the [encapsulate]. The
implementation reports the following.
In addition to SIG-FN, we export AFTER2, AFTER1, BEFORE2, DURING and
BEFORE1.
The following constraint is associated with both of the functions DURING and
SIG-FN:
(AND (EQUAL (DURING X)
(IF (CONSP X)
X (CONS (CAR (SIG-FN X)) 17)))
(CONSP (SIG-FN X))
(IMPLIES (AND (ATOM X) (BEFORE2 X))
(EQUAL (CAR (DURING X))
(CAR (SIG-FN X)))))
Notice that the formula (consp (during x)) is not a conjunct of the
constraint. During the first pass of the encapsulate, this formula
is stored as a :[type-prescription] rule deduced during the
definition of the function during. However, the rule is not
exported because of a rather subtle soundness issue. (If you are
interested in details, see the comments in source function
putprop-type-prescription-lst.)
We conclude by asking (and to a certain extent, answering) the
following question: Isn't there an approach to assigning
constraints that avoids over-constraining more simply than our
``second cut'' above? Perhaps it seems that given an [encapsulate],
we should simply assign to each locally defined function the
theorems exported about that function. If we adopted that simple
approach the events below would be admissible.
(encapsulate
(((foo *) => *))
(local (defun foo (x) x))
(defun bar (x)
(foo x))
(defthm bar-prop
(equal (bar x) x)
:rule-classes nil))
(defthm foo-id
(equal (foo x) x)
:hints ((\"Goal\" :use bar-prop)))
; The following event is not admissible in ACL2.
(defthm ouch!
nil
:rule-classes nil
:hints
((\"Goal\" :use
((:functional-instance foo-id
(foo (lambda (x) (cons x x))))))))
Under the simple approach we have in mind, bar is constrained to
satisfy both its definition and bar-prop because bar mentions a
function declared in the signature list of the encapsulation. In
fact, bar is so-constrained in the ACL2 semantics of encapsulation
and the first two events above (the encapsulate and the consequence
that foo must be the identity function) are actually admissible.
But under the simple approach to assigning constraints, foo is
unconstrained because no theorem about it is exported. Under that
approach, ouch! is provable because foo can be instantiated in
foo-id to a function other than the identity function.
It's tempting to think we can fix this by including definitions, not
just theorems, in constraints. But consider the following slightly
more elaborate example. The problem is that we need to include as a
constraint on foo not only the definition of bar, which mentions
foo explicitly, but also abc, which has foo as an ancestor.
(encapsulate
(((foo *) => *))
(local (defun foo (x) x))
(local (defthm foo-prop
(equal (foo x) x)))
(defun bar (x)
(foo x))
(defun abc (x)
(bar x))
(defthm abc-prop
(equal (abc x) x)
:rule-classes nil))
(defthm foo-id
(equal (foo x) x)
:hints ((\"Goal\" :use abc-prop)))
; The following event is not admissible in ACL2.
(defthm ouch!
nil
:rule-classes nil
:hints
((\"Goal\" :use
((:functional-instance foo-id
(foo (lambda (x) (cons x x)))
(bar (lambda (x) (cons x x))))))))")
(CONVERSION
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Conversion to Uppercase
When symbols are read by Common Lisp they are converted to upper
case. Note carefully that this remark applies to the characters in
symbols. The characters in strings are not converted upper case.
To type a symbol containing lower case characters you can enclose the
symbol in vertical bars, as in |AbC| or you can put a ``backslash''
before each lower case character you wish to preserve, as in A\\bC.
|AbC| and A\\bC are two different ways of writing the same symbol
(just like 2/4 and 1/2 are two different ways of writing the same
rational and 123 and 0123 are two different ways to write the same
natural number). The symbol has three characters in its name, the
middle one of which is a lower case b.")
(COPYRIGHT
(ABOUT-ACL2)
"ACL2 copyright, license, sponsorship
This topic provides information about copyright, license, authorship,
and sponsorship of the ACL2 system. For information about copyright
and authorship of [documentation], see [documentation-copyright],
which notes that there are many documentation authors.
ACL2 Version 7.2 --- A Computational Logic for Applicative Common
Lisp
Copyright (C) 2016, Regents of the University of Texas
This version of ACL2 is a descendent of ACL2 Version 1.9, Copyright
(C) 1997 Computational Logic, Inc. See the documentation topic
NOTE-2-0.
This program is free software; you can redistribute it and/or modify
it under the terms of the LICENSE file distributed with ACL2.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
LICENSE for more details.
Written by: Matt Kaufmann and J Strother Moore
email: Kaufmann@cs.utexas.edu and Moore@cs.utexas.edu
Department of Computer Science
University of Texas at Austin
Austin, TX 78712 U.S.A.
Please also see [acknowledgments].
Subtopics
[Documentation-copyright]
Copyright and authorship of documentation")
(COROLLARY
(RULE-CLASSES)
"The corollary formula of a [rune]
See [formula]. This is a low-level system function at the present
time. See [pr] and see [pr!] instead. Also see [rule-classes] for
the use of the symbol :corollary in specifying a rule class.")
(CORROBORATING_MODELS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Corroborating Models
[{IMAGE}]
After producing a model, it must be corroborated against reality. The
Falling Body Model has been corroborated by a vast number of
experiments in which the time and distance were measured and
compared according to the formula. In general all models must be
corroborated by experiment.
The Falling Body Model can be derived from deeper models, namely
Newton's laws of motion and the assertion that, over the limited
distances concerned, graviation exerts a constant acceleration on
the object. When the model in question can be derived from other
models, it is the other models that are being corroborated by our
experiments.
Because nature is not formal, we cannot prove that our models of it
are correct. All we can do is test our models against nature's
behavior.
Such testing often exposes restrictions on the applicability of our
models. For example, the Falling Body Model is inaccurate if air
resistance is significant. Thus, we learn not to use that model to
predict how long it takes a feather to fall from a 200 foot tower
in the earth's atmosphere.
In addition, attempts at corroboration might reveal that the model is
actually incorrect. Careful measurements might expose the fact that
the gravitational force increases as the body falls closer to
earth. Very careful measurements might reveal relativistic effects.
Technically, the familiar Falling Body Model is just wrong, even
under excessive restrictions such as ``in a perfect vacuum'' and
``over small distances.'' But it is an incredibly useful model
nonetheless.
There are several morals here.
Models need not be complete to be useful.
Models need not be perfectly accurate to be useful.
The user of a model must understand its limitations.
[{IMAGE}]")
(COUNT
(LISTS STRINGS ACL2-BUILT-INS)
"Count the number of occurrences of an item in a string or true-list
Example Forms:
(count #\\D \"DabcDefcDe\") ; = 3
(count #\\D \"DabcDefcDe\" :start 1) ; = 2
(count #\\D \"DabcDefcDe\" :start 1 :end 5) ; = 1
(count #\\D \"DabcDefcDe\" :start 1 :end 4) ; = 0
(count #\\z \"DabcDefcDe\") ; = 0
(count '(a b) '(17 (a b) 23 (a b) (c d))) ; = 2
General Form:
(count item sequence &key start end)
(Count item sequence) returns the number of times item occurs in
sequence. The [guard] for calls of count (which is actually a macro
in ACL2) specifies that sequence is a string or a true-list, and
that start, which defaults to 0, and end, which defaults to the
length of sequence, are valid indices into sequence.
See any Common Lisp documentation for more information about count,
which is a Common Lisp utility. At this time ACL2 does not support
keyword arguments for count other than :start and :end; we may add
support for the :from-end keyword upon request.
Macro: <count>
(defmacro count
(item sequence &key (start '0) end)
(cons 'count-fn
(cons item
(cons sequence
(cons start (cons end 'nil))))))")
(CPU-CORE-COUNT
(PARALLELISM ACL2-BUILT-INS)
"The number of cpu cores
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
Unless the ACL2 executable supports parallel execution (see
[parallelism]), this function returns (mv 1 state). Otherwise:
(Cpu-core-count state) returns (mv core-count state), where
core-count is determined as follows. If environment variable
ACL2_CORE_COUNT has a non-empty value, then that value should
represent a positive integer (else an error occurs), which is the
returned core-count. Otherwise, the returned core-count may be
obtained from the underlying Common Lisp implementation, else as a
positive integer value from [state] global variable 'cpu-core-count
(see [assign]). Otherwise an error occurs.
Example:
(cpu-core-count state) ==> (mv 4 state)
Cpu-core-count has the following logical definition.
Function: <cpu-core-count>
(defun cpu-core-count (state)
(declare (xargs :stobjs state :guard t))
(mv-let (nullp val state)
(read-acl2-oracle state)
(declare (ignore nullp))
(mv val state)))")
(CURRENT-PACKAGE
(LD)
"The package used for reading and printing
Current-package is an [ld] special (see [ld]). The accessor is
(current-package state) and the updater is (set-current-package val
state), or more conventionally, (in-package val). The value of
current-package is actually the string that names the package.
(Common Lisp's ``package'' objects do not exist in ACL2.) The
current package must be known to ACL2, i.e., it must be one of the
initial packages or a package defined with [defpkg] by the user.
When printing symbols, the package prefix is displayed if it is not
the current-package and may be optionally displayed otherwise.
Thus, if current-package is \"ACL2\" then the symbol 'ACL2::SYMB may
be printed as SYMB or ACL2::SYMB, while 'MY-PKG::SYMB must be
printed as MY-PKG::SYMB. But if current-package is \"MY-PKG\" then
the former symbol must be printed as ACL2::SYMB while the latter
may be printed as SYMB.
In Common Lisp, current-package also affects how objects are read
from character streams. Roughly speaking, read and print are
inverses if the current-package is fixed, so reading from a stream
produced by printing an object must produce an equal object.
In ACL2, the situation is more complicated because we never read
objects from character streams, we only read them from object
``streams'' (channels). Logically speaking, the objects in such a
channel are fixed regardless of the setting of current-package.
However, our host file systems do not support the idea of Lisp
object files and instead only support character files. So when you
open an object input channel to a given (character file) we must
somehow convert it to a list of ACL2 objects. This is done by a
deus ex machina (``a person or thing that appears or is introduced
suddenly and unexpectedly and provides a contrived solution to an
apparently insoluble difficulty,'' Webster's Ninth New Collegiate
Dictionary). Roughly speaking, the deus ex machina determines what
sequence of calls to read-object will occur in the future and what
the current-package will be during each of those calls, and then
produces a channel containing the sequence of objects produced by
an analogous sequence of Common Lisp reads with *current-package*
bound appropriately for each.
A simple rule suffices to make sane file [io] possible: before you
read an object from an object channel to a file created by printing
to a character channel, make sure the current-package at read-time
is the same as it was at print-time.")
(CURRENT-THEORY
(THEORIES THEORY-FUNCTIONS)
"Currently [enable]d rules as of logical name
Examples:
(current-theory :here)
(current-theory 'lemma3)
See [logical-name].
General Form:
(current-theory logical-name)
Returns the current theory as it existed immediately after the
introduction of [logical-name] provided it is evaluated in an
environment in which the variable symbol WORLD is bound to the
current ACL2 logical world, (w state). Thus,
ACL2 !>(current-theory :here)
will cause an (unbound variable) error while
ACL2 !>(let ((world (w state))) (current-theory :here))
will return the current theory in world.
See [theories] and see [logical-name] for a discussion of theories in
general and why the commonly used ``theory functions'' such as
current-theory are really macros that expand into terms involving
the variable world.
The theory returned by current-theory is in fact the theory selected
by the [in-theory] event most recently preceding logical name,
extended by the rules introduced up through [logical-name].
You may experience a fencepost problem in deciding which logical name
to use. [Deflabel] can always be used to mark unambiguously for
future reference a particular point in the development of your
theory. The order of [events] in the vicinity of an [encapsulate]
is confusing. See [encapsulate].
This ``function'' is actually a macro that expands to a term
mentioning the single free variable [world]. When theory
expressions are evaluated by [in-theory] or the :[in-theory] hint,
[world] is bound to the current ACL2 [world].")
(CUSTOM-KEYWORD-HINTS
(HINTS)
"User-defined hints
See [add-custom-keyword-hint] for a discussion of how advanced users
can define their own hint keywords. For examples, see the community
books directory books/hints/, in particular basic-tests.lisp.
Subtopics
[Show-custom-keyword-hint-expansion]
Print out custom keyword hints when they are expanded")
(CW
(IO ACL2-BUILT-INS)
"Print to the comment window
Example:
(cw \"The goal is ~p0 and the alist is ~x1.~%\"
(untranslate term t nil)
unify-subst)
Logically, this expression is equivalent to nil. However, it has the
effect of first printing to the so-called ``comment window'' the
[fmt] string as indicated. Thus, cw is like fmt (see [fmt]) except
in three important ways. First, it is a macro whose calls expand to
calls of a :[logic] mode function. Second, it neither takes nor
returns the ACL2 [state]; logically cw simply returns nil, although
it prints to a comment window that just happens to share the
terminal screen with the standard character output [*standard-co*].
Third, its fmt args are positional references, so that for example
(cw \"Answers: ~p0 and ~p1\" ans1 ans2)
prints in the same manner as:
(fmt \"Answers: ~p0 and ~p1\"
(list (cons #\\0 ans1) (cons #\\1 ans2))
*standard-co* state nil)
Typically, calls of cw are embedded in [prog2$] forms, e.g.,
(prog2$ (cw ...)
(mv a b c))
which has the side-effect of printing to the comment window and
logically returning (mv a b c).
General Form:
(cw fmt-string arg1 arg2 ... argn)
where n is between 0 and 9 (inclusive). The macro uses
[fmt-to-comment-window], passing it the column 0 and [evisc-tuple]
nil, after assembling the appropriate alist binding the [fmt] vars
#\\0 through #\\9; see [fmt]. If you want
(a) more than 10 vars,
(b) vars other than the digit chars,
(c) a different column, or
(d) a different evisc-tuple,
then call [fmt-to-comment-window] instead.
Also see [cw!], which is useful if you want to be able to read the
printed forms back in.
Finally, we discuss another way to create formatted output that also
avoids the need to pass in the ACL2 [state]. The idea is to use
wormholes; see [wormhole]. Below is a function you can write, along
with some calls, providing an illustration of this approach.
(defun my-fmt-to-comment-window (str alist)
(wormhole 'my-fmt-to-comment-window
'(lambda (whs) whs)
(list str alist)
'(pprogn
(fms (car (@ wormhole-input))
(cadr (@ wormhole-input))
*standard-co*
state
nil)
(value :q))
:ld-verbose nil
:ld-error-action :return ; harmless return on error
:ld-prompt nil))
; A non-erroneous call:
(my-fmt-to-comment-window \"Here is ~x0 for your inspection~%\"
(list (cons #\\0 'foo)))
; An error inside the fmt string (unbound fmt var); note that even
; with the error, the wormhole is exited.
(my-fmt-to-comment-window \"Here is ~x1 for your inspection~%\"
(list (cons #\\0 'foo)))
; A guard violation in the binding; note that even with the error,
; the wormhole is exited.
(my-fmt-to-comment-window \"Here is ~x0 for your inspection~%\"
(list (cons #\\0 (car 'foo))))")
(CW!
(IO ACL2-BUILT-INS)
"Print to the comment window
This is the same as [cw], except that [cw] inserts backslash (\\)
characters when forced to print past the right margin, in order to
make the output a bit clearer in that case. Use cw! instead if you
want to be able to read the forms back in.")
(CW-GSTACK
(BREAK-REWRITE DEBUGGING)
"Debug a rewriting loop or stack overflow
Example Forms:
(cw-gstack)
(cw-gstack :frames 10) ; show only the top 10 frames
(cw-gstack :frames '(1 10)) ; same as above: show only frames 1 through 10
(cw-gstack :frames '(10 20)) ; show only frames 10 through 20
(cw-gstack :evisc-tuple (evisc-tuple 3 4 nil nil))
; print with print-level 3 and print-length 4
(cw-gstack :evisc-tuple nil) ; print using default ``evisceration'',
; essentially the same as just above
(cw-gstack :evisc-tuple '(nil 3 4 (hide)))
; same as just above
General Form:
(cw-gstack :frames frames :evisc-tuple evisc-tuple)
where :frames and :evisc-tuple are optional, but if they are
supplied, their values are evaluated. The value of frames should be
either a natural number or a list of two natural numbers, the first
less than the second; and the value of evisc-tuple should be an
evisc-tuple (see [evisc-tuple]). If :evisc-tuple is omitted, then
substructures deeper than 3 are replaced by ``#'' and those longer
than 4 are replaced by ``...'', and terms of the form (hide ...)
are printed as <hidden>. Also see [set-iprint] for an alternative
to printing ``#'' and ``...''.
Stack overflows may occur, perhaps caused by looping rewrite rules.
In some Lisps, stack overflows may manifest themselves as
segmentation faults, causing the entire ACL2 image to crash.
Finding looping rewrite rules can be tricky, especially if you are
using books supplied by other people. (However, see
[set-rewrite-stack-limit] for a way to avoid stack overflows caused
by rewriter loops.)
Normally, a stack overflow will cause the printing of an error
message that suggests how to proceed. Just follow those
instructions, and you will generally be able to see what is causing
the loop.
Suggestion: Once you have found the loop and fixed it, you should
execute the ACL2 command :[brr] nil, so that you don't slow down
subsequent proof attempts.")
(DEAD-EVENTS
(DEBUGGING)
"Using proof supporters to identify dead code and unused theorems
Below, when we talk about ``an event A'', we mean an event whose name
is A.
When event A is used in a proof performed to admit event B that you
submit to ACL2, we say that A is a ``proof-supporter'' of B. ACL2
stores an association list such that for every event B with at
least one proof-supporter, B is associated with a list of all of
its proof-supporters, sorted by [symbol-<]. The following form
evaluates to that alist, which is called the
``proof-supporters-alist''.
(global-val 'proof-supporters-alist (w state))
By ``used in a proof'' above, we mean: applied as a rule or supplied
explicitly via [hints] of type :use, :by, or :clause-processor.
That is, the [events] ``used in a proof'' for admitting an event E
are those listed in the summary printed at the conclusion of
admitting E.
Note that if proofs are skipped when admitting event E, say because
the last admission of E was done by [include-book] (or
certify-book, which ends with an [include-book]), then there will
be no entry in that alist for E. (An exception is made however for
[encapsulate] [events], where proof-supporters are remembered from
the first pass; see below.) So if you want the
proof-supporters-alist to include supporters for events in a book,
use [ld] rather than [include-book] or [certify-book] to process
the events in that book. If however you are interested in the
proof-supporters FROM a book that support a later event, then it is
fine to include that book.
The case for [encapsulate] is slightly tricky. Consider an example of
the following form.
A ; event preceding the encapsulate
(encapsulate
()
B
(local C) ; uses A and B in a proof
D ; uses C in a proof
)
At the conclusion of this [encapsulate] event, the
proof-supporters-alist associates D with A and B, but not C (which
has disappeared, since it is [local]).
Note that this sort of ``transitive closure'' operation is only
performed when necessary due to the disappearance of [local]
[events]. For example, if we replace (local C) above by just C,
then D is associated in the proof-supporters-alist only with C, not
with A or B. If you want the transitive closure of the relation
computed by the proof-supporters-alist, you have to compute it
yourself. (This was a deliberate design decision, in order to avoid
slowing down event processing.) However, there is help available on
how to do such a computation:
A community book, books/tools/dead-events.lisp, does such a
transitive closure, and moreover uses that information to find
``dead events'' relative to a list of ``desired'' events. For
example, suppose you use [ld] to process the events, with proofs,
in a book intended to prove theorems MAIN-1 and MAIN-2. (Remember,
[certify-book] will not save such information.) Suppose furthermore
that the book begins with some [include-book] forms followed by
(deflabel book-start). You could evaluate this form:
(dead-events '(main-1 main-2) :start 'book-start)
The result is a list of events that you probably can delete from the
book without causing any proofs to fail. See the dead-events.lisp
book for further documentation.
You might also find the code in the above book to be helpful for
writing your own utilities based on the proof-supporters-alist.")
(DEALING-WITH-KEY-COMBINATIONS-OF-FUNCTION-SYMBOLS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"How to get rid of key combinations of function symbols
Suppose REV reverses a list, MEMBER checks that its first argument is
an element of its second, and SQUARES-PLUS-3P is some complicated
predicate. Suppose you're proving some Main Theorem that involves
those concepts and the theorem prover presents you with the
following hideous formula as a key checkpoint. What action should
you take?
Hint: Don't read the formula ``for sense,'' i.e., don't try to
understand what this formula is saying! Just look at every subterm
involving a nest of two function symbols and ask if you know
something about those two symbols that allows you to simplify that
one subterm.
(IMPLIES (AND (CONSP X)
(MEMBER (+ 3 (* I I)) (REV X))
(LIST-OF-INTEGERS X)
(INTEGERP I)
(<= 0 I)
(INTEGERP K)
(<= 0 K)
(< I K)
(SQUARES-PLUS-3P K X)
(NOT (EQUAL (CAR X) (+ 3 (* I I))))
(NOT (MEMBER (+ 3 (* I I)) X)))
(SQUARES-PLUS-3P K (REV X)))?
The experienced ACL2 user will stop reading at the second hypothesis!
(MEMBER (+ 3 (* I I)) (REV X))
The combination of MEMBER and REV can be simplified. The question
``is e a member of (REV x)'' can be answered by asking ``is e a
member of x''. The two questions are equivalent. This insight comes
from your intuition about the semantics of REV -- it just reorders
the elements but doesn't add or delete any. The second question is
simpler since it doesn't mention REV, so this is a good
transformation to make. And the theorem that they are equivalent is
simpler than the key checkpoint above because it involves fewer
functions and smaller expressions.
You might formalize this insight as
(equal (member e (rev x))
(member e x))
But this conjecture is not a theorem, because (member e x) returns
the cdr of x that begins with e, not just a Boolean (t or nil)
indicating whether e is an element of x. The location of the first
e in (rev x) is generally different than the location in x. So when
we say the two questions are ``equivalent'' we don't mean they are
equal. We mean that they're propositionally equivalent: both nil or
both non-nil. This sense of equivalence is called ``if and only
if'' and is checked by the function iff.
So our intuitive insight can be phrased as this theorem:
(iff (member e (rev x))
(member e x))
Suggesting that this formulation of the insight is ``obvious'' begs
many questions. Mathematically, we could have avoided iff and just
written two implications:
(and (implies (member e x) (member e (rev x)))
(implies (member e (rev x)) (member e x))).
or
(and (implies (member e x) (member e (rev x)))
(implies (not (member e x)) (not (member e (rev x))))).
Or we could have used iff but ``oriented'' it the other way:
(iff (member e x)
(member e (rev x)))
We choose to write
(iff (member e (rev x))
(member e x))
because of our knowledge of how ACL2 turns formulas into rules!
We deal with this at greater length later. But just to drive the
point home, if we issue the command:
(defthm member-rev
(iff (member e (rev x))
(member e x)))
ACL2 will build in a rule that causes every propositional occurrence
of (MEMBER e (REV x)) to be replaced by (MEMBER e x). (By
``propositional occurrence'' we mean an occurrence in which the
value is tested, as by IF or the propositional connectives.
Remember, one might use member to determine the location of an
element too.)
Note carefully: if you do not tell ACL2 how to make a rule from a
theorem, it makes a rewrite rule. Rewrite rules always replace
instances of the left-hand side by the corresponding instances of
the right-hand side. That is, when interpreted as a rewrite rule,
(iff alpha beta) makes ACL2 replace alpha by beta.
Probably the biggest mistake new users make is forgetting that every
theorem they prove creates a very specific rule. You must remember
that you are programming ACL2 with these rules. Being careless in
your statement of theorems is tantamount to being careless in your
programming. What you get is a mess.
Had we proved the same equivalence, but with the iff commuted, we
would be giving ACL2 bad advice. We would be telling it ``replace
instances of (MEMBER e x) by the corresponding instances of (MEMBER
e (REV x))''! If ACL2 had that rule and ever tried to simplify any
member expression, e.g., (MEMBER A B), it would get into an
infinite loop, e.g., producing the following sequence of
transformations:
(MEMBER A B)
(MEMBER A (REV B))
(MEMBER A (REV (REV B)))
...
until it eventually exhausted some resource.
Recall that we entertained the idea of phrasing our insight about
member and rev with implications rather than iff. Generally
speaking, implications produce weaker rules -- rules that apply
less often. We discuss that later.
Now suppose we've proved member-rev, oriented so as to rewrite
(member e (rev x)) to (member e x), and built it in as a rewrite
rule. Then suppose we repeated the attempt to prove our Main
Theorem. This time, when the prover is processing the hideous Key
Checkpoint printed above, our new lemma, member-rev, will hit it.
It will transform the formula to:
(IMPLIES (AND (CONSP X)
(MEMBER (+ 3 (* I I)) X) ; <-- the hyp has simplified
(LIST-OF-INTEGERS X)
(INTEGERP I)
(<= 0 I)
(INTEGERP K)
(<= 0 K)
(< I K)
(SQUARES-PLUS-3P K X)
(NOT (EQUAL (CAR X) (+ 3 (* I I))))
(NOT (MEMBER (+ 3 (* I I)) X)))
(SQUARES-PLUS-3P K (REV X)))?
and then that will collapse to T, since the IMPLIES has contradictory
hypotheses (note the last hypothesis above).
By proving member-rev we proved the hideous checkpoint. We never had
to look at the rest of the formula or think about why it is a
theorem. Furthermore, attacking the main theorem again, from
scratch, with member-rev in the database, may eliminate other
checkpoints that came up the last time we tried to prove our main
goal. So we recommend addressing one checkpoint at a time.
This example illustrates that purely local thinking -- looking for
simplifiable combinations of function symbols -- can sometimes lead
to proofs and should always be your first reaction to a key
checkpoint: what local fact do you know that would clean up the
formula? Don't think about deep questions like ``why is this
true?'' until you can't see any way to make it simpler.
It is important to train yourself to see combinations of function
symbols and to create strong rules for eliminating them. We will
give you opportunities to practice this later in the tutorial.
If you have been reading the tutorial introduction to the theorem
prover, use your browser's Back Button now to return to
[introduction-to-key-checkpoints].")
(DEALING-WITH-TAU-PROBLEMS
(INTRODUCTION-TO-THE-TAU-SYSTEM)
"Some advice on dealing with problems caused by the tau system
For background on the tau system, see
[introduction-to-the-tau-system]. The two most common problems
caused by the tau system have to do with the system's interaction
with ``legacy'' proof scripts. Such scripts may suffer because they
were not designed to exploit tau reasoning and which may configure
the tau database in quite incomplete and arbitrary ways. The two
most common problems we have seen are (a) significant slow downs in
a few proofs and (b) failed proof attempts due to hints being
misapplied because the tau system caused subgoals to be renumbered.
We discuss the rather limited means of dealing with these problems
here. In [future-work-related-to-the-tau-system] we list some major
inadequacies of the tau system.
If the tau system contributes to a proof, the [rune]
(:[executable-counterpart] tau-system) will be listed among the
Rules in the Summary. However, merely by being attempted the tau
system can slow down proofs in which it makes no contribution.
The most brutal and fool-proof way to isolate a proof from the tau
system is to disable the entire system. This can be done globally
by
(in-theory (disable (tau-system))) ; (:executable-counterpart tau-system)
or locally with a subgoal specific hint:
...
:hints ((\"...subgoal id...\" :in-theory (disable (tau-system))))
Conducting a proof with and without the participation of the tau
system can help you determine whether tau reasoning is helping or
hurting.
Dealing with Slowdowns
The [time-tracker] utility was added to allow users to investigate
whether excessive amounts of time are being spent in a given
function. It was then used to annotate the code for the tau system
as described in [time-tracker-tau]. The result is that if
``excessive'' time is spent in tau reasoning, messages to that
effect will be printed to the proof log. The question is: aside
from disabling the tau system how can the proof be sped up?
There are two common causes of slowdown in the tau system. The first
stems from the system's use of :[executable-counterpart]s to
determine whether a constant has a given tau. Recall that a tau is
a conjunction of monadic predicates. To determine whether some
constant satisfies the tau, the predicates are executed. If you
have a hard-to-compute predicate this can be very slow. The most
typical such predicates in ACL2 applications are those that check
invariants, e.g., that recognize ``good states'' or ``well-formed
data.'' These are often written inefficiently because they are
intended only for used in theorems and, before the tau system was
added, they may have never been applied to constants. The most
common constants tau predicates are applied to are 0, T, and NIL,
although different models may stress other constants. To understand
why NIL for example is frequently tested, if the test of an
IF-expression is computed to have tau s then the next question we
ask is ``does nil satisfy s?''
You may determine whether the tau system is spending time executing
tau predicates by observing the rewriter --- see [dmr] --- or by
interrupting the system and getting a backtrace (see
[set-debugger-enable]).
If excessive time is being spent in a tau predicate, a draconian
solution is to disable the :[executable-counterpart] of that
predicate, for example in either of these equivalent ways. The tau
system does not execute disabled :[executable-counterpart]s.
(in-theory (disable (:executable-counterpart foo)))
(in-theory (disable (foo)))
In either case above, you may prefer to provide local :[in-theory]
:[hints] rather than :in-theory [events].
Disabling the executable counterpart of expensive tau predicates will
weaken the tau system, probably only negligibly, because it can no
longer run the predicates to determine whether they admits given
constants.
A more sophisticated solution is to make the tau system record values
of the :[logic]-mode function in question, so that the system will
look up the necessary values rather than running the function every
time the question arises. It will look up recorded values whether
the executable counterpart of the tau predicate is enabled or
disabled. Here is an example of a lemma that can provide such a
solution. See the discussion of the Eval form of :[tau-system]
rules.
(defthm lemma
(and (foo 0)
(foo 17)
(foo t)
(not (foo '(a b c))))
:rule-classes :tau-system)
It might be difficult to determine which constants are being
repeatedly tested, although tracing ([trace$]) suspected tau
predicates will show what they are being called on.
At the moment there are no better user-level tools to discover this.
However, some users may wish to consider the following hack: In the
ACL2 source file tau.lisp, immediately after the definition of the
system function ev-fncall-w-tau-recog, there is a comment which
contains some raw Lisp code that can be used to investigate whether
tau's use of evaluation on constants is causing a problem and to
determine which constants are involved.
The second main cause of slowdowns by the tau system is that the
system contains ``too many'' conjunctive rules (see the Conjunctive
form in [tau-system]). Unfortunately, we have no tools for either
identifying the problem or addressing it! That said, let us tell
you what we do know!
Conjunctive rules are used to ``complete'' each tau as it is built.
Referring to the weekdayp example in [tau-system], if a tau is
constructed that recognizes weekdays but not MON, TUE, THU, or FRI,
it is completed by adding that the tau recognizes (only) WED. This
means that when we construct a tau we scan all known conjunctive
rules and see whether all but one of the literals of any
conjunctive rule are present. This can be expensive. To mitigate
this expense, the tau system caches the computation on a per proof
basis (the cache is cleared after every proof).
To learn what conjunctive rules there are in your system, evaluate
(assoc 'tau-conjunctive-rules (tau-database (w state)))
Perhaps by sending the implementors that list, we can think of ways
to index the conjunctive rules to save time.
Dealing with Misapplied Hints
The second common problem caused by the tau system in legacy proof
scripts is that it can cause subgoals to be renumbered and thus
cause hints to be missed. The only ways to address this problem is
either to disable the tau system (locally or globally by disabling
(:executable-counterpart tau-system)) or change the legacy hints to
use the new subgoal names.")
(DEBUGGING
(TOP ACL2)
"Tools for debugging failed or slow proofs, or misbehaving functions.
Subtopics
[Accumulated-persistence]
To get statistics on which [rune]s are being tried
[Break-rewrite]
The read-eval-print loop entered to [monitor] rules
[Cw-gstack]
Debug a rewriting loop or stack overflow
[Dead-events]
Using proof supporters to identify dead code and unused theorems
[Disassemble$]
Disassemble a function
[Dmr]
Dynamically monitor rewrites and other prover activity
[Failed-forcing]
How to deal with a proof [failure] in a forcing round
[Failure]
How to deal with a proof failure
[Forward-chaining-reports]
To see reports about the forward chaining process
[Guard-debug]
Generate markers to indicate sources of [guard] proof obligations
[Measure-debug]
Generate markers to indicate sources of [measure] proof obligations
[Nil-goal]
How to proceed when the prover generates a goal of nil
[Print-gv]
Print a form whose evaluation caused a guard violation
[Proof-checker]
An interactive tool for controlling ACL2's proof processes.
[Proof-tree]
Proof tree displays
[Pstack]
Seeing what the prover is up to
[Quick-and-dirty-subsumption-replacement-step]
(advanced topic) controlling a heuristic in the prover's clausifier
[Redo-flat]
Redo on failure of a [progn], [encapsulate], or [certify-book]
[Set-check-invariant-risk]
Potential slowdown for [program]-mode updates to [stobj]s or
[arrays]
[Set-debugger-enable]
Control whether Lisp errors and breaks invoke the Lisp debugger
[Set-guard-msg]
Specify what is printed when a [guard] is violated
[Set-print-gv-defaults]
Set default keyword values for [print-gv]
[Splitter]
Reporting of rules whose application may have caused case splits
[Time-tracker]
Display time spent during specified evaluation
[Trace]
Tracing functions in ACL2
[Type-prescription-debugging]
Improve a built-in [type-prescription] rule
[Walkabout]
Explore an ACL2 cons tree")
(DECLARE
(PROGRAMMING ACL2-BUILT-INS)
"Extra declarations that can occur in function definitions, [let]
bindings, and so forth.
Common Lisp provides a declaration mechanism that allows the
programmer to explain additional information to the compiler. For
instance:
* The programmer might declare that some variable always has some
particular type. The compiler might then, depending on its
optimization/safety settings, either add run-time checks to
ensure that this really is true, or optimize the compiled code
by assuming the variable has the correct type.
* The programmer might declare that some variable is ignored. The
compiler might then, instead of warning the programmer that the
variable is never used, explicitly check to make sure that it
really is never used.
ACL2 supports the above kinds of declarations, and also adds its own
kinds of declarations for specifying things like the [guard]s and
[measure]s of functions, as described in [xargs].
There are also other kinds of Common Lisp declarations that ACL2 does
not support, e.g., pertaining to inlining, safety settings,
variable lifetime, and so forth.
Usage
Examples:
(declare (ignore x y z))
(declare (ignorable x y z)
(type integer i j k)
(type (satisfies integerp) m1 m2))
(declare (xargs :guard (and (integerp i)
(<= 0 i))
:guard-hints ((\"Goal\" :use (:instance lemma3
(x (+ i j)))))))
General Form:
(declare d1 ... dn)
where, in ACL2, each di is of one of the following forms:
(ignore v1 ... vn)
where each vi is a variable introduced in the immediately superior
lexical environment. These variables must not occur free in the
scope of the declaration. This declaration can be useful for
inhibiting compiler warnings; see also [set-ignore-ok].
(ignorable v1 ... vn)
where each vi is a variable introduced in the immediately superior
lexical environment. These variables need not occur free in the
scope of the declaration. This declaration can be useful for
inhibiting compiler warnings; see also [set-ignore-ok].
(type type-spec v1 ... vn)
where each vi is a variable introduced in the immediately superior
lexical environment and type-spec is a type specifier (as
described in the documentation for [type-spec]). This
declaration can be useful for optimizing Common Lisp execution
speed. See also [the].
(xargs :key1 val1 ... :keyn valn)
where the legal values of the keys and values are described in the
documentation for [xargs]. These declarations are only allowed
at the top level of definitions ([defun] and [defmacro], as
shown below), and convey information such as the [guard] and
[measure] for a function.
(optimize ...)
for example, (optimize (safety 3)). This is allowed only at the top
level of [defun] forms and is probably only rarely of any
interest. See any Common Lisp documentation for more
information.
Declarations in ACL2 may occur only where dcl occurs below:
* (DEFUN name args doc-string dcl ... dcl body)
* (DEFMACRO name args doc-string dcl ... dcl body)
* (LET ((v1 t1) ...) dcl ... dcl body)
* (MV-LET (v1 ...) term dcl ... dcl body)
* (FLET ((name args dcl ... dcl body) ...))
Of course, if a form macroexpands into one of these (e.g., as [let*]
expands into nested [let]s and our er-let* expands into nested
[mv-let]s) then declarations are permitted as handled by the macros
involved.
Declare is defined in Common Lisp. See any Common Lisp documentation
for more information.
Subtopics
[Declare-stobjs]
Declaring a formal parameter name to be a single-threaded object
[Set-ignore-ok]
Allow unused formals and locals without an ignore or ignorable
declaration
[Type-spec]
Type specifiers can be used in Common Lisp type declarations and
[the] forms, and may result in improved efficiency of
execution.
[Xargs]
Extra arguments, for example to give [hints] to [defun]")
(DECLARE-STOBJS
(STOBJ DECLARE)
"Declaring a formal parameter name to be a single-threaded object
When a [defun] uses one of its formals as a single-threaded object
([stobj]), the defun must include a declaration that the formal is
to be so used. An exception is the formal ``[state],'' which if not
declared as explained below, may still be used provided an
appropriate global ``declaration'' is issued: see [set-state-ok].
If the formal in question is counters then an appropriate declaration
is
(declare (xargs :stobjs counters))
or, more generally,
(declare (xargs :stobjs (... counters ...)))
where all the single-threaded formals are listed.
For such a declaration to be legal it must be the case that all the
names have previously been defined as single-threaded objects with
[defstobj].
When an argument is declared to be single-threaded the guard of the
function is augmented by conjoining to it the condition that the
argument satisfy the recognizer for the single-threaded object.
Furthermore, the syntactic checks done to enforce the legal use of
single-threaded objects are also sufficient to allow these guard
conjuncts to be automatically proved.
The obvious question arises: Why does ACL2 insist that you declare
stobj names before using them in defuns if you can only declare
names that have already been defined with defstobj? What would go
wrong if a formal were treated as a single-threaded object if and
only if it had already been so defined?
Suppose that one user, say Jones, creates a book in which counters is
defined as a single-threaded object. Suppose another user, Smith,
creates a book in which counters is used as an ordinary formal
parameter. Finally, suppose a third user, Brown, wishes to use both
books. If Brown includes Jones' book first and then Smith's, then
Smith's function treats counters as single-threaded. But if Brown
includes Smith's book first, the argument is treated as ordinary.
ACL2 insists on the declaration to ensure that the definition is
processed the same way no matter what the context.")
(DEFABBREV
(MACROS EVENTS PROGRAMMING)
"A convenient form of macro definition for simple expansions
Examples:
(defabbrev snoc (x y) (append y (list x)))
(defabbrev sq (x) (declare (type (signed-byte 8) x)) (* x x))
General Form:
(defabbrev name (v1 ... vn) doc-string decl1 ... declk body)
where name is a new function symbol, the vi are distinct variable
symbols, and body is a term. The decli, if supplied, should be
legal declare forms; see [declare]. Doc-string, if non-nil, is an
optional string that can provide documentation but is essentially
ignored by ACL2.
Roughly speaking, the defabbrev event is akin to defining f so that
(f v1 ... vn) = body. But rather than do this by adding a new
axiom, defabbrev defines f to be a macro so that (f a1 ... an)
expands to body, with the ``formals,'' vi, replaced by the
``actuals,'' ai.
For example, if snoc is defined as shown in the first example above,
then (snoc (+ i j) temp) is just an abbreviation for
(append temp (list (+ i j))).
In order to generate efficiently executable Lisp code, the macro that
defabbrev introduces uses a [let] to bind the ``formals'' to the
``actuals.'' Consider the second example above. Logically speaking,
(sq (ack i j)) is an abbreviation for (* (ack i j) (ack i j)). But
in fact the macro for sq introduced by defabbrev actually arranges
for (sq (ack i j)) to expand to:
(let ((x (ack i j)))
(* x x))
which executes more efficiently than (* (ack i j) (ack i j)).
In the theorem prover, the let above expands to
((lambda (x) (* x x)) (ack i j))
and thence to (* (ack i j) (ack i j)).
It is important to note that the term in body should not contain a
call of name --- i.e., defabbrev should not be used in place of
defun when the function is recursive. ACL2 will not complain when
the defabbrev form is processed, but instead ACL2 will more than
likely go into an infinite loop during macroexpansion of any form
that has a call of name.
It is also important to note that the parameters of any call of a
macro defined by defabbrev will, as is the case for the parameters
of a function call, be evaluated before the body is evaluated,
since this is the evaluation order of [let]. This may lead to some
errors or unexpected inefficiencies during evaluation if the body
contains any conditionally evaluted forms like cond, case, or if.
Consider the following example.
(defabbrev foo (x y)
(if (test x) (bar y) nil))
Notice a typical one-step expansion of a call of foo (see [trans1]):
ACL2 !>:trans1 (foo expr1 expr2)
(LET ((X EXPR1) (Y EXPR2))
(IF (TEST X) (BAR Y) NIL))
ACL2 !>
Now imagine that expr2 is a complicated expression whose evaluation
is intended only when the predicate test holds of expr1. The
expansion above suggests that expr2 will always be evaluated by the
call (foo expr1 expr2), which may be inefficient (since perhaps we
only need that value when test is true of expr1). The evaluation of
expr2 may even cause an error, for example in :[program] mode if
the expression expr2 has been constructed in a manner that could
cause a guard violation unless test holds of expr1.")
(DEFABSSTOBJ
(EVENTS STOBJ)
"Define a new abstract single-threaded object
We assume familiarity with single-threaded objects; see [stobj] and
see [defstobj]. The event defabsstobj defines a so-called
``abstract stobj'', a notion we introduce briefly now and then
explain in more depth below.
The evaluation of a [defstobj] event produces logical definitions for
several functions: a recognizer, which characterizes the [stobj] in
terms of lists; a creator, which produces an initial suitable list
structure; and field accessors and updators, defined in terms of
[nth] and [update-nth]. Defabsstobj provides a way to define
alternate definitions for ``stobj primitives'' for a corresponding
single-threaded object. These stobj primitives include a
recognizer, a creator, and other ``exported'' functions. In
essence, defabsstobj establishes interface functions, or
``exports'', on a new stobj that is a copy of an indicated
``concrete'' stobj that already exists.
We begin below with an introduction to abstract [stobj]s. We then
explain the [defabsstobj] event by way of an example. We conclude
by giving summary documentation for the defabsstobj event.
For another introduction to abstract stobjs, see the paper ``Abstract
Stobjs and Their Application to ISA Modeling'' by Shilpi Goel,
Warren A. Hunt, Jr., and Matt Kaufmann, in the proceedings of {ACL2
Workshop 2013 | http://www.cs.uwyo.edu/~ruben/acl2-13}.
INTRODUCTION
We start with a brief review of [stobj]s and some potential problems
with them, followed by an introduction to abstract stobjs and how
they can avoid these problems. Prior experience with stobjs will
probably help the reader to absorb the ideas below.
Recall that single-threaded objects, or [stobj]s, provide a way for
ACL2 users to stay within the ACL2 logic, where every data object
is an atom or a [cons] of data objects, while obtaining the
benefits of fast evaluation through destructive updates. Consider
for example this very simple event.
(defstobj st fld)
This event introduces a recognizer, stp, and a creator, create-st,
for a data structure consisting of a single field accessed and
updated by functions fld and update-fld, respectively. Each of
these four primitive functions has both a logical definition, which
is used when the prover reasons about the function, and an
executable definition, which is used in raw Lisp. In the logic, stp
recognizes objects that have the requisite fields. In raw Lisp,
there is a ``live stobj'', which is an array object whose fields
correspond to those specified by the [defstobj] event, implemented
as Lisp arrays.
Here are the logical definition and the executable definition,
respectively, that are introduced for the field accessor, fld,
introduced above. Notice that since a stobj is represented in raw
Lisp using an array, the raw Lisp accessor uses a raw Lisp array
accessor, svref. (You can see all the logical and executable
definitions by evaluating the form (trace$ defstobj-axiomatic-defs
defstobj-raw-defs) before evaluating the [defstobj] form.)
; logical definition
(defun fld (st)
(declare (xargs :guard (stp st)
:verify-guards t))
(nth 0 st))
; executable (raw Lisp) definition
(defun fld (st)
(svref st 0))
Sophisticated programming with stobjs can provide efficient
implementations of algorithms, but may require the preservation of
a complex invariant. One can, of course, define a function to
implement such an invariant after introducing the stobj, as
follows.
; Introduce a stobj.
(defstobj st fld1 ... fldk)
; Define an invariant on that stobj.
(defun good-stp (st)
(declare (xargs :stobjs st))
...)
; Define some basic functions that update the stobj and preserve the
; invariant.
(defun update-st (... st ...)
(declare (xargs :stobjs st
:guard (and (good-stp st) ...)))
...)
...
; Prove that the invariant is indeed preserved by those basic functions.
(defthm good-stp-update-st
(implies (and (good-stp st)
...)
(good-stp (update-st ... st ...))))
...
; Implement algorithms built on the basic functions.
(defun foo (... st ...)
(declare (xargs :stobjs st
:guard (and (good-stp st) ...)))
... (update-st ... st ...) ...)
; Prove invariance theorems about these algorithms.
(defthm good-stp-foo
(implies (and (good-stp st)
...)
(good-stp (foo ... st ...))))
...
; Prove other properties of these algorithms.
(defthm foo-is-correct
(implies (and (good-stp st)
...)
(some-property (foo ... st ...))))
...
But there are at least two potential difficulties in using stobjs as
described above.
1. When foo is executed on concrete data in the ACL2 loop, the guard
check may be expensive because (good-stp st) is expensive.
2. Reasoning about foo (using rules like foo-is-correct above)
involves proving hypotheses of invariance theorems, which may
be complicated for the user to manage or slow for the theorem
prover.
The defabsstobj event offers an opportunity to address these issues.
It introduces a new stobj, which we call an ``abstract stobj'',
which is associated with a corresponding ``concrete stobj''
introduced by an earlier [defstobj] event. The defabsstobj event
specifies a logical (:LOGIC) and an executable (:EXEC) definition
for each primitive operation, or ``stobj primitive'', involving
that stobj. As is the case for [defstobj], the logical definition
is what ACL2 reasons about, and is appropriate to apply to an ACL2
object satisfying the logical definition of the recognizer function
for the stobj. The executable definition is applied in raw Lisp to
a live stobj, which is an array object associated with the given
stobj name.
We can picture a sequence of updates to corresponding abstract and
concrete stobjs as follows. Initially in this picture, st$a0 and
st$c0 are a corresponding abstract and concrete stobj
(respectively). Then an update, u1, is applied with :LOGIC and
:EXEC functions u$a1 and u$c1, respectively. The resulting abstract
and concrete stobj, st$a1 and st$c1, correspond as before. Then a
second update, u2, is applied with :LOGIC and :EXEC functions u$a2
and u$c2, respectively --- again preserving the correspondence. And
so on.
Abstract u$a1 u$a2 u$a3
(:logic) st$a0 --> st$a1 --> st$a2 --> ...
^ ^ ^ ^
Correspondence | | | ... |
v v v v
u$c1 u$c2 u$c3
Concrete st$c0 --> st$c1 --> st$c2 --> ...
(:exec)
We conclude this introduction with some remarks about implementation.
Consider an abstract stobj st with corresponding concrete stobj
st$c. The live stobjs for st and st$c have the same structure, but
are distinct arrays. Indeed, the raw Lisp creator function for st$c
is called to create a new initial live stobj for st. As we will see
below, reads and writes in raw Lisp to the live stobj for st are
ultimately performed using the primitive accessors and updaters
defined for st$c. One might think of the live stobjs for st and
st$c as being congruent stobjs (see [defstobj]), except that the
stobjs themselves are not congruent: the stobj primitives
introduced for st may be applied to st but not arbitrary field
updaters of st$c, for example. As one might expect, the :EXEC
function for an exported function is applied to the live stobj for
st in raw Lisp.
EXAMPLE
We present examples, with detailed comments intended to explain
abstract stobjs, in two community books:
books/misc/defabsstobj-example-1.lisp and
books/misc/defabsstobj-example-2.lisp. In this section we outline
the first of these. We suggest that after you finish this
[documentation] topic, you read through those two books.
Here is the first of two closely related defabsstobj [events] from
the book defabsstobj-example-1.lisp, but in expanded form. We will
show the abbreviated form later, which omits most of data in the
form that is immediately below. Thus most of the information shown
here is default information. We believe that the comments below
explain most or all of what you need to know in order to start
using defabsstobj, and that you will learn the remainder when you
see error messages. For example, we do not say in the comments
below that every :LOGIC and :EXEC function must be
[guard]-verified, but that is indeed a requirement.
(defabsstobj st ; The new abstract stobj is named st.
; The concrete stobj corresponding to st is st$c:
:concrete st$c
; The recognizer for the new abstract stobj is stp, which is defined to be
; st$ap in the logic, and is executed on the live stobj in raw Lisp using
; st$cp.
:recognizer (stp :logic st$ap :exec st$cp)
; The initial stobj is defined as create-st (a function of no arguments),
; which is defined logically as create-st$a, though create-st$c is invoked to
; create the initial live stobj for st. The :correspondence and :preserved
; keywords refer to proof obligations, discussed below.
:creator (create-st :logic create-st$a :exec create-st$c
:correspondence create-st{correspondence}
:preserved create-st{preserved})
; Proof obligations are generated that involve a correspondence between the
; new abstract stobj and corresponding concrete stobj. The function
; st$corr, which need not be executable (see :DOC defun-nx), takes two
; arguments, a concrete stobj and an abstract stobj. This function symbol is
; used in the statements of the proof obligations.
:corr-fn st$corr
; In this example we have four exports. In each case a new function is
; introduced that has the same signature as its :EXEC function, except that
; st$c is replaced by st. The :LOGIC and :EXEC functions are as specified,
; and the other keywords refer to proof obligations that we discuss below.
:exports ((lookup :logic lookup$a
:exec mem$ci
:correspondence lookup{correspondence}
:guard-thm lookup{guard-thm})
(update :logic update$a
:exec update-mem$ci
:correspondence update{correspondence}
:preserved update{preserved}
:guard-thm update{guard-thm})
(misc :logic misc$a
:exec misc$c
:correspondence misc{correspondence})
(update-misc :logic update-misc$a
:exec update-misc$c
:correspondence update-misc{correspondence}
:preserved update-misc{preserved}))
:doc nil)
Note that all stobj primitives (recognizer, creator, and exported
functions) are defined in the ACL2 loop in terms of their :LOGIC
functions and in raw Lisp in terms of their :EXEC functions. In the
ACL2 loop, a [defun] form defines a function, while in raw Lisp, a
[defmacro] form defines a macro (for efficiency). We first
illustrate how that works for the recognizer. (You can see all the
logical and executable definitions by evaluating the form (trace$
defabsstobj-axiomatic-defs defabsstobj-raw-defs) before evaluating
the [defstobj] form.)
; In the ACL2 loop:
(defun stp (st)
(declare (xargs :guard 't))
(st$ap st))
; In raw Lisp:
(defmacro stp (&rest args) (cons 'st$cp args))
The definitions are made similarly for exported functions, with
[guard]s derived from their :LOGIC functions as follows. Consider
the exported function update in our example. Its :LOGIC function,
update$a, has formals (k val st$a) and the following guard.
(and (and (integerp k) (<= 0 k) (<= k 49))
(and (integerp val) (<= 0 val))
(st$ap st$a)
(mem$c-entryp val))
The formals of update are obtained by starting with the formals of
its :EXEC function, update-mem$ci --- which are (i v st$c) --- and
replacing the concrete stobj name st$c by the new stobj name st.
The formals of update are thus (i v st). The guard for update is
obtained in two steps. The first step is to substitute the formals
of update for the formals of update$a in the guard for update$a, to
obtain the following.
(and (and (integerp i) (<= 0 i) (<= i 49))
(and (integerp v) (<= 0 v))
(st$ap st)
(mem$c-entryp v))
The second step is to replace, for each new stobj primitive p, the
:LOGIC function for p by p itself. The only :LOGIC function
occurring in the formula just above is st$ap, which is the :LOGIC
funcction for stp. The guard for update is thus as follows.
(and (and (integerp i) (<= 0 i) (<= i 49))
(and (integerp v) (<= 0 v))
(stp st)
(mem$c-entryp v))
We turn now to the proof obligations, as promised above. There are
three types: :CORRESPONDENCE, :PRESERVED, and :GUARD-THM. All
required lemmas may be printed simply by defining the necessary
:LOGIC and :EXEC functions and then submitting the defabsstobj
event. (To advanced users: also see [defabsstobj-missing-events]
for a utility that returns the required formulas in translated
form.) Although the defabsstobj event will fail if the required
lemmas have not been proved, first it will print the [defthm] forms
that must be admitted in order to complete submission of the
defabsstobj event. (Note that although the those theorems are
stated exactly in the form expected by the system, you are welcome
to supply whatever :[rule-classes] you prefer, even though the
system creates :rule-classes nil by default.)
The detailed theory explaining the need for these lemmas may be found
in a comment in ACL2 source file other-events.lisp, in a comment
entitled ``Essay on the Correctness of Abstract Stobjs''. Here, we
give an informal sense of the importance of these lemmas as we
present examples of them. Fundamental is the notion of evaluation
in the logic versus evaluation using live stobjs, where one
imagines tracking the current value of each abstract stobj during
each of these two evaluations.
We start with the :CORRESPONDENCE lemmas. These guarantee that
evaluation in the logic agrees with evaluation using live stobjs,
in the sense that the only difference is between a logical stobj
and a live stobj, where the two correspond in the sense of the
function specified by :CORR-FN. We start with the :CREATOR function
where the statement is quite simple, stating that the :CORR-FN
holds initially.
(defthm create-st{correspondence}
(st$corr (create-st$c) (create-st$a)))
For the exported functions, there are essentially two cases. If an
exported function returns other than the new abstract stobj, then
the theorem asserts the equality of the results of applying the
:LOGIC and :EXEC functions for the exported function. Hypotheses
include the :CORR-FN correspondence followed by the [guard] for the
:LOGIC function, which is stated in terms of the formal parameters
of the :EXEC function except using the abstract stobj (here, st) in
place of the concrete stobj (here, st$c). The conclusion uses the
:EXEC formals, modified in the call of the :LOGIC function (here,
lookup$a) to use the abstract stobj, as in the hypotheses.
(defthm lookup{correspondence}
(implies (and (st$corr st$c st)
(integerp i) (<= 0 i) (<= i 49)
(st$ap st))
(equal (mem$ci i st$c)
(lookup$a i st)))
:rule-classes nil)
By contrast, if the exported function returns the new abstract stobj,
then the conclusion uses the correspondence function insted of
EQUAL, as in the following.
(defthm update{correspondence}
(implies (and (st$corr st$c st)
(integerp i) (<= 0 i) (<= i 49)
(integerp v) (<= 0 v)
(st$ap st)
(mem$c-entryp v))
(st$corr (update-mem$ci i v st$c)
(update$a i v st)))
:rule-classes nil)
For exported functions that return multiple values, such conclusions
are conjoined together over the returned values.
The :PRESERVED lemmas guarantee that updates to the abstract stobj
preserve its recognizer. The fact that every exported function has
this property provides justification for an optimization performed
by ACL2 during generation of proof obligations for [guard]
verification, by assuming that the recognizer always holds. The
:PRESERVED lemma for the :CREATOR shows that the recognizer holds
initially.
(defthm create-st{preserved}
(st$ap (create-st$a)))
Here is a typical such lemma, for the exported function update. Note
that there is no such lemma for lookup, since lookup does not
return st.
(defthm update{preserved}
(implies (and (integerp i) (<= 0 i) (<= i 49)
(integerp v) (<= 0 v)
(st$ap st)
(mem$c-entryp v))
(st$ap (update$a i v st))))
Finally, we consider the :GUARD-THM lemmas. These serve to guarantee
that the [guard] holds for each call of an :EXEC function. During
guard verification, logical definitions are used; in particular,
since each exported function is defined in the logic as the
corresponding call of its :LOGIC function, guard verification shows
that each call of the :LOGIC function for an exported function
satisfies that function's guard. But why is this true for raw Lisp
evaluation using live stobjs, where the :EXEC function is called
for an exported function? The :GUARD-THM lemmas provide the answer,
as they state that if the :LOGIC function's guard holds, then the
:EXEC function's guard holds. Here is an example. Note that the
hypotheses come from the correspondence of the concrete and
abstract function as guaranteed by the :CORR function, together
with the guard of the :LOGIC function; and the conclusion comes
from the guard of the :EXEC function.
(defthm lookup{guard-thm}
(implies (and (st$corr st$c c)
(integerp i)
(<= 0 i)
(<= i 49)
(st$ap st))
(and (integerp i)
(<= 0 i)
(< i (mem$c-length st$c))))
:rule-classes nil)
We conclude this EXAMPLE section by showing a short form for the
defabsstobj form displayed above.
(defabsstobj st
:exports ((lookup :exec mem$ci)
(update :exec update-mem$ci)
misc update-misc))
SUMMARY DOCUMENTATION
The General Form is as shown below, where the order of keywords is
unimportant. Duplicate keywords are discouraged; while permitted,
only the first (leftmost) occurrence of a given keyword is used.
Only the :exports keyword is required.
(defabsstobj st
:concrete concrete
:recognizer recognizer
:creator creator
:corr-fn corr-fn
:congruent-to congruent-to
:protect-default protect-default
:exports (e1 ... ek)
:doc doc)
The keyword argument :EXPORTS must be supplied, and missing or nil
keyword arguments have defaults as indicated below. All arguments
must satisfy the conditions below.
Before we describe the arguments, we define a notion of a ``function
spec'' and its ``completion''. A function spec is either a symbol
or else a list of the form
(fn :kwd1 val1 ... :kwdn valn),
that is, a symbol followed by a [keyword-value-listp]. We view the
case of a symbol, s, as the function spec (s), with no keywords.
There must be no duplicate keywords. In each case that we expect a
function spec, the context provides a set of valid keywords for
that function spec; it is an error to provide any other keyword in
the function spec. Each function spec is interpreted as its
``completion'', obtained by extending the function spec with a
default value for each valid keyword as indicated below. With that
interpretation, the ``exported function'' of a function spec is its
car, and that function symbol and each keyword value must be a
guard-verified function symbol; and moreover, the :EXEC function
must not include the new abstract stobj name, st, among its
formals.
We are ready to describe the arguments of defabsstobj.
St is a symbol, which names the new abstract stobj.
Concrete is the name of an existing stobj that is not an abstract
stobj, i.e., was introduced with [defstobj] (not
[defabsstobj]).
Recognizer is a function spec (for the recognizer function). The
valid keywords are :LOGIC and :EXEC. The default for recognizer
is obtained by adding the suffix \"P\" to name. The default value
for :LOGIC is formed by adding the suffix \"$AP\" to recognizer;
for :EXEC, by adding the suffix \"$CP\". The :EXEC function must
be the recognizer for the specified :CONCRETE stobj.
Creator is a function spec (for the creator function). The valid
keywords are :LOGIC and :EXEC. The default for creator is
obtained by adding the prefix \"CREATE-\" to name. The default
value for :LOGIC is formed by adding the suffix \"$A\" to
creator; for :EXEC, by adding the suffix \"$C\". The :CREATOR
function must be the creator for the specified :CONCRETE stobj,
as ACL2 checks that the :CREATOR function takes no arguments
and returns the :CONCRETE stobj.
Corr-fn is a known function symbol that takes two arguments (for the
correspondence theorems). The default for corr-fn is obtained
by adding the suffix \"$CORR\" to name.
Congruent-to should either be nil (the default) or the name of an
abstract stobj previously introduced (by [defabsstobj]). In the
latter case, the current and previous abstract stobj should
have the same concrete stobj (not merely congruent concrete
stobjs), and their :EXPORTS fields should have the same length
and also correspond, as follows: the ith export of each should
have the same :LOGIC and :EXEC symbols. See [defstobj] for more
about congruent stobjs. Note that if two names are congruent,
then they are either both ordinary stobjs or both abstract
stobjs.
Protect-default should either be nil (the default) or t. It provides
the value of keyword :PROTECT for each member of exports that
does not explicitly specify :PROTECT. See the discussion of
exports below.
An important aspect of the congruent-to parameter is that if it is
not nil, then the checks for lemmas --- {CORRESPONDENCE},
{GUARD-THM}, and {PRESERVED} --- are omitted. Thus, the values
of keyword :CORR-FN, and the values of keywords
:CORRESPONDENCE, :GUARD-THM, and :PRESERVED in each export (as
we discuss next), are irrelevant; they are not inferred and
they need not be supplied.
The value of :EXPORTS is a non-empty true list. Each ei is a function
spec (for an exported function). The valid keywords are :LOGIC,
:EXEC, :CORRESPONDENCE, and :GUARD-THM, :PROTECT, and also
:PRESERVED if and only if the specified :EXEC function returns
the :CONCRETE stobj. The default values for all of these
keywords except :PROTECT are obtained by respectively adding
the suffix \"$A\" \"$C\", \"{CORRESPONDENCE}\", \"{GUARD-THM}\", or
\"{PRESERVED}\". For :PROTECT, the default is nil unless the
defabsstobj event specifies :PROTECT-DEFAULT t.
Doc, if non-nil, is a string that can provide documentation but is
essentially ignored by ACL2.
Not shown is the keyword, :MISSING; the effect of :missing t is to
turn the call of defabsstobj into a corresponding call of
[defabsstobj-missing-events].
Note that a defabsstobj event will fail if the required lemmas ---
that is, those for valid keywords :CORRESPONDENCE, :GUARD-THM, and
:PRESERVED --- have not been proved, unless proofs are being
skipped. The exemption when skipping proofs allows the supporting
lemmas to be [local] to [books] and [encapsulate] [events]. If the
[ld] special [ld-skip-proofsp] is t, then the missing [events] are
printed with a warning before the defabsstobj event is admitted;
but if ld-skip-proofsp is the symbol INCLUDE-BOOK, then that
warning is omitted. (Also see [skip-proofs] and see
[ld-skip-proofsp].) If however proofs are not being skipped, then
the defabsstobj event will fail after printing the missing events.
Advanced users may wish to see [defabsstobj-missing-events] for a
utility that returns a data structure containing the missing
lemmas.
Let st be an abstract stobj with corresponding concrete stobj st$c.
let f be an exported function for st and let f$a and f$c be the
corresponding :LOGIC and :EXEC functions, respectively. The formals
of f are obtained by taking the formals of f$c and replacing st$c
by st. The [guard] for f is derived as follows from the guard of
f$a. First, the formals of f$a are replaced by the formals of f in
the guard of f$a, to obtain a term we denote here as guard-pre. Now
for each exported function symbol g of st with corresponding :LOGIC
function g$a, form a functional substitution by consing g$a with g.
Finally, apply that functional substitution to guard-pre; the
result is the guard of f. That guard must satisfy the usual
conditions of a guard: thus, it must return a single non-[stobj]
value and satisfy normal syntactic restrictions, including
single-threadedness in its handling of stobjs.
Remark. Because of how guards are created for exported functions, and
in particular because :LOGIC functions are replaced as discussed
above, a good discipline is to define :LOGIC functions that are not
intended for general use, but are intended only for use as :LOGIC
functions of corresponding stobj primitives. For example, suppose
that you use length as the :LOGIC function for some stobj
primitive, f (as opposed to using your own function, say,
foo-length or foo$a). Then every call of length will be replaced by
f when creating the guard of a stobj primitive from the guard of
its :LOGIC function. This might not be what you intended if you
were using length in that guard simply to compute the length of an
ordinary list.
There are a few additional restrictions, as follows.
All exported function names must be new (unless redefinition is on;
see [ld-redefinition-action]), and there must be no duplicates
among them.
The :CONCRETE stobj name must be a formal parameter of the :EXEC fn
of every function spec, except for the :CREATOR function spec.
Also the input signatures of the :LOGIC and :EXEC function for
a function spec must agree, except perhaps at the position of
that :CONCRETE formal.
For function specs other than the :CREATOR function spec, the output
signatures of the :LOGIC and :EXEC functions must have the same
length and must agree, except perhaps at position p_out of the
:CONCRETE stobj in the :EXEC function's output. If p_in is the
position of the :CONCRETE stobj in the :EXEC function's
formals, then the :LOGIC function's output at position p_out
should match the :LOGIC function's formal at position p_in.
The :PROTECT keyword is something that you should ignore unless you
get an error message about it, pertaining to modifying the
concrete stobj non-atomically. In that case, you can eliminate
the error by providing :PROTECT t in the function spec, or by
providing defabsstobj keyword argument :PROTECT-DEFAULT t at
the top level. The above explanation is probably all you need
to know about :PROTECT, but just below is a more complete
explanation for those who desire it. Further information is
also available if you need it; see [set-absstobj-debug], and
see the example uses of these keywords in community book
books/misc/defabsstobj-example-2.lisp.
For those who are interested, here is a more detailed discussion of
:PROTECT and :PROTECT-DEFAULT, as promised above. It applies to any
function spec for an export (hence not to the :CREATOR function
spec). If the :EXEC function is a stobj primitive, then clearly the
following property holds: any execution of a call of that function
can only update the concrete stobj at most once --- i.e.,
modification of the concrete stobj is atomic. ACL2 can deduce this
property not only for stobj primitives but for many other functions
as well. However, if ACL2 cannot deduce this property, then it will
cause an error saying that the :EXEC function ``appears capable of
modifying the concrete stobj, <stobj_name>, non-atomically.'' That
message also explains how to eliminate this error: provide :PROTECT
t for the function spec. Alternatively, all function specs without
an explicit :PROTECT keyword can be implicitly supplied :PROTECT t
by supplying the value t for the :PROTECT-DEFAULT keyword parameter
of the defabsstobj event. However, beware that when :PROTECT is t,
the generated raw Lisp code runs slightly less efficiently ---
though perhaps with negligible efficiency loss if the :EXEC
function is not trivial. Community books
books/misc/defabsstobj-example-3.lisp and
books/misc/defabsstobj-example-4.lisp provide related information.
We conclude with some remarks.
Unlike [defstobj], there is no :renaming argument. Instead, the
scheme described above provides a flexible way to assign names.
Also unlike [defstobj], there is no :inline or :non-memoizable
argument; :inline is essentially t, in the sense that stobj
primitives are macros in raw Lisp; and the :non-memoizable argument
is derived implicitly from the value of that argument (nil by
default) for the corresponding concrete stobj.
Those who use [hons-enabled] features, including function memoization
(see [memoize]), may be aware that the memo table for a function is
flushed whenever it is the case that one of its stobj inputs is
updated. In fact, such flushing happens even when a stobj that is
congruent to one of its stobj inputs is updated. For that purpose,
an abstract stobj is considered to be congruent to its
corresponding concrete stobj.
Subtopics
[Set-absstobj-debug]
Obtain debugging information upon atomicity violation for an
abstract stobj")
(DEFABSSTOBJ-MISSING-EVENTS
(EVENTS)
"Obtain the [events] needed to admit a [defabsstobj] event
We assume familiarity with [defabsstobj]. Defabsstobj-missing-events
is a macro is for advanced users (who, for example, understand the
role of the translate and untranslate functions), who want
programmatic access to the [defthm] events required to admit a
specific defabsstobj event.
This macro has the same syntax as [defabsstobj] --- to use it, just
replace a call of [defabsstobj] by a call of
defabsstobj-missing-events on the same arguments. The result is an
error triple (mv erp val state). If erp is nil, then val is the
list of all objects (name formula . old-formula), where a [defthm]
event named name remains to be admitted whose translated formula is
formula, and where old-formula is nil unless the indicated event
already exists (hence with a different formula), in which case
old-formula is the existing translated formula.
To build a [defthm] event from the above value, val, we suggest
evaluating a form like (untranslate formula t (w state)).")
(DEFATTACH
(EVENTS)
"Execute constrained functions using corresponding attached functions
This [documentation] topic is organized into the following sections:
Introductory example.
Syntax and semantics of defattach.
Three primary uses of defattach.
Miscellaneous remarks, with discussion of possible user errors.
Please see [encapsulate] if you intend to use defattach but are not
already familiar with the use of encapsulate to introduce
constrained functions.
See community book books/misc/defattach-example.lisp for a small
example. it illustrates how defattach may be used to build
something like ``higher-order'' programs, in which constrained
functions may be refined to different executable functions. More
uses of defattach may be found in the ACL2 source code,
specifically, file boot-strap-pass-2.lisp.
The argument :skip-checks t enables easy experimentation with
defattach, by permitting use of :[program] mode functions and the
skipping of semantic checks. Also permitted is :skip-checks nil
(the default) and :skip-checks :cycles, which turns off only the
update of the extended ancestor relation (see below) and hence the
check for cycles in this relation; see below. We do not make any
logical claims when the value of :skip-checks is non-nil; indeed, a
trust tag is required in this case (see [defttag]). Note that the
interaction of memoization and attachments is not tracked for
attachments introduced with a non-nil value of :skip-checks. For
more discussion of :skip-checks t, see [defproxy]; we do not
discuss :skip-checks further, here.
Introductory example.
We begin with a short log illustrating the use of defattach. Notice
that after evaluating the event (defattach f g), a call of the
constrained function f is evaluated by instead calling g on the
arguments.
ACL2 !>(encapsulate
((f (x) t :guard (true-listp x)))
(local (defun f (x) x))
(defthm f-property
(implies (consp x) (consp (f x)))))
[... output omitted ...]
T
ACL2 !>(defun g (x)
(declare (xargs :guard (or (consp x) (null x))))
(cons 17 (car x)))
[... output omitted ...]
G
ACL2 !>(f '(3 4)) ; undefined function error
ACL2 Error in TOP-LEVEL: ACL2 cannot ev the call of undefined function
F on argument list:
((3 4))
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
ACL2 !>(defattach f g)
[... output omitted ...]
:ATTACHMENTS-RECORDED
ACL2 !>(f '(3 4)) ; f is evaluated using g
(17 . 3)
ACL2 !>(trace$ f g)
((F) (G))
ACL2 !>(f '(3 4)) ; f is evaluated using g
1> (ACL2_*1*_ACL2::F (3 4))
2> (ACL2_*1*_ACL2::G (3 4))
3> (G (3 4))
<3 (G (17 . 3))
<2 (ACL2_*1*_ACL2::G (17 . 3))
<1 (ACL2_*1*_ACL2::F (17 . 3))
(17 . 3)
ACL2 !>(defattach f nil) ; unattach f (remove its attachment)
[... output omitted ...]
:ATTACHMENTS-RECORDED
ACL2 !>(f '(3 4)) ; undefined function error once again
1> (ACL2_*1*_ACL2::F (3 4))
ACL2 Error in TOP-LEVEL: ACL2 cannot ev the call of undefined function
F on argument list:
((3 4))
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
ACL2 !>
Syntax and semantics of defattach.
The log above shows that the event (defattach f g) allows g to be
used for evaluating calls of f. From a logical perspective, the
evaluation takes place in the addition to the current session of an
``attachment equation'' axiom (universally quantified over all x)
for each defattach event:
(equal (f x) (g x)) ;;; attachment equation axiom for (defattach f g)
Below we explain defattach in some detail. But it is important to
keep in mind that evaluation with the attachment equations takes
place in an extension of the logical theory of the session. ACL2
guarantees that this so-called ``evaluation theory'' remains
consistent, assuming the absence of [defaxiom] [events] from the
user. This guarantee is a consequence of a more general guarantee:
an ACL2 logical [world] exists in which (loosely speaking) the
attachment equation for (defattach f g), as (defun f (...) (g
...)), takes the place of the original defining event for f, for
each defattach event. This more general guarantee holds even if
there are [defaxiom] events, though as explained below, no function
symbol that syntactically supports a defaxiom formula is allowed to
get an attachment. A deeper discussion of the logical issues is
available (but not intended to be read by most users) in a long
comment in the ACL2 source code labeled ``Essay on Defattach.''
Example Forms:
(defattach f g) ; call g in place of calling constrained function f
(defattach (f g)) ; same as just above
(defattach (f g :hints ((\"Goal\" :in-theory (enable foo)))))
; equivalent to first form above, except with hints for the
; proof that the guard of f implies the guard of g
(defattach (f g :hints ((\"Goal\" :in-theory (enable foo)))
:otf-flg t))
; as above, except with an :otf-flg of t for the proof that
; the guard of f implies the guard of g
(defattach (f g)
:hints ((\"Goal\" :use my-thm)))
; equivalent to first form above, except with hints for the
; proof that the constraints on f hold for g
(defattach (f g)
:hints ((\"Goal\" :use my-thm))
:otf-flg t)
; as above, except with an :otf-flg of t for the proof that
; the constraints on f hold for g
(defattach (f g)
(h j)) ; Attach g to f and attach j to h
(defattach (f g :attach nil)
(h j)) ; Same as just above, including the same proof obligations,
; except for one difference: because of :attach nil, calls
; of f will not be evaluated, i.e., there will be no
; executable attachment of g to f
(defattach (f nil)
(h j)) ; Attach j to h and unattach f
(defattach (f g :hints ((\"Goal\" :in-theory (enable foo))))
(h j :hints ((\"Goal\" :in-theory (enable bar))))
:hints ((\"Goal\" :use my-thm)))
; Attach g to f and attach j to h, with hints:
; - For proving that the guard of f implies the guard of g,
; enable foo;
; - For proving that the guard of h implies the guard of j,
; enable bar; and
; - For proving that the constraints on f and h hold for
; g and j (respectively), use theorem my-thm.
(defattach f nil) ; remove the attachment of f, if any (e.g., g above)
(defattach (f nil)) ; same as just above
General Forms:
(defattach f g) ; single attach or, if g is nil, unattach
(defattach (f1 g1 :kwd val ...)
...
(fk gk :kwd' val' ...)
:kwd'' val'' ...)
where each indicated keyword-value pair is optional and each keyword
is one of :ATTACH, :HINTS, :OTF-FLG, or :INSTRUCTIONS. The value of
each :ATTACH keyword is either t or nil, with default t except that
the value of :ATTACH at the ``top level,'' after each entry (fi gi
...), is the default for each :ATTACH keyword supplied in such an
entry. We discuss the :ATTACH keyword later in this [documentation]
topic. The associated values for the other keywords have the usual
meanings for the proof obligations described below: the guard proof
obligation for keywords within each (fi gi ...) entry, and the
constraint proof obligation for keywords at the top level. No
keyword may occur twice in the same context, i.e., within the same
(fi gi ...) entry or at the top level; and :INSTRUCTIONS may not
occur in the same context with :HINTS or :OTF-FLG.
The first General Form above is simply an abbreviation for the form
(defattach (f g)), which is an instance of the second General Form
above. For the second General Form we say that gi is ``attached
to'' fi (by the defattach event) if gi is not nil, and otherwise we
say that fi is ``unattached'' (by the defattach event). It is also
convenient to refer to <fi,gi> as an ``attachment pair'' (of the
event) if gi is not nil. We may refer to the set of fi as the
``attachment nest'' of each fi.
We start with a brief introduction to the first General Form in the
case that g is not nil. This form arranges that during evaluation,
with exceptions noted below, every call of the constrained function
symbol f will in essence be replaced by a call of the function
symbol g on the same arguments. We may then refer to g as the
``attachment of'' f, or say that ``g is attached to f.'' Notable
exceptions, where we do not use attachments during evaluation, are
for macroexpansion, evaluation of [defconst] and [defpkg] terms,
evaluation during [table] events, some [stobj] operations including
all [updates], and especially evaluation of ground terms (terms
without free variables) during proofs. However, even for these
cases we allow the use of attachments in the first argument of
[prog2$] and, more generally, the next-to-last (i.e., second)
argument of [return-last] when its first argument is not of the
form 'm for some macro, m.
To see why attachments are disallowed during evaluation of ground
terms during proofs (except for the [prog2$] and [return-last]
cases mentioned above), consider the following example.
(defstub f (x) t)
(defun g (x) (+ 3 x))
(defattach f g)
If the form (f 2) is submitted at the ACL2 prompt, the result will be
5 because the attachment g of f is called on the argument, 2.
However, during a proof the term (f 2) will not be simplified to 5,
since that would be unsound, as there are no axioms about f that
would justify such a simplification.
For the case that g is nil in the first General Form above, the
result is the removal of the existing attachment to f, if any.
After this removal, calls of f will once again cause errors saying
that ``ACL2 cannot ev the call of undefined function f ...''. In
this case not only is the previous attachment to f removed;
moreover, for every function symbol f' in the attachment nest of f
in the defattach event that introduced the existing attachment to
f, then f' is unattached. (An example near the end of this
[documentation] topic shows why this unattachment needs to be
done.) Such removal takes place before the current defattach is
processed, but is restored if the new event fails to be admitted.
We focus henceforth on the second General Form. There must be at
least one attachment, i.e., i must be at least 1. All keywords are
optional; their role is described below. The fi must be distinct
constrained function symbols, that is, function symbols all
introduced in [signature]s of [encapsulate] [events] (or macros
such as [defstub] that generate [encapsulate] events). Each non-nil
gi is a :[logic]-mode function symbol that has had its guards
verified, with the same [signature] as fi (though formal parameters
for fi and gi may have different names). (Note: The macro
defattach!, defined in community book books/misc/defattach-bang,
avoids this restriction.) This event generates proof obligations
and an ordering check, both described below. The effect of this
event is first to remove any existing attachments for all the
function symbols fi, as described above for the first General Form,
and then to attach each gi to fi.
Proof obligations must be checked before making attachments. For this
discussion we assume that each gi is non-nil (otherwise first
remove all attachment pairs <fi,gi> for which gi is nil). Let s be
the functional substitution mapping each fi to gi. For any term u,
we write u\\s for the result of applying s to u; that is, u\\s is the
``functional instance'' obtained by replacing each fi by gi in u.
Let G_fi and G_gi be the guards of fi and gi, respectively. Let
G_fi' be the result of replacing each formal of fi by the
corresponding formal of gi in G_fi. ACL2 first proves, for each i
(in order), the formula (implies G_fi' G_gi)\\s. If this sequence of
proofs succeeds, then the remaining formula to prove is the
functional instance C\\s of the conjunction C of the constraints on
the symbols fi; see [constraint]. This last proof obligation is
thus similar to the one generated by functional instantiation (see
[constraint]). As with functional instantiation, ACL2 stores the
fact that such proofs have been done so that they are avoided in
future events (see [lemma-instance]). Thus, you will likely avoid
some proofs with the sequence
(defattach f g)
(defattach f nil)
(defattach f g)
(defattach f nil)
...
rather than the sequence:
(defattach f g)
:u
(defattach f g)
:u
...
It remains to describe an ordering check. We begin with the following
motivating example.
(defstub f (x) t) ; constrained function with no constraints
(defun g (x) (declare (xargs :guard t)) (not (f x)))
(defattach f g) ; ILLEGAL!
Were the above defattach event to succeed, the evaluation theory
(discussed above) would be inconsistent: (f x) equals (g x) by the
new attachment equation, which in turn equals (not (f x)) by
definition of g. The evaluation would therefore be meaningless.
Also, from a practical perspective, there would be an infinite loop
resulting from any call of f.
We consider a function symbol g to be an ``extended immediate
ancestor of'' a function symbol f if either of the following two
criteria is met: (a) g occurs in the formula that introduces f
(i.e., definition body or constraint) and g is introduced by an
event different from (earlier than) the event introducing f; or (b)
g is attached to f. For a proposed defattach event, we check that
this relation has no cycles, where for condition (b) we include all
attachment pairs that would result, including those remaining from
earlier defattach events.
Of course, a special case is that no function symbol may be attached
to itself. Similarly, no function symbol may be attached to any of
its ``siblings'' --- function symbols introduced by the same event
--- as siblings are considered equivalent for purposes of the
acyclicity check.
Three primary uses of defattach.
We anticipate three uses of defattach:
(1) Constrained function execution
(2) Sound modification of the ACL2 system
(3) Program refinement
We discuss these in turn.
(1) The example at the beginning of this [documentation] illustrates
constrained function execution.
(2) ACL2 is written essentially in itself. Thus, there is an
opportunity to attaching to system functions. For example,
encapsulated function too-many-ifs-post-rewrite, in the ACL2 source
code, receives an attachment of too-many-ifs-post-rewrite-builtin,
which implements a heuristic used in the rewriter. To find all such
examples, search the source code for the string `-builtin'.
Over time, we expect to continue replacing ACL2 source code in a
similar manner. We invite the ACL2 community to assist in this
``open architecture'' enterprise; feel free to email the ACL2
implementors if you are interested in such activity.
(3) Recall that for an attachment pair <f,g>, a proof obligation is
(speaking informally) that g satisfies the constraint on f. Yet
more informally speaking, g is ``more defined'' than f; we can
think of g as ``refining'' f. With these informal notions as
motivation, we can view defattach as providing refinement though
the following formal observation: the evaluation theory extends the
theory of the ACL2 session, specifically by the addition of all
attachment equations. For the logic-inclined, it may be useful to
think model-theoretically: The class of models of the evaluation
theory is non-empty but is a subset of the class of models of the
current session theory.
Miscellaneous remarks, with discussion of possible user errors.
We conclude with remarks on some details.
A defattach event is never redundant (see [redundant-events]); in
that sense it is analogous to [in-theory].
As mentioned above, the use of attachments is disabled for evaluation
of ground terms during proofs. However, attachments can be used on
code during the proof process, essentially when the ``program
refinement'' is on theorem prover code rather than on functions we
are reasoning about. The attachment to too-many-ifs-post-rewrite
described above provides one example of such attachments. Meta
functions and clause-processor functions can also have attachments,
with the restriction that no common ancestor with the evaluator can
have an attachment; see [evaluator-restrictions].
For an attachment pair <f,g>, evaluation of f never consults the
[guard] of f. Rather, control passes to g, whose guard is checked
if necessary. The proof obligation related to guards, as described
above, guarantees that any legal call of f is also a legal call of
g. Thus for guard-verified code that results in calls of f in raw
Lisp, it is sound to replace these calls with corresponding calls
of g.
Defattach events are illegal inside any [encapsulate] event with a
non-empty [signature] unless they are [local] to the [encapsulate].
We next discuss a restriction based on a notion of a function symbol
syntactically supporting an event. Function symbol f is ancestral
in event E if either f occurs in E, or (recursively) f occurs in an
event E' that introduces some function symbol g that is ancestral
in E. We require that no function symbol ancestral in the formula
of a [defaxiom] event may have an attachment. Theoretical reasons
are discussed in comments in the ACL2 source code, but here we give
a little example showing the need for some such restriction:
without it, we show how to prove nil!
(defn g1 () 1)
(defn g2 () 2)
(defstub f1 () t)
(defstub f2 () t)
(defund p (x)
(declare (ignore x))
t)
(defevaluator evl evl-list
((p x)))
(defaxiom f1-is-f2
(equal (f1) (f2)))
(defun meta-fn (x)
(cond ((equal (f1) (f2))
x)
(t *nil*)))
(defthm bad-meta-rule
(equal (evl x a)
(evl (meta-fn x) a))
:rule-classes ((:meta :trigger-fns (p))))
(defattach f1 g1)
(defattach f2 g2)
(defthm contradiction
nil
:hints ((\"Goal\" :use ((:instance (:theorem (not (p x)))
(x t)))))
:rule-classes nil)
To see all attachments: (all-attachments (w state)). However, note
that attachments introduced with a non-nil value of :skip-checks
will be omitted from this list. To obtain the attachment to a
function symbol FN, without the above restriction and with value
nil if there is no attachment to FN: (cdr (attachment-pair 'FN (w
state))).
Next we discuss the :ATTACH keyword. There is rarely if ever a reason
to specify :ATTACH T, but the following (admittedly contrived)
example shows why it may be necessary to specify :ATTACH NIL. First
we introduce three new function symbols.
(defstub f (x) t)
(defun g (x)
(f x))
(encapsulate ((h (x) t))
(local (defun h (x) (g x)))
(defthm h-prop
(equal (h x) (g x))))
Now suppose we want to attach the function [ACL2-numberp] to both f
and h.
(defattach (f acl2-numberp) (h acl2-numberp))
Such an attempt fails, because the following constraint is generated
but is not a theorem: (EQUAL (ACL2-NUMBERP X) (G X)). Clearly we
also need to attach to g as well.
(defattach (f acl2-numberp) (h acl2-numberp) (g acl2-numberp))
But this fails for a different reason, as explained by the error
message:
ACL2 Error in ( DEFATTACH (F ACL2-NUMBERP) ...): It is illegal to
attach to function symbol G, because it was introduced with DEFUN.
See :DOC defattach.
That is: logically, we need to attach acl2-numberp to g, but we
cannot actually attach to g because it was introduced with [defun],
not with [encapsulate]. So we specify :ATTACH NIL for the
attachment to g, saying that no actual attachment should be made to
the code for g, even though for logical purposes we should consider
that g has been given the indicated attachment.
(defattach (f acl2-numberp) (h acl2-numberp) (g acl2-numberp :attach nil))
Finally, we can check that f, g, and h execute as expected.
ACL2 !>(assert-event (and (f 3)
(not (f t))
(g 3)
(not (g t))
(h 3)
(not (h t))))
:PASSED
ACL2 !>
We conclude with an example promised above, showing why it is
necessary in general to unattach all function symbols in an
existing attachment nest when unattaching any one of those function
symbols. Consider the following example.
(defstub f1 () t)
(encapsulate ((f2 () t))
(local (defun f2 () (f1)))
(defthm f2=f1 (equal (f2) (f1))))
(encapsulate ((f3 () t))
(local (defun f3 () (f1)))
(defthm f3=f1 (equal (f3) (f1))))
(defun four () (declare (xargs :guard t)) 4)
(defun five () (declare (xargs :guard t)) 5)
(defattach (f1 four) (f2 four))
(defattach (f1 five) (f3 five))
The second defattach replaces erases the existing attachment pair
<f1,four> before installing the new attachment pairs <f1,five> and
<f3,five>. After the second defattach, both (f1) and (f3) evaluate
to 5. Now suppose that the attachment pair <f2,four> were not
erased. Then we would have (f1) evaluating to 5 and (f2) evaluating
to 4, contradicting the constraint f2=f1. The evaluation theory
would thus be inconsistent, and at a more concrete level, the user
might well be surprised by evaluation results if the code were
written with the assumption specified in the constraint f2=f1.
Subtopics
[Ignored-attachment]
Why attachments are sometimes not used")
(DEFAULT
(ARRAYS ACL2-BUILT-INS)
"Return the :default from the [header] of a 1- or 2-dimensional array
Example Form:
(default 'delta1 a)
General Form:
(default name alist)
where name is an arbitrary object and alist is a 1- or 2-dimensional
array. This function returns the contents of the :default field of
the [header] of alist. When [aref1] or [aref2] is used to obtain a
value for an index (or index pair) not bound in alist, the default
value is returned instead. Thus, the array alist may be thought of
as having been initialized with the default value. default operates
in virtually constant time if alist is the semantic value of name.
See [arrays].
Function: <default>
(defun
default (name l)
(declare (xargs :guard (or (array1p name l) (array2p name l))))
(cadr (assoc-keyword :default (cdr (header name l)))))")
(DEFAULT-BACKCHAIN-LIMIT
(RULE-CLASSES)
"Specifying the backchain limit for a rule
See [backchain-limit].
The initial value is (nil nil). To inspect the current value (as
explained elsewhere; see [backchain-limit]):
(default-backchain-limit wrld :ts) ; for type-set reasoning
(default-backchain-limit wrld :rewrite) ; for rewriting")
(DEFAULT-DEFUN-MODE
(MISCELLANEOUS)
"The default [defun-mode] of [defun]'d functions
When a [defun] is processed and no :mode xarg is supplied, the
function default-defun-mode is used. To find the default
[defun-mode] of the current ACL2 [world], type (default-defun-mode
(w state)). See [defun-mode] for a discussion of [defun-mode]s. To
change the default [defun-mode] of the ACL2 [world], type one of
the keywords :[program] or :[logic].
The default ACL2 [prompt] displays the current default [defun-mode]
by showing the character p for :[program] mode, and omitting it for
:[logic] mode; see [default-print-prompt]. The default [defun-mode]
may be changed using the keyword [command]s :[program] and
:[logic], which are equivalent to the [command]s (program) and
(logic). Each of these names is documented separately: see
[program] and see [logic]. The default [defun-mode] is stored in
the [table] [ACL2-defaults-table] and hence may also be changed by
a [table] [command]. See [table] and also see
[ACL2-defaults-table]. Both mode-changing [command]s are [events].
While [events] that change the default [defun-mode] are permitted
within an [encapsulate] or the text of a book, their effects are
[local] in scope to the duration of the encapsulation or inclusion.
For example, if the default [defun-mode] is :[logic] and a book is
included that contains the event (program), then subsequent
[events] within the book are processed with the default
[defun-mode] :[program]; but when the [include-book] event
completes, the default [defun-mode] will still be :[logic].
[Command]s that change the default [defun-mode] are not permitted
inside [local] forms.")
(DEFAULT-HINTS
(HINTS)
"A list of hints added to every proof attempt
Examples:
ACL2 !>(default-hints (w state))
((computed-hint-1 clause)
(computed-hint-2 clause stable-under-simplificationp))
The value returned by this function is added to the right of the
:[hints] argument of every [defthm] and [thm] command, and to hints
provided to [defun]s as well (:hints, :guard-hints, and (for
ACL2(r)) :std-hints).
See [set-default-hints] for a more general discussion. Advanced users
only: see [override-hints] for an advanced variant of default hints
that are not superseded by :[hints] arguments.
Subtopics
[Add-default-hints]
Add to the default hints
[Add-default-hints!]
Add to the default hints non-[local]ly
[Default-hints-table]
A [table] used to provide [hints] for proofs
[Remove-default-hints]
Remove from the default hints
[Remove-default-hints!]
Remove from the default hints non-[local]ly
[Set-default-hints]
Set the default hints
[Set-default-hints!]
Set the default hints non-[local]ly")
(DEFAULT-HINTS-TABLE
(DEFAULT-HINTS)
"A [table] used to provide [hints] for proofs
Please see [set-default-hints], see [add-default-hints], and see
[remove-default-hints] for how to use this table. For completeness,
we mention here that under the hood, these events all update the
default-hints-table by updating its key, t, for example as follows.
(table default-hints-table t
'((computed-hint-1 clause)
(computed-hint-2 clause
stable-under-simplificationp)))
The use of default hints is explained elsewhere; see
[set-default-hints].
Advanced users only: see [override-hints] for an advanced variant of
default hints.")
(DEFAULT-PRINT-PROMPT
(LD)
"The default [prompt] printed by [ld]
Example prompt:
ACL2 p!s>
The [prompt] printed by ACL2 displays the current package, followed
by a space, followed by zero or more of the three [characters] as
specified below, followed by the character [>] printed one or more
times, reflecting the number of recursive calls of [ld]. The three
[characters] in the middle are as follows:
p ; when (default-defun-mode (w state)) is :program
! ; when guard checking is on
s ; when (ld-skip-proofsp state) is t
See [default-defun-mode], see [set-guard-checking], and see
[ld-skip-proofsp].
Also see [ld-prompt] to see how to install your own [prompt].
Here are some examples with ld-skip-proofsp nil.
ACL2 !> ; logic mode with guard checking on
ACL2 > ; logic mode with guard checking off
ACL2 p!> ; program mode with guard checking on
ACL2 p> ; program mode with guard checking off
Here are some examples with [default-defun-mode] of :[logic].
ACL2 > ; guard checking off, ld-skip-proofsp nil
ACL2 s> ; guard checking off, ld-skip-proofsp t
ACL2 !> ; guard checking on, ld-skip-proofsp nil
ACL2 !s> ; guard checking on, ld-skip-proofsp t
Finally, here is the prompt in raw mode (see [set-raw-mode]),
regardless of the settings above:
ACL2 P>")
(DEFAULT-RULER-EXTENDERS
(RULER-EXTENDERS)
"The default [ruler-extenders] for [defun]'d functions
When a [defun] is processed and no :ruler-extenders xarg is supplied,
the function default-ruler-extenders is used to obtain the current
ruler-extenders; see [ruler-extenders]. To find the default
[ruler-extenders] of the current ACL2 [world], type
(default-ruler-extenders (w state)).
While [events] that change the default [ruler-extenders] are
permitted within an [encapsulate] or the text of a book, their
effects are [local] in scope to the duration of the encapsulation
or inclusion. See [default-defun-mode] for an analogous discussion
for defun-modes.")
(DEFAULT-TOTAL-PARALLELISM-WORK-LIMIT
(PARALLEL-PROOF)
"For ACL2(p): returns the default value for global
total-parallelism-work-limit
See [set-total-parallelism-work-limit].")
(DEFAULT-VERIFY-GUARDS-EAGERNESS (POINTERS)
"See [set-verify-guards-eagerness].")
(DEFAXIOM
(EVENTS)
"Add an axiom
WARNING: We strongly recommend that you not add axioms. If at all
possible you should use [defun] or [mutual-recursion] to define new
concepts recursively or use [encapsulate] to constrain them
constructively. If your goal is to defer a proof by using a
top-down style, consider using [skip-proofs]; see the discussion on
``Top-Down Proof'' in Section B.1.2 of ``Computer-Aided Reasoning:
An Approach.'' Adding new axioms frequently renders the logic
inconsistent.
Example:
(defaxiom sbar (equal t nil)
:rule-classes nil)
General Form:
(defaxiom name term
:rule-classes rule-classes)
where name is a new symbolic name (see [name]), term is a term
intended to be a new axiom, and rule-classes is a legal value for
:rule-classes (see [rule-classes]). The keyword argument is
optional. If :[rule-classes] is not supplied, the list (:rewrite)
is used; if you wish the axiom to generate no rules, specify
:[rule-classes] nil.")
(DEFCHOOSE
(EVENTS)
"Define a Skolem (witnessing) function
Examples:
(defchoose choose-x-for-p1-and-p2 (x) (y z)
(and (p1 x y z)
(p2 x y z)))
; Axiom added by the event above:
(IMPLIES (AND (P1 X Y Z) (P2 X Y Z))
(LET ((X (CHOOSE-X-FOR-P1-AND-P2 Y Z)))
(AND (P1 X Y Z) (P2 X Y Z))))
(defchoose choose-x-for-p1-and-p2 x (y z) ; equivalent to the above
(and (p1 x y z)
(p2 x y z)))
; The following is as above, but strengthens the axiom added to pick a sort
; of canonical witness, as described below.
(defchoose choose-x-for-p1-and-p2 x (y z)
(and (p1 x y z)
(p2 x y z))
:strengthen t)
(defchoose choose-x-and-y-for-p1-and-p2 (x y) (z)
(and (p1 x y z)
(p2 x y z)))
General Form:
(defchoose fn
(bound-var1 ... bound-varn)
(free-var1 ... free-vark)
body
:strengthen b),
where fn is the symbol you wish to define and is a new symbolic name
(see [name]), (bound-var1 ... bound-varn) is a list of distinct
`bound' variables (see below), (free-var1 ... free-vark) is the
list of formal parameters of fn and is disjoint from the bound
variables, and body is a term. The use of lambda-list keywords
(such as &optional) is not allowed. The :strengthen keyword
argument is optional; if supplied, it must be t or nil.
The system treats fn very much as though it were declared in the
[signature] of an [encapsulate] event, with a single axiom exported
as described below. If you supply a :use hint (see [hints]), :use
fn, it will refer to that axiom. No rule (of class :[rewrite] or
otherwise; see [rule-classes]) is created for fn.
Defchoose is only executed in [defun-mode] :[logic]; see
[defun-mode]. Also see [defun-sk].
In the most common case, where there is only one bound variable, it
is permissible to omit the enclosing parentheses on that variable.
The effect is the same whether or not those parentheses are
omitted. We describe this case first, where there is only one bound
variable, and then address the other case. Both cases are discussed
assuming :strengthen is nil, which is the default. We deal with the
case :strengthen t at the end.
The effect of the form
(defchoose fn bound-var (free-var1 ... free-vark)
body)
is to introduce a new function symbol, fn, with formal parameters
(free-var1 ... free-vark). Now consider the following axiom, which
states that fn picks a value of bound-var so that the body will be
true, if such a value exists:
(1) (implies body
(let ((bound-var (fn free-var1 ... free-vark)))
body))
This axiom is ``clearly conservative'' under the conditions expressed
above: the function fn simply picks out a ``witnessing'' value of
bound-var if there is one. For a rigorous statement and proof of
this conservativity claim, see [conservativity-of-defchoose].
Next consider the case that there is more than one bound variable,
i.e., there is more than one bound-var in the following.
(defchoose fn
(bound-var1 ... bound-varn)
(free-var1 ... free-vark)
body)
Then fn returns a multiple value with n components, and formula (1)
above is expressed using [mv-let] as follows:
(implies body
(mv-let (bound-var1 ... bound-varn)
(fn free-var1 ... free-vark)
body))
We now discuss the case that :strengthen t is supplied. For
simplicity we return to our simplest case, with defchoose applied
to function fn, a single free variable y, and a single bound
variable bound-var. The idea is that if we pick the ``smallest''
witnessing bound-var for two different free variables y and y1,
then either those two witnesses are the same, or else one is less
than the other, in which case the smaller one is a witness for its
free variable but not for the other. (See comments in source
function defchoose-constraint-extra for more details.) Below, body1
is the result of replacing y by y1 in body.
(2) (or (equal (fn y) (fn y1))
(let ((bound-var (fn y)))
(and body
(not body1)))
(let ((bound-var (fn y1)))
(and body1
(not body))))
An important application of this additional axiom is to be able to
define a ``fixing'' function that picks a canonical representative
of each equivalence class, for a given equivalence relation. The
following events illustrate this point.
(encapsulate
((equiv (x y) t))
(local (defun equiv (x y) (equal x y)))
(defequiv equiv))
(defchoose efix (x) (y)
(equiv x y)
:strengthen t)
(defthm equiv-implies-equal-efix-1
(implies (equiv y y1)
(equal (efix y) (efix y1)))
:hints ((\"Goal\" :use efix))
:rule-classes (:congruence))
(defthm efix-fixes
(equiv (efix x) x)
:hints ((\"Goal\" :use ((:instance efix (y x))))))
If there is more than one bound variable, then (2) is modified in
complete analogy to (1) to use [mv-let] in place of [let].
Comment for logicians: As we point out in the documentation for
[defun-sk], defchoose is ``appropriate,'' by which we mean that it
is conservative, even in the presence of epsilon-0 induction. For a
proof, See [conservativity-of-defchoose].
Subtopics
[Conservativity-of-defchoose]
Proof of conservativity of [defchoose]")
(DEFCONG
(EVENTS)
"Prove [congruence] rule
Defcong is used to prove that one [equivalence] relation preserves
another in a given argument position of a given function.
Example:
(defcong set-equal iff (memb x y) 2)
is an abbreviation for
(defthm set-equal-implies-iff-memb-2
(implies (set-equal y y-equiv)
(iff (memb x y) (memb x y-equiv)))
:rule-classes (:congruence))
See [congruence] and also see [equivalence].
NOTE: defcong may only be used to create classic [congruence] rules,
not [patterned-congruence] rules.
General Form:
(defcong equiv1 equiv2 term k
:rule-classes rule-classes
:instructions instructions
:hints hints
:otf-flg otf-flg
:event-name event-name
:doc doc)
where equiv1 and equiv2 are known [equivalence] relations; term is a
call of a function fn, other than if, on the correct number of
distinct variable arguments, (fn x1 ... xn); k is a positive
integer less than or equal to the arity of fn; and other arguments
are as specified in the documentation for [defthm]. The defcong
macro expands into a call of [defthm]. The name of the [defthm]
event is equiv1-implies-equiv2-fn-k unless an :event-name keyword
argument is supplied for the name. The term of the theorem is
(implies (equiv1 xk yk)
(equiv2 (fn x1... xk ...xn)
(fn x1... yk ...xn))).
The rule-class :[congruence] is added to the [rule-classes]
specified, if it is not already there. All other arguments to the
generated [defthm] form are as specified by the keyword arguments
above.")
(DEFCONST
(EVENTS PROGRAMMING)
"Define a constant
Examples:
(defconst *digits* '(0 1 2 3 4 5 6 7 8 9))
(defconst *n-digits* (the unsigned-byte (length *digits*)))
General Form:
(defconst name term doc-string)
where name is a symbol beginning and ending with the character *,
term is a variable-free term that is evaluated to determine the
value of the constant, and doc-string, if non-nil, is an optional
string that can provide documentation but is essentially ignored by
ACL2.
When a constant symbol is used as a [term], ACL2 replaces it by its
value; see [term].
Note that defconst uses a ``safe mode'' to evaluate its form, in
order to avoids soundness issues but with an efficiency penalty
(perhaps increasing the evaluation time by several hundred
percent). If efficiency is a concern, or if for some reason you
need the form to be evaluated without safe mode (e.g., you are an
advanced system hacker using trust tags to traffic in raw Lisp
code), consider using [defconsts] instead. Also see
[using-tables-efficiently] for an analogous issue with [table]
events.
It may be of interest to note that defconst is implemented at the
lisp level using defparameter, as opposed to defconstant.
(Implementation note: this is important for proper support of
undoing and redefinition.)
We close with a technical remark, perhaps of interest only who make
use of the [hons-enabled] features of ACL2. For an event of the
form (defconst *C* (quote OBJ)), i.e., (defconst *C* 'OBJ), then
the value associated with *C* is OBJ; that is, the value of *C* is
[eq] to the actual object OBJ occurring in the defconst form. So
for example, if [make-event] is used to generate such a defconst
event, as it is in the two books mentioned above, and OBJ is a fast
alist (see [fast-alists]), then the value of *C* is a fast alist.
This guarantee disappears if the term in the defconst form is not a
quoted object, i.e., if it is not of the form (quote OBJ).
Subtopics
[Sharp-dot-reader]
Read-time evaluation of constants")
(DEFDOC
(EVENTS)
"Deprecated event (formerly for adding documentation)
This event is deprecated; see [xdoc] for information about
[documentation] in ACL2. Defdoc [events] are never considered
redundant (see [redundant-events]).")
(DEFEQUIV
(EVENTS)
"Prove that a function is an [equivalence] relation
Example:
(defequiv set-equal)
is an abbreviation for
(defthm set-equal-is-an-equivalence
(and (booleanp (set-equal x y))
(set-equal x x)
(implies (set-equal x y) (set-equal y x))
(implies (and (set-equal x y)
(set-equal y z))
(set-equal x z)))
:rule-classes (:equivalence))
See [equivalence].
General Form:
(defequiv fn
:rule-classes rule-classes
:instructions instructions
:hints hints
:otf-flg otf-flg
:event-name event-name
:doc doc)
where fn is a function symbol of arity 2, event-name, if supplied, is
a symbol, and all other arguments are as specified in the
documentation for [defthm]. The defequiv macro expands into a call
of defthm. The name of the defthm is fn-is-an-equivalence, unless
event-name is supplied, in which case event-name is the name used.
The term generated for the defthm event states that fn is Boolean,
reflexive, symmetric, and transitive. The rule-class :equivalence
is added to the [rule-classes] specified, if it is not already
there. All other arguments to the generated defthm form are as
specified by the other keyword arguments above.")
(DEFEVALUATOR
(EVENTS)
"Introduce an evaluator function
Example:
(defevaluator evl evl-list
((length x) (member-equal x y)))
See [meta].
General Form:
(defevaluator ev ev-list
((g1 x1 ... xn_1)
...
(gk x1 ... xn_k))
:namedp flg) ; [optional keyword argument]
where ev and ev-list are new function symbols and g1, ..., gk are old
function symbols with the indicated number of formals, i.e., each
gi has n_i formals. If the :namedp keyword argument is provided,
its value should be Boolean. If not provided, the default value for
flg is nil.
This function provides a convenient way to constrain ev and ev-list
to be mutually-recursive evaluator functions for the symbols g1,
..., gk. Roughly speaking, an evaluator function for a fixed,
finite set of function symbols is a restriction of the universal
evaluator to terms composed of variables, constants, lambda
expressions, and applications of the given functions. However,
evaluator functions are constrained rather than defined, so that
the proof that a given metafunction is correct vis-a-vis a
particular evaluator function can be lifted (by functional
instantiation) to a proof that it is correct for any larger
evaluator function. See [meta] for a discussion of metafunctions.
If the :namedp flg is nil (the default) constraints have names of the
form ev-CONSTRAINT-i, e.g., EV-CONSTRAINT-0, EV-CONSTRAINT-1, etc.
If flg is non-nil, the constraints are named more mnemonically,
e.g., EV-OF-VARIABLE, EV-OF-REVAPPEND-CALL, etc. We illustrate the
:namedp t names below.
Defevaluator executes an [encapsulate] after generating the
appropriate [defun] and [defthm] events. Perhaps the easiest way to
understand what defevaluator does is to execute the keyword command
:trans1 (defevaluator evl evl-list ((length x) (member-equal x y)))
and inspect the output. This trick is also useful in the rare case
that the event fails because a hint is needed. In that case, the
output of :[trans1] can be edited by adding hints, then submitted
directly.
Formally, ev is said to be an ``evaluator function for g1, ..., gk,
with mutually-recursive counterpart ev-list'' iff ev and ev-list
are constrained functions satisfying just the [constraint]s
discussed below.
Ev and ev-list must satisfy [constraint]s (0)-(5) and (k) below. When
:namedp nil is supplied, the i in the generated constraint names
are the parenthesized numbers below. When :namedp t is supplied,
the mnemonic names are those shown in brackets below.
(0) How to ev an arbitrary function application:
[EV-OF-FNCALL-ARGS]
(implies (and (consp x)
(syntaxp (not (equal a ''nil)))
(not (equal (car x) 'quote)))
(equal (ev x a)
(ev (cons (car x)
(kwote-lst (ev-list (cdr x) a)))
nil)))
(1) How to ev a variable symbol:
[EV-OF-VARIABLE]
(implies (symbolp x)
(equal (ev x a) (and x (cdr (assoc-equal x a)))))
(2) How to ev a constant:
[EV-OF-QUOTE]
(implies (and (consp x)
(equal (car x) 'quote))
(equal (ev x a) (cadr x)))
(3) How to ev a lambda application:
[EV-OF-LAMBDA]
(implies (and (consp x)
(consp (car x)))
(equal (ev x a)
(ev (caddar x)
(pairlis$ (cadar x)
(ev-list (cdr x) a)))))
(4) How to ev an empty argument list:
[EV-LIST-OF-ATOM]
(implies (not (consp x-lst))
(equal (ev-list x-lst a)
nil))
(5) How to ev a non-empty argument list:
[EV-LIST-OF-CONS]
(implies (consp x-lst)
(equal (ev-list x-lst a)
(cons (ev (car x-lst) a)
(ev-list (cdr x-lst) a))))
(k) For each i from 1 to k, how to ev an application of gi,
where gi is a function symbol of n arguments:
[EV-OF-gi-CALL]
(implies (and (consp x)
(equal (car x) 'gi))
(equal (ev x a)
(gi (ev x1 a)
...
(ev xn a)))),
where xi is the (cad...dr x) expression equivalent to (nth i x).
Defevaluator defines suitable witnesses for ev and ev-list, proves
the theorems about them, and constrains ev and ev-list
appropriately. We expect defevaluator to work without assistance
from you, though the proofs do take some time and generate a lot of
output. The proofs are done in the context of a fixed theory,
namely the value of the constant *defevaluator-form-base-theory*.
(Aside: (3) above may seem surprising, since the bindings of a are
not included in the environment that is used to evaluate the lambda
body, (caddar x). However, ACL2 lambda expressions are all closed:
in (lambda (v1 ... vn) body), the only free variables in body are
among the vi. See [term].)
Acknowledgement: We thank Sol Swords and Jared Davis for their
community book tools/defevaluator-fast.lisp, which provided the
model on which the current defevaluator is based. The original
defevaluator was very inefficient, e.g., taking thousands of times
longer than the current one on an evaluator interpreting 800
function symbols. We refactored their defevaluator-fast (with
permission) and made it the new implementation as of ACL2
Version_7.2. Both implementations produce the same constraints
modulo the naming option provided by :namedp.")
(DEFEXEC
(EVENTS MBE)
"Attach a terminating executable function to a definition
Suppose you define a function (fn x) with a [guard] of (good-input-p
x), and you know that when the guard holds, the measure decreases
on each recursive call. Unfortunately, the definitional principle
(see [defun]) ignores the guard. For example, if the definition has
the form
(defun fn (x)
(declare (xargs :guard (good-input-p x)))
(if (not-done-yet x)
(... (fn (destr x)) ...)
...))
then in order to admit this definition, ACL2 must prove the
appropriate formula asserting that (destr x) is ``smaller than'' x
under the assumption (not-done-yet x) but without the assumption
(good-input-p x), even if (not-done-yet x) is true. In essence, it
may be necessary to submit instead the following definition.
(defun fn (x)
(declare (xargs :guard (good-input-p x)))
(if (good-input-p x)
(if (not-done-yet x)
(... (fn (destr x)) ...)
...)
nil)
But it is unfortunate that when calls of fn are evaluated, for
example when fn is applied to an explicit constant during a proof,
then a call of good-input-p must now be evaluated on each recursive
call.
Fortunately, defexec provides a way to keep the execution efficient.
For the example above we could use the following form.
(defexec fn (x)
(declare (xargs :guard (good-input-p x)))
(mbe :logic (if (good-input-p x)
(if (not-done-yet x)
(... (fn (destr x)) ...)
...)
nil)
:exec (if (not-done-yet x)
(... (fn (destr x)) ...)
...)))
Here ``[mbe]'' stands for ``must be equal'' and, roughly speaking,
its call above is logically equal to the :logic form but is
evaluated using the :exec form when the guard holds. See [mbe]. The
effect is thus to define fn as shown in the [defun] form above, but
to cause execution of fn using the :exec body. The use of defexec
instead of [defun] in the example above causes a termination proof
to be performed, in order to guarantee that evaluation always
theoretically terminates, even when using the :exec form for
evaluation.
Example:
; Some of the keyword arguments in the declarations below are irrelevant or
; unnecessary, but they serve to illustrate their use.
(defexec f (x)
(declare (xargs :measure (+ 15 (acl2-count x))
:ruler-extenders :basic
:hints ((\"Goal\" :in-theory (disable nth)))
:guard-hints ((\"Goal\" :in-theory (disable last)))
:guard (and (integerp x) (<= 0 x) (< x 25)))
(exec-xargs
:test (and (integerp x) (<= 0 x))
:default-value 'undef ; defaults to nil
:measure (nfix x)
:ruler-extenders :basic
:well-founded-relation o<))
(mbe :logic (if (zp x)
1
(* x (f (- x 1))))
:exec (if (= x 0)
1
(* x (f (- x 1))))))
The above example macroexpands to the following.
(ENCAPSULATE ()
(LOCAL
(ENCAPSULATE ()
(SET-IGNORE-OK T)
(SET-IRRELEVANT-FORMALS-OK T)
(LOCAL (DEFUN F (X)
(DECLARE
(XARGS :VERIFY-GUARDS NIL
:HINTS ((\"Goal\" :IN-THEORY (DISABLE NTH)))
:MEASURE (NFIX X)
:RULER-EXTENDERS :BASIC
:WELL-FOUNDED-RELATION O<))
(IF (AND (INTEGERP X) (<= 0 X))
(IF (= X 0) 1 (* X (F (- X 1))))
'UNDEF)))
(LOCAL (DEFTHM F-GUARD-IMPLIES-TEST
(IMPLIES (AND (INTEGERP X) (<= 0 X) (< X 25))
(AND (INTEGERP X) (<= 0 X)))
:RULE-CLASSES NIL))))
(DEFUN F (X)
(DECLARE (XARGS :MEASURE (+ 15 (ACL2-COUNT X))
:RULER-EXTENDERS :BASIC
:HINTS ((\"Goal\" :IN-THEORY (DISABLE NTH)))
:GUARD-HINTS ((\"Goal\" :IN-THEORY (DISABLE LAST)))
:GUARD (AND (INTEGERP X) (<= 0 X) (< X 25))))
(MBE :LOGIC
(IF (ZP X) 1 (* X (F (- X 1))))
:EXEC
(IF (= X 0) 1 (* X (F (- X 1)))))))
Notice that in the example above, the :[hints] in the [local]
definition of F are inherited from the :hints in the [xargs] of the
defexec form. We discuss such inheritance below.
CAVEAT: Termination is not considered for calls of [mbe] under the
top-level call. Moreover, the :exec part of an [mbe] call under the
:logic part of any superior mbe call is completely ignored.
General Form:
(defexec fn (var1 ... varn) doc-string dcl ... dcl
(mbe :LOGIC logic-body
:EXEC exec-body))
where the syntax is identical to the syntax of [defun] where the body
is a call of mbe, with the exceptions described below. Thus, fn is
the symbol you wish to define and is a new symbolic name and (var1
... varn) is its list of formal parameters (see [name]). The first
exception is that at least one dcl (i.e., [declare] form) must
specify a :guard, guard. The second exception is that one of the
dcls is allowed to contain an element of the form (exec-xargs ...).
The exec-xargs form, if present, must specify a non-empty
[keyword-value-listp] each of whose keys is one of :test,
:default-value, or one of the standard [xargs] keys of :measure,
:ruler-extenders, :well-founded-relation, :hints, or :stobjs. Any
of these five standard xargs keys that is present in an xargs of
some dcl but is not specified in the (possibly nonexistent)
exec-xargs form is considered to be specified in the exec-xargs
form, as illustrated in the example above for :hints. (So for
example, if you want :hints in the final, non-local definition but
not in the local definition, then specify the :hints in the xargs
but specify :hints nil in the exec-xargs.) If :test is specified
and not nil, let test be its value; otherwise let test default to
guard. If :default-value is specified, let default-value be its
value; else default-value is nil. Default-value should have the
same [signature] as exec-body; otherwise the defexec form will fail
to be admitted.
The above General Form's macroexpansion is of the form (PROGN encap
final-def), where encap and final-def are as follows. Final-def is
simply the result of removing the exec-xargs declaration (if any)
from its [declare] form, and is the result of evaluating the given
defexec form, since encap is of the following form.
; encap
(ENCAPSULATE ()
(set-ignore-ok t) ; harmless for proving termination
(set-irrelevant-formals-ok t) ; harmless for proving termination
(local local-def)
(local local-thm))
The purpose of encap is to ensure the the executable version of name
terminates on all arguments. Thus, local-def and local-thm are as
follows, where the xargs of the [declare] form are the result of
adding :VERIFY-GUARDS NIL to the result of removing the :test and
(optional) :default-value from the exec-xargs.
; local-def
(DEFUN fn formals
(DECLARE (XARGS :VERIFY-GUARDS NIL ...))
(IF test
exec-body
default-value))
; local-thm
(DEFTHM fn-EXEC-GUARD-HOLDS
(IMPLIES guard test)
:RULE-CLASSES NIL)
We claim that if the above local-def and local-thm are admitted, then
all evaluations of calls of fn terminate. The concern is that the
use of [mbe] in final-def allows for the use of exec-body for a
call of fn, as well as for subsequent recursive calls, when guard
holds and assuming that the guards have been verified for
final-def. However, by local-thm we can conclude in this case that
test holds, in which case the call of fn may be viewed as a call of
the version of fn defined in local-def. Moreover, since guards have
been verified for final-def, then guards hold for subsequent
evaluation of exec-body, and in particular for recursive calls of
fn, which can thus continue to be viewed as calls using local=def.")
(DEFINE-PC-HELP
(PROOF-CHECKER)
"Define a macro command whose purpose is to print something
Example:
(define-pc-help pp ()
(if (goals t)
(io? proof-checker nil state
(state-stack)
(fms0 \"~|~y0~|\"
(list (cons #0
(fetch-term (conc t)
(current-addr t))))))
(print-all-goals-proved-message state)))
General Form:
(define-pc-help name args &rest body)
This defines a macro command named name, as explained further below.
The body should (after removing optional declarations) be a form
that returns state as its single value. Typically, it will just
print something.
What (define-pc-help name args &rest body) really does is to create a
call of define-pc-macro that defines name to take arguments args,
to have the declarations indicated by all but the last form in
body, and to have a body that (via pprogn) first executes the form
in the last element of body and then returns a call to the command
skip (which will return (mv nil t state)).")
(DEFINE-PC-MACRO
(PROOF-CHECKER)
"Define a proof-checker macro command
Example:
(define-pc-macro ib (&optional term)
(value
(if term
`(then (induct ,term) bash)
`(then induct bash))))
The example above captures a common paradigm: one attempts to prove
the current goal by inducting and then simplifying the resulting
goals. (see [proof-checker-commands] for documentation of the
command then, which is itself a pc-macro command, and commands
induct and bash.) Rather than issuing (then induct bash), or worse
yet issuing induct and then issuing bash for each resulting goals,
the above definition of ib would let you issue ib and get the same
effect.
General Form:
(define-pc-macro cmd args doc-string dcl ... dcl body)
where cmd is the name of the pc-macro than you want to define, args
is its list of formal parameters. Args may include lambda-list
keywords &optional and &rest; see [macro-args], but note that here,
args may not include &key or &whole.
The value of body should be an [error-triple], of the form (mv erp
xxx state) for some erp and xxx. If erp is nil, then xxx is handed
off to the proof-checker's instruction interpreter. Otherwise,
evaluation typically halts. We may write more on the full story
later if there is interest in reading it.")
(DEFINE-PC-META
(PROOF-CHECKER)
"Define a proof-checker meta command
Built-in proof-checker meta commands include undo and restore, and
others (lisp, exit, and sequence); see [proof-checker-commands].
The advanced proof-checker user can define these as well. See ACL2
source file proof-checker-b.lisp for examples, and contact the ACL2
implementors if those examples do not provide sufficient
documentation.")
(DEFINE-TRUSTED-CLAUSE-PROCESSOR
(EVENTS)
"Define a trusted (unverified) goal-level simplifier
This [documentation] assumes familiarity with :clause-processor
rules; see [clause-processor]. Briefly put, a clause-processor is a
user-defined function that takes as input the ACL2 representation
of a goal --- a clause --- and returns a list of goals (i.e., a
list of clauses). A :clause-processor rule is a way to inform ACL2
that a clause-processor has been proved correct and now may be
specified in :clause-processor [hints].
Here we describe a utility, define-trusted-clause-processor, that
provides another way to inform ACL2 that a function is to be
considered a clause-processor that can be specified in a
:clause-processor hint. You can find examples of correct and
incorrect use of this utility in community book
books/clause-processors/basic-examples.
Consider the simple example already presented for :clause-processor
rules (again, see [clause-processor]), for a simple
clause-processor named note-fact-clause-processor. Instead of
introducing an evaluator and proving a correctness theorem with
:rule-classes :clause-processor, we can simply inform ACL2 that we
trust the function note-fact-clause-processor to serve as a
clause-processor.
(define-trusted-clause-processor
note-fact-clause-processor
nil
:ttag my-ttag)
A non-nil :ttag argument generates a [defttag] event in order to
acknowledge the dependence of the ACL2 session on the (unproved)
correctness of this clause-processor. That argument can be omitted
if there is currently an active trust tag. Note that the extra
[defttag] event will be [local] to the
define-trusted-clause-processor event; that is, its effect will
disappear after the define-trusted-clause-processor event
completes. (This point becomes clear if one understands that a call
of define-trusted-clause-processor expands to a call of
[encapsulate], and a [defttag] event is essentially [local] within
any [encapsulate] event, as is any event that sets the
[ACL2-defaults-table].) See [defttag]. Because we are trusting this
clause-processor, rather than having proved it correct, we refer to
it as a ``trusted'' clause-processor to contrast with a
proved-correct, or ``verified'', clause-processor.
Now that the event displayed above has established
note-fact-clause-processor as a (trusted) clause-processor, we can
use it in a :clause-processor hint, for example as follows. Notice
that the output is identical to that for the corresponding example
presented for the verified case (see [clause-processor]), except
that the word ``verified'' has been replaced by the word
``trusted''.
ACL2 !>(thm (equal (car (cons x y))
x)
:hints
((\"Goal\"
:clause-processor
(note-fact-clause-processor clause '(equal a a)))))
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
We now apply the trusted :CLAUSE-PROCESSOR function NOTE-FACT-CLAUSE-
PROCESSOR to produce two new subgoals.
Subgoal 2
(IMPLIES (EQUAL A A)
(EQUAL (CAR (CONS X Y)) X)).
But we reduce the conjecture to T, by the :executable-counterpart of
IF and the simple :rewrite rule CAR-CONS.
Subgoal 1
(EQUAL A A).
But we reduce the conjecture to T, by primitive type reasoning.
Q.E.D.
Summary
Form: ( THM ...)
Rules: ((:EXECUTABLE-COUNTERPART IF)
(:EXECUTABLE-COUNTERPART NOT)
(:FAKE-RUNE-FOR-TYPE-SET NIL)
(:REWRITE CAR-CONS))
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Proof succeeded.
ACL2 !>
Indeed, if one runs this example first and subsequently verifies the
clause-processor, one will see the word ``trusted'' change to
``verified''.
The general form is as follows.
(define-trusted-clause-processor
cl-proc ;;; clause-processor function
supporters ;;; see below
&key
label ;;; optional, but required if doc is non-nil
doc ;;; optional
ttag ;;; discussed above
partial-theory ;;; optional encapsulate event
)
If a :label LAB is supplied, then a subsidiary [deflabel] event will
be generated with name LAB, which will enable you to to undo this
define-trusted-clause-processor event using: :[ubt] LAB. If you
supply a :label then you may supply a :doc argument to use with
that generated [deflabel] event. We discussed the :ttag argument
above. The entire form is considered redundant (skipped) if it is
identical to one already executed in the current ACL2 world; but if
it is not redundant, then cl-proc must not already have been
similarly designated as a trusted clause-processor.
Note that cl-proc may be defined either in :program-mode or
:logic-mode.
The supporters argument should be a true list of function symbols in
the current ACL2 world. It is important that this list include
user-defined functions whose definitions support the correctness of
the clause-processor function. Otherwise, [local] definitions of
those missing supporters can render the use of this
clause-processor unsound, as discussed in the paper referenced at
the end of the [clause-processor] documentation topic. Moreover,
ACL2 assumes for dependent clause-processors (discussed below) that
every function symbol constrained by the ``promised encapsulate''
of that event is either among those supporters or ancestral in one
of them (i.e. a supporter of a supporter, a supporter of one of
those, etc.).
Dependent clause-processors and promised encapsulates: The
:partial-theory argument
Suppose you want to introduce a clause-processor to reason about a
complex hardware simulator that is implemented outside ACL2. Sawada
and Reeber had just such a problem, as reported in their FMCAD 2006
paper. Indeed, they used [sys-call] to implement a :[program]-mode
function in ACL2 that can invoke that simulator. In principle one
could code the simulator directly in ACL2; but it would be a
tremendous amount of work that has no practical purpose, given the
interface to the external simulator. So: In what sense can we have
a clause-processor that proves properties about a simulator when
that simulator is not fully axiomatized in ACL2? Our answer, in a
nutshell, is this: The above :partial-theory argument provides a
way to write merely some of the [constraint]s on the external tool
(or even no constraints at all), with the understanding that such
constraints are present implicitly in a stronger ``promised''
encapsulate, for example by exporting the full definition.
If a trusted clause-processor is introduced with a :partial-theory
argument, we call it a ``dependent'' clause-processor, because its
correctness is dependent on the constraints implicitly introduced
by the :partial-theory encapsulate form. The implicit constraints
should logically imply the constraints actually introduced by the
explicit encapsulate, but they should also be sufficient to justify
every possible invocation of the clause-processor in a
:clause-processor hint. The user of a
define-trusted-clause-processor form is making a guarantee --- or,
is relying on a guarantee provided by the writer of that form ---
that in principle, there exists a so-called ``promised
encapsulate'': an encapsulate form with the same [signature] as the
:partial-theory encapsulate form associated with the trusted
clause-processor, but whose constraints introduced are the
aforementioned implicit constraints.
There are several additional requirements on a :partial-theory
argument. First, it must be an [encapsulate] event with non-empty
[signature]. Moreover, the functions introduced by that event must
be exactly those specified in the signature, and no more. And
further still, the define-trusted-clause-processor form cannot be
executed inside any [encapsulate] form with non-empty [signature];
we can think of this situation as attempting to associate more than
one encapsulate with the functions introduced in the inner
encapsulate.
The :partial-theory event will (in essence) be executed as part of
the evaluation of the define-trusted-clause-processor form. Again,
a critical obligation rests on the user who provides a
:partial-theory: there must exist (in principle at least) a
corresponding promised encapsulate form with the same [signature]
that could logically be admitted, whenever the above
define-trusted-clause-processor form is evaluated successfully,
that justifies the designation of cl-proc as a clause-processor.
See also the paper mentioned above for more about promised
encapsulates. A key consequence is that the [constraint]s are
unknown for the functions introduced in (the signature of) a
:partial-theory [encapsulate] form. Thus, functional instantiation
(see [functional-instantiation-example]) is disabled for function
in the signature of a :partial-theory form.
A remark on the underlying implementation
You can see all of the current trusted clause-processors by issuing
the command (table trusted-clause-processor-table). Those that are
dependent clause-processors will be associated in the resulting
association list with a pair whose car is the list of supporters
and whose cdr is t, i.e., with (supporters . t); the others will be
associated just with (supporters).
Thus, define-trusted-clause-processor is actually a macro that
generates (among other things) a table event for a table named
trusted-clause-processor-table; see [table]. You are invited to use
:[trans1] to see expansions of calls of this macro.
A technique for using raw Lisp to define a trusted clause-processor
The following code is intended to give an idea for how one might
define the ``guts'' of a trusted clause-processor in raw Lisp. The
idea is to stub out functions, such as acl2-my-prove below, that
you want to define in raw Lisp; and then, load a raw Lisp file to
overwrite any such function with the real code. But then we make
any such overwritten function untouchable. (This last step is
important because otherwise, one can prove nil using a
:functional-instance :use hint, by exploiting the fact that this
function has executable code for which there is no corresponding
definitional axiom.) Note: The point here is only to illustrate the
use of raw Lisp, so we do not bother to define or explain functions
hint-to-termlist or disjoin-clause-segments-to-clause, which this
example assumes are defined elsewhere; their meanings are not
important for this example.
(defstub acl2-my-prove (term hint) t)
(program)
(defttag :my-cl-proc)
(progn
; We wrap everything here in a single progn, so that the entire form is
; atomic. That's important because we want the use of push-untouchable to
; prevent anything besides my-clause-processor from calling acl2-my-prove.
(progn!
(set-raw-mode-on state)
(load \"my-hint-raw.lsp\") ; defines my-prove in raw Lisp
(defun acl2-my-prove (term hint)
(my-prove term hint)))
(defun my-clause-processor (cl hint)
(declare (xargs :guard (pseudo-term-listp cl)
:mode :program))
(if (acl2-my-prove (disjoin cl) hint)
(disjoin-clause-segments-to-clause
(pairlis$ (hint-to-termlist hint) nil)
cl)
(prog2$ (cw \"~|~%NOTE: Unable to prove goal with ~
my-clause-processor and indicated hint.~|\")
(list cl))))
(push-untouchable acl2-my-prove t)
)")
(DEFINITION
(RULE-CLASSES)
"Make a rule that acts like a function definition
See [rule-classes] for a general discussion of rule classes and how
they are used to build rules from formulas. An example :[corollary]
formula from which a :definition rule might be built is:
Examples:
(defthm open-len-twice
(implies (true-listp x)
(equal (len x)
(if (null x)
0
(if (null (cdr x))
1
(+ 2 (len (cddr x)))))))
:rule-classes :definition)
; Same as above, with :controller-alist made explicit:
(defthm open-len-twice
(implies (true-listp x)
(equal (len x)
(if (null x)
0
(if (null (cdr x))
1
(+ 2 (len (cddr x)))))))
:rule-classes ((:definition :controller-alist ((len t)))))
General Form:
(implies hyp (equiv (fn a1 ... an) body))
where equiv is an equivalence relation and fn is a function symbol
other than [if], [hide], [force] or [case-split]. Such rules allow
``alternative'' definitions of fn to be proved as theorems but used
as definitions. These rules are not true ``definitions'' in the
sense that they (a) cannot introduce new function symbols and (b)
do not have to be terminating recursion schemes. They are just
conditional rewrite rules that are controlled the same way we
control recursive definitions. We call these ``definition rules''
or ``generalized definitions''.
Consider the general form above. Generalized definitions are stored
among the :[rewrite] rules for the function ``defined,'' fn above,
but the procedure for applying them is a little different. During
rewriting, instances of (fn a1 ... an) are replaced by
corresponding instances of body provided the hyps can be
established as for a :[rewrite] rule and the result of rewriting
body satisfies the criteria for function expansion. There are two
primary criteria, either of which permits expansion. The first is
that the ``recursive'' calls of fn in the rewritten body have
arguments that already occur in the goal conjecture. The second is
that the ``controlling'' arguments to fn are simpler in the
rewritten body.
The notions of ``recursive call'' and ``controllers'' are complicated
by the provisions for mutually recursive definitions. Consider a
``clique'' of mutually recursive definitions. Then a ``recursive
call'' is a call to any function defined in the clique and an
argument is a ``controller'' if it is involved in the measure that
decreases in all recursive calls. These notions are precisely
defined by the definitional principle and do not necessarily make
sense in the context of generalized definitional equations as
implemented here.
But because the heuristics governing the use of generalized
definitions require these notions, it is generally up to the user
to specify which calls in body are to be considered recursive and
what the controlling arguments are. This information is specified
in the :clique and :controller-alist fields of the :definition rule
class.
The :clique field is the list of function symbols to be considered
recursive calls of fn. In the case of a non-recursive definition,
the :clique field is empty; in a singly recursive definition, it
should consist of the singleton list containing fn; otherwise it
should be a list of all of the functions in the mutually recursive
clique with this definition of fn.
If the :clique field is not provided it defaults to nil if fn does
not occur as a function symbol in body and it defaults to the
singleton list containing fn otherwise. Thus, :clique must be
supplied by the user only when the generalized definition rule is
to be treated as one of several in a mutually recursive clique.
The :controller-alist is an alist that maps each function symbol in
the :clique to a mask specifying which arguments are considered
controllers. The mask for a given member of the clique, fn, must be
a list of t's and nil's of length equal to the arity of fn. A t
should be in each argument position that is considered a
``controller'' of the recursion. For a function admitted under the
principle of definition, an argument controls the recursion if it
is one of the arguments measured in the termination argument for
the function. But in generalized definition rules, the user is free
to designate any subset of the arguments as controllers. Failure to
choose wisely may result in the ``infinite expansion'' of
definitional rules but cannot render ACL2 unsound since the rule
being misused is a theorem.
If the :controller-alist is omitted it can sometimes be defaulted
automatically by the system. If the :clique is nil, the
:controller-alist defaults to nil. If the :clique is a singleton
containing fn, the :controller-alist defaults to the controller
alist computed by (defun fn args body). (The user can obtain some
control over this analysis by setting the default ruler-extenders;
see [ruler-extenders].) If the :clique contains more than one
function, the user must supply the :controller-alist specifying the
controllers for each function in the clique. This is necessary
since the system cannot determine and thus cannot analyze the other
definitional equations to be included in the clique.
For example, suppose fn1 and fn2 have been defined one way and it is
desired to make ``alternative'' mutually recursive definitions
available to the rewriter. Then one would prove two theorems and
store each as a :definition rule. These two theorems would exhibit
equations ``defining'' fn1 and fn2 in terms of each other. No
provision is here made for exhibiting these two equations as a
system of equations. One is proved and then the other. It just so
happens that the user intends them to be treated as mutually
recursive definitions. To achieve this end, both :definition rules
should specify the :clique (fn1 fn2) and should specify a suitable
:controller-alist. If, for example, the new definition of fn1 is
controlled by its first argument and the new definition of fn2 is
controlled by its second and third (and they each take three
arguments) then a suitable :controller-alist would be ((fn1 t nil
nil) (fn2 nil t t)). The order of the pairs in the alist is
unimportant, but there must be a pair for each function in the
clique.
Inappropriate heuristic advice via :clique and :controller-alist can
cause ``infinite expansion'' of generalized definitions, but cannot
render ACL2 unsound.
Note that the actual definition of fn1 has the runic name
(:definition fn1). The runic name of the alternative definition is
(:definition lemma), where lemma is the name given to the event
that created the generalized :definition rule. This allows theories
to switch between various ``definitions'' of the functions.
By default, a :definition rule establishes the so-called ``body'' of
a function. The body is used by :expand [hints], and it is also
used heuristically by the theorem prover's preprocessing (the
initial simplification using ``simple'' rules that is controlled by
the preprocess symbol in :do-not [hints]), induction analysis, and
the determination for when to warn about non-recursive functions in
rules. The body is also used by some heuristics involving whether a
function is recursively defined, and by the expand, x, and x-dumb
commands of the [proof-checker].
See [rule-classes] for a discussion of the optional field
:install-body of :definition rules, which controls whether a
:definition rule is used as described in the paragraph above. Note
that even if :install-body nil is supplied, the rewriter will still
rewrite with the :definition rule; in that case, ACL2 just won't
install a new body for the top function symbol of the left-hand
side of the rule, which for example affects the application of
:expand hints as described in the preceding paragraph. Also see
[set-body] and see [show-bodies] for how to change the body of a
function symbol.
Note only that if you prove a definition rule for function foo, say,
foo-new-def, you will need to refer to that definition as
foo-new-def or as (:DEFINITION foo-new-def). That is because a
:definition rule does not change the meaning of the symbol foo for
:use [hints], nor does it change the meaning of the symbol foo in
theory expressions; see [theories], in particular the discussion
there of runic designators. Similarly :[pe] foo and :[pf] foo will
still show the original definition of foo.
The definitional principle, [defun], actually adds :definition rules.
Thus the handling of generalized definitions is exactly the same as
for ``real'' definitions because no distinction is made in the
implementation. Suppose (fn x y) is [defun]'d to be body. Note that
[defun] (or [defuns] or [mutual-recursion]) can compute the clique
for fn from the syntactic presentation and it can compute the
controllers from the termination analysis. Provided the definition
is admissible, [defun] adds the :definition rule (equal (fn x y)
body).
Subtopics
[Bind-free]
To bind free variables of a rewrite, definition, or linear rule
[Case-split]
Like force but immediately splits the top-level goal on the
hypothesis
[Force]
Identity function used to force a hypothesis
[Set-body]
Set the definition body
[Show-bodies]
Show the potential definition bodies
[Simple]
:[definition] and :[rewrite] rules used in preprocessing
[Syntaxp]
Attach a heuristic filter on a rule")
(DEFLABEL
(EVENTS)
"Build a landmark
Examples:
(deflabel interp-section)
General Form:
(deflabel name)
where name is a new symbolic name (see [name]). By virtue of the fact
that deflabel is an event, it marks the current [history] with the
name. For example, you may wish to undo back through some label or
compute a theory expression (see [theories]) in terms of some
labels. Deflabel [events] are never considered redundant. See
[redundant-events].")
(DEFLOCK
(PARALLEL-PROGRAMMING)
"Define a wrapper macro that provides mutual exclusion in ACL2(p)
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel evaluation and proof; see [parallelism].
Example Form:
(deflock *my-lock*)
General Form:
(deflock *symbol*)
where *symbol* is a symbol whose first and last characters are both
the character #\\*.
A call of this macro generates a definition of another macro, named
with-<modified-lock-symbol>, where <modified-lock-symbol> is the
given symbol with the leading and trailing * characters removed.
This newly defined macro will guarantee mutually exclusive
execution when called in the body of the raw Lisp definition of a
function, as is typically the case for [guard]-verified functions,
for :[program] mode functions, and for calls of macro [top-level].
(See [guard-evaluation-table] for details of how raw Lisp code
might not be invoked when guard-checking (see [set-guard-checking])
has value :none or :all.) Note that this macro is also simply the
identity when invoked directly in the top-level loop; see
[top-level] for a way to avoid this issue, and see
[parallelism-at-the-top-level] for a general discussion of this
issue for calls of [parallelism] primitives.
To see how mutual exclusion is guaranteed, consider the raw Lisp code
generated for the macro, with-<modified-lock-symbol>, that is
introduced by a call of deflock. This code uses a lock (with the
given *symbol* as its name), which guarantees that for any two
forms that are each in the scope of a call of
with-<modified-lock-symbol>, the forms do not execute concurrently.
Note that a call of deflock expands into the application of progn to
two events, as illustrated below.
ACL2 !>:trans1 (deflock *my-cw-lock*)
(PROGN (TABLE LOCK-TABLE '*MY-CW-LOCK* T)
(DEFMACRO WITH-MY-CW-LOCK (&REST ARGS)
(LIST* 'WITH-LOCK '*MY-CW-LOCK* ARGS)))
ACL2 !>
Thus, deflock forms are legal embedded event forms (see
[embedded-event-form]) for [books] as well as [encapsulate] and
[progn] [events].
The following log shows a lock in action. Recall that locks work as
expected in [guard]-verified and :[program] mode functions; they do
not, however, work in :[logic] mode functions that have not been
guard-verified, as illustrated below.
ACL2 !>(deflock *my-cw-lock*)
[[.. output omitted ..]]
WITH-MY-CW-LOCK
ACL2 !>(defun foo (n)
(declare (xargs :guard (natp n) :verify-guards nil))
(plet ((x1 (with-my-cw-lock (cw \"~x0\" (make-list n))))
(x2 (with-my-cw-lock (cw \"~x0\" (make-list n)))))
(and (null x1) (null x2))))
[[.. output omitted ..]]
FOO
ACL2 !>(foo 20)
(NIL NIL NIL NIL( NIL NIL NIL NIL NIL NILNIL NIL NILNIL NIL NILNIL
NIL NILNIL NIL NIL NILNIL NIL NIL
NIL NILNIL NIL NILNIL )
NIL NIL NIL NIL NIL NIL NIL NIL)
T
ACL2 !>(verify-guards foo)
[[.. output omitted ..]]
FOO
ACL2 !>(foo 20)
(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
T
ACL2 !>")
(DEFMACRO
(MACROS EVENTS PROGRAMMING)
"Define a macro
Example Defmacros:
(defmacro xor (x y)
(list 'if x (list 'not y) y))
(defmacro git (sym key)
(list 'getprop sym key nil
'(quote current-acl2-world)
'(w state)))
(defmacro one-of (x &rest rst)
(declare (xargs :guard (symbol-listp rst)))
(cond ((null rst) nil)
(t (list 'or
(list 'eq x (list 'quote (car rst)))
(list* 'one-of x (cdr rst))))))
Example Expansions:
term macroexpansion
(xor a b) (if a (not b) b)
(xor a (foo b)) (if a (not (foo b)) (foo b))
(git 'car 'lemmas) (getprop 'car 'lemmas nil
'current-acl2-world
(w state))
(one-of x a b c) (or (eq x 'a)
(or (eq x 'b)
(or (eq x 'c) nil)))
(one-of x 1 2 3) ill-formed (guard violation)
General Form:
(defmacro name macro-args doc-string dcl ... dcl body)
where name is a new symbolic name (see [name]), macro-args specifies
the formal parameters of the macro, and body is a term. The formal
parameters can be specified in a much more general way than is
allowed by ACL2 [defun] [events]; see [macro-args] for a
description of keyword (&key) and optional (&optional) parameters
as well as other so-called ``lambda-list keywords'', &rest and
&whole. Doc-string, if non-nil, is an optional string that can
provide documentation but is essentially ignored by ACL2. Each dcl
is an optional declaration (see [declare]) except that the only
[xargs] keyword permitted by defmacro is :[guard].
For compute-intensive applications see the community book
misc/defmac.lisp, which can speed up macroexpansion by introducing
an auxiliary defun. For more information, evaluate the form
(include-book \"misc/defmac\" :dir :system) and then evaluate :doc
defmac.
Macroexpansion occurs when a form is read in, i.e., before the
evaluation or proof of that form is undertaken. To experiment with
macroexpansion, see [trans]. When a form whose [car] is name arises
as the form is read in, the arguments are bound as described in
CLTL pp. 60 and 145, the [guard] is checked, and then the body is
evaluated. The result is used in place of the original form.
In ACL2, macros do not have access to the ACL2 state, [state]. (If
[state] or any user-defined stobj (see [stobj]) is a macro
argument, it is treated as an ordinary variable, bound at
macro-expansion time to a piece of syntax.) This is in part a
reflection of CLTL, p. 143, ``More generally, an implementation of
Common Lisp has great latitude in deciding exactly when to expand
macro calls with a program. ... Macros should be written in such a
way as to depend as little as possible on the execution environment
to produce a correct expansion.'' In ACL2, the product of
macroexpansion is independent of the current environment and is
determined entirely by the macro body and the functions and
constants it references. It is possible, however, to define macros
that produce expansions that refer to [state] or other
single-threaded objects (see [stobj]) or variables not among the
macro's arguments. See the git example above. For a related utility
that does have access to the ACL2 [state], see [make-event].")
(DEFMACRO-LAST
(EVENTS)
"Define a macro that returns its last argument, but with side effects
This is an advanced feature that requires a trust tag. For
explanation, including an example, see [return-last].")
(DEFN (DEFUN EVENTS)
"Definition with [guard] t
Defn is [defun] with [guard] t.")
(DEFND
(DEFUN EVENTS)
"[disable]d definition with [guard] t
Defnd is [defund] with [guard] t.")
(DEFPKG
(EVENTS PACKAGES PROGRAMMING)
"Define a new symbol package
Example:
(defpkg \"MY-PKG\"
(union-eq *acl2-exports*
*common-lisp-symbols-from-main-lisp-package*))
General Form:
(defpkg \"name\" term doc-string)
where \"name\" is a non-empty string consisting of standard characters
(see [standard-char-p]), none of which is lower case, that names
the package to be created; term is a variable-free expression that
evaluates to a list of symbols, where no two distinct symbols in
the list may have the same [symbol-name], to be imported into the
newly created package; and doc-string, if non-nil, is an optional
string that can provide documentation but is essentially ignored by
ACL2. The name of the new package must be ``new'': the host lisp
must not contain any package of that name. There are two exceptions
to this newness rule, discussed at the end of this documentation.
(There is actually an additional argument, book-path, that is used
for error reporting but has no logical content. Users should
generally ignore this argument, as well as the rest of this
sentence: a book-path will be specified for [defpkg] events added
by ACL2 to the [portcullis] of a book's [certificate]; see
[hidden-death-package].)
Defpkg forms can be entered at the top-level of the ACL2 [command]
loop. They should not occur in [books] (see [certify-book]).
After a successful defpkg it is possible to ``intern'' a string into
the package using [intern-in-package-of-symbol]. The result is a
symbol that is in the indicated package, provided the imports allow
it. For example, suppose 'my-pkg::abc is a symbol whose
[symbol-package-name] is \"MY-PKG\". Suppose further that the imports
specified in the defpkg for \"MY-PKG\" do not include a symbol whose
[symbol-name] is \"XYZ\". Then
(intern-in-package-of-symbol \"XYZ\" 'my-pkg::abc)
returns a symbol whose [symbol-name] is \"XYZ\" and whose
[symbol-package-name] is \"MY-PKG\". On the other hand, if the
imports to the defpkg does include a symbol with the name \"XYZ\",
say in the package \"LISP\", then
(intern-in-package-of-symbol \"XYZ\" 'my-pkg::abc)
returns that symbol (which is uniquely determined by the restriction
on the imports list above). See [intern-in-package-of-symbol].
Upon admission of a defpkg event, the function pkg-imports is
extended to compute a list of all symbols imported into the given
package, without duplicates.
Defpkg is the only means by which an ACL2 user can create a new
package or specify what it imports. That is, ACL2 does not support
the Common Lisp functions make-package or import. Currently, ACL2
does not support exporting at all.
The Common Lisp function [intern] is weakly supported by ACL2; see
[intern]. A more general form of that function is also provided:
see [intern$].
We now explain the two exceptions to the newness rule for package
names. The careful experimenter will note that if a package is
created with a defpkg that is subsequently undone, the host lisp
system will contain the created package even after the undo.
Because ACL2 hangs onto [world]s after they have been undone, e.g.,
to implement :[oops] but, more importantly, to implement error
recovery, we cannot actually destroy a package upon undoing it.
Thus, the first exception to the newness rule is that name is
allowed to be the name of an existing package if that package was
created by an undone defpkg and the newly proposed set of imports
is identical to the old one. See
[package-reincarnation-import-restrictions]. This exception does
not violate the spirit of the newness rule, since one is
disinclined to believe in the existence of undone packages. The
second exception is that name is allowed to be the name of an
existing package if the package was created by a defpkg with
identical set of imports. That is, it is permissible to execute
``redundant'' defpkg [command]s. The redundancy test is based on
the values of the two import forms (comparing them after sorting
and removing duplicates), not on the forms themselves.
Finally, we explain why we require the package name to contain
standard characters, none of which is lower case. We have seen at
least one implementation that handled lower-case package names
incorrectly. Since we see no need for lower-case characters in
package names, which can lead to confusion anyhow (note for example
that foo::bar is a symbol whose [symbol-package-name] is \"FOO\", not
\"foo\"), we simply disallow them. Since the notion of ``lower case''
is only well-specified in Common Lisp for standard characters, we
restrict to these.
NOTE: Also see [managing-ACL2-packages] for contributed documentation
on managing ACL2 packages.
Subtopics
[Hidden-death-package]
Handling [defpkg] [events] that are [local]
[Hidden-defpkg]
Handling defpkg events that are local")
(DEFPROXY
(EVENTS)
"Define a non-executable :[program]-mode function for attachment
This event is provided for those who want to experiment with
[defattach] using :[program] mode functions, and without proof
obligations or constraints on cycles in the extended ancestors
graph; see [defattach]. If you merely want to define a stub or a
non-executable function, see [defstub] or see [defun-nx],
respectively.
See community book books/misc/defproxy-test.lisp for an extended (but
simple) example.
Example Forms:
(defproxy subr1 (* *) => *)
(defproxy add-hash (* * hashtable) => (mv * hashtable))
General Form:
(defproxy name args-sig => output-sig)
where name is a new function symbol and (name . args-sig) =>
output-sig) is a signature; see [signature].
The macro defproxy provides a convenient way to introduce a
``proxy'': a :program mode function that can be given attachments
for execution (see [defattach]), assuming that there is an active
trust tag (see [defttag]). Thus, a defproxy calls expands to a
[defun] form with the following [xargs] [declare] form:
:non-executable :program. Note that [verify-termination] is not
permitted for such a function. However, it is permitted to put the
proxy function into :[logic] mode by use of an [encapsulate] event;
indeed, this is the way to ``upgrade'' an attachment so that the
normal checks are performed and no trust tag is necessary.
In order to take advantage of a [defproxy] form, one provides a
subsequent defattach form to attach an executable function to the
defproxy-introduced function. When :skip-checks t is provided in a
[defattach] form, the usual checks for defattach [events] are
skipped, including proof obligations and the check that the
extended ancestor relation has no cycles (see [defattach]). There
must be an active trust tag (see [defttag]) in order to use
:skip-checks t. In that case the use of :skip-checks t is
permitted; but note that its use is in fact required if a
:[program] mode function is involved, and even if a :[logic] mode
function is involved that has not been [guard]-verified.
The following log shows a simple use of defproxy.
ACL2 !>(defproxy foo-stub (*) => *)
Summary
Form: ( DEFUN FOO-STUB ...)
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
FOO-STUB
ACL2 !>(foo-stub '(3 4 5))
ACL2 Error in TOP-LEVEL: ACL2 cannot ev the call of undefined function
FOO-STUB on argument list:
((3 4 5))
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
ACL2 !>(defun foo-impl (x)
(declare (xargs :mode :program
:guard (or (consp x) (eq x nil))))
(car x))
Summary
Form: ( DEFUN FOO-IMPL ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO-IMPL
ACL2 !>(defttag t)
TTAG NOTE: Adding ttag :T from the top level loop.
T
ACL2 !>(defattach (foo-stub foo-impl) :skip-checks t)
Summary
Form: ( DEFATTACH (FOO-STUB FOO-IMPL) ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
:ATTACHMENTS-RECORDED
ACL2 !>(foo-stub '(3 4 5))
3
ACL2 !>
One can replace this attachment with one that uses :[logic] mode
functions and does not skip checks. The idea is to reintroduce the
proxy function using an [encapsulate] form, which does not require
redefinition (see [ld-redefinition-action]) to be enabled, and
either to put the attachment into :[logic] mode with the [guard]
verified, as we do in the example below, or else to attach to a
different [guard]-verified :[logic] mode function.
ACL2 !>(defattach (foo-stub nil) :skip-checks t) ; remove attachment
Summary
Form: ( DEFATTACH (FOO-STUB NIL) ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
:ATTACHMENTS-RECORDED
ACL2 !>(encapsulate
((foo-stub (x) t :guard (true-listp x)))
(local (defun foo-stub (x) (cdr x)))
(defthm foo-stub-reduces-acl2-count
(implies (consp x)
(< (acl2-count (foo-stub x))
(acl2-count x)))))
[[ ... output omitted here ... ]]
The following constraint is associated with the function FOO-STUB:
(IMPLIES (CONSP X) (< (ACL2-COUNT (FOO-STUB X)) (ACL2-COUNT X)))
Summary
Form: ( ENCAPSULATE ((FOO-STUB ...) ...) ...)
Rules: NIL
Warnings: Non-rec
Time: 0.02 seconds (prove: 0.01, print: 0.00, other: 0.01)
T
ACL2 !>(verify-termination foo-impl)
Since FOO-IMPL is non-recursive, its admission is trivial. We could
deduce no constraints on the type of FOO-IMPL.
Computing the guard conjecture for FOO-IMPL....
The guard conjecture for FOO-IMPL is trivial to prove. FOO-IMPL is
compliant with Common Lisp.
Summary
Form: ( DEFUN FOO-IMPL ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Summary
Form: ( MAKE-EVENT (VERIFY-TERMINATION-FN ...))
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
FOO-IMPL
ACL2 !>(defttag nil) ; optional
NIL
ACL2 !>(defattach (foo-stub foo-impl))
The guard proof obligation is
(IMPLIES (TRUE-LISTP X)
(OR (CONSP X) (EQ X NIL))).
But we reduce the conjecture to T, by primitive type reasoning.
Q.E.D.
This concludes the guard proof.
We now prove that the attachment satisfies the required constraint.
The goal to prove is
(IMPLIES (CONSP X)
(< (ACL2-COUNT (FOO-IMPL X))
(ACL2-COUNT X))).
[[ ... output omitted here ... ]]
Q.E.D.
Summary
Form: ( DEFATTACH (FOO-STUB FOO-IMPL))
Rules: ((:DEFINITION ACL2-COUNT)
(:DEFINITION FOO-IMPL)
(:ELIM CAR-CDR-ELIM)
(:FAKE-RUNE-FOR-LINEAR NIL)
(:FAKE-RUNE-FOR-TYPE-SET NIL)
(:REWRITE CAR-CONS)
(:REWRITE CDR-CONS)
(:TYPE-PRESCRIPTION ACL2-COUNT))
Time: 0.02 seconds (prove: 0.01, print: 0.01, other: 0.00)
:ATTACHMENTS-RECORDED
ACL2 !>
We close with some remarks on the checking of [guard]s in the case
that [defattach] has been called with keyword argument :skip-checks
t. We illustrate with examples, where we assume an attachment pair
(f . g) created by an event (defattach ... (f g) ... :skip-checks t
...). A good model for the treatment of :skip-checks t is dependent
on whether f was introduced with defproxy or with [encapsulate]:
for defproxy, the normal guard-related checks are treated as
skipped, while for [encapsulate], they are assumed to hold.
First suppose that f was introduced using defproxy, and consider the
following example.
(defproxy f (*) => *)
(defun g (x) (car x)) ; not guard-verified; implicit guard of t is too weak
(defttag t) ; trust tag needed for :skip-checks t
(defattach (f g) :skip-checks t)
If we try to evaluate the form (f 3) in ACL2, then the top-level
so-called ``executable counterpart'' (i.e., the logically-defined
funcction, also known as the ``*1*'' function) of f is invoked. It
calls the executable counterpart of g, which calls the executable
counterpart of [car], which in turn checks the [guard] of [car] and
causes a guard violation error (unless we first turn off
guard-checking; see [set-guard-checking]).
ACL2 !>(trace$ f g)
((F) (G))
ACL2 !>(f 3)
1> (ACL2_*1*_ACL2::F 3)
2> (ACL2_*1*_ACL2::G 3)
ACL2 Error in TOP-LEVEL: The guard for the function call (CAR X),
which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments
in the call (CAR 3). To debug see :DOC print-gv, see :DOC trace, and
see :DOC wet. See :DOC set-guard-checking for information about suppressing
this check with (set-guard-checking :none), as recommended for new
users.
ACL2 !>
Little changes if we modify the example above by strengtheing the
guard of g.
(defproxy f (*) => *)
(defun g (x)
(declare (xargs :guard (consp x)))
(car x))
(defttag t) ; trust tag needed for :skip-checks t
(defattach (f g) :skip-checks t)
The result of evaluating (f 3) is as before, except that this time
the guard violation occurs at the time that g is called.
ACL2 !>(trace$ f g)
((F) (G))
ACL2 !>(f 3)
1> (ACL2_*1*_ACL2::F 3)
2> (ACL2_*1*_ACL2::G 3)
ACL2 Error in TOP-LEVEL: The guard for the function call (G X), which
is (CONSP X), is violated by the arguments in the call (G 3). To debug
see :DOC print-gv, see :DOC trace, and see :DOC wet. See :DOC set-
guard-checking for information about suppressing this check with (set-
guard-checking :none), as recommended for new users.
ACL2 !>
Now consider a slight variation of the example just above, in which f
is introduced using [encapsulate] instead of using defproxy.
(encapsulate ( ((f *) => *) )
(local (defun f (x) x)))
(defun g (x)
(declare (xargs :guard (consp x)))
(car x))
(defttag t) ; trust tag needed for :skip-checks t
(defattach (f g) :skip-checks t)
Since f was introduced by [encapsulate] instead of by defproxy, ACL2
assumes that the usual guard properties hold. In particular, it
assumes that (informally speaking) the guard of f implies the guard
of g; see [defattach] for details. So in this case, ACL2 proceeds
under that assumption even though it's actually false, and the
result is a raw Lisp error.
ACL2 !>(trace$ f g)
((F) (G))
ACL2 !>(f 3)
1> (ACL2_*1*_ACL2::F 3)
2> (G 3)
***********************************************
************ ABORTING from raw Lisp ***********
Error: Attempt to take the car of 3 which is not listp.
***********************************************
If you didn't cause an explicit interrupt (Control-C),
then the root cause may be call of a :program mode
function that has the wrong guard specified, or even no
guard specified (i.e., an implicit guard of t).
See :DOC guards.
To enable breaks into the debugger (also see :DOC acl2-customization):
(SET-DEBUGGER-ENABLE T)
ACL2 !>
If you replace g by its definition in the first example of this
series, i.e. with a guard (implicitly) of t, you will see the same
error, this time because the [defattach] event assumed that g was
guard-verified.")
(DEFPUN
(EVENTS)
"Define a tail-recursive function symbol
Defpun is a macro developed by Pete Manolios and J Moore that allows
tail-recursive definitions. It is defined in community book
books/misc/defpun.lisp, so to use it, execute the following event.
(include-book \"misc/defpun\" :dir :system)
Details of defpun are provided by Manolios and Moore in the ``Partial
Functions in ACL2'' published with the {ACL2 2000 workshop |
http://www.cs.utexas.edu/users/moore/acl2/workshop-2000/}. Also see
{Partial Functions in ACL2 |
http://www.cs.utexas.edu/users/moore/publications/defpun/index.html}.
A variant, defp, has been developed by Matt Kaufmann to allow more
general forms of tail recursion. If defpun doesn't work for you,
try defp by first executing the following event.
(include-book \"misc/defp\" :dir :system)
Sandip Ray has contributed a variant of defpun, defpun-exec, that
supports executability. See community book
books/defexec/defpun-exec/defpun-exec.lisp:
(include-book \"defexec/defpun-exec/defpun-exec\" :dir :system)
He has also contributed community book
books/misc/misc2/defpun-exec-domain-example.lisp, for functions
that are uniquely defined in a particular domain.")
(DEFREC
(EVENTS)
"Introduce a record structure, like a struct in C.
The defrec macro is built into ACL2 and is frequently used in the
ACL2 sources to define basic kinds of structures.
Better Alternatives to Defrec
While defrec may be a reasonable choice for writing [program]-mode
code, most users would likely be better served by using one of the
many, richer alternatives to [defrec] that are available in various
books. See for instance macros such as:
* The [std::defaggregate] macro from [std/util],
* The [defdata] macro,
* The [fty::defprod] macro from the [fty] library, and
* The data-structures/structures book.
A major reason to favor these macros over defrec is that they
introduce the constructors and accessors for the structure as
proper functions, rather than mere macros. This is very helpful
when you are trying to use ACL2 to reason about code that works
with structures. For instance, it means that your proof goals will
involve terms like (employee->position x) instead of (cdddr x).
Another reason is that defrec does not support putting constraints on
the fields of your structure. For instance, you might want to have
an employee structure where the name field is always a string. You
can't do this with defrec, but any of the above macros support it.
Some of the above macros also have other useful features, e.g.,
integration with [b*], support for [xdoc] documentation, and so
forth.
Usage
A typical use of defrec might look like this:
(defrec employee ;; name of the structure
(name salary . position) ;; fields of the structure
nil) ;; \"cheap\" flag
This will result in the introduction of:
* A \"weak\" recognizer function, weak-employee-p, which recognizes cons
structures that have the right shape. We call the recognizer
weak because it doesn't impose any constraints on the fields,
e.g., there is no requirement that the name of an employee must
be a string or that the salary must be a number.
* A [make] macro that can be used like this:
(make employee :name \"Jimmy\"
:salary 0
:position \"Unpaid Intern\")
* A [change] macro that can be used like this:
(let ((jimmy (make-employee :name \"Jimmy\" ...)))
(change employee jimmy :salary 300000
:position \"Vice President\"))
* Suitable [access] macros that can be used like this:
(let ((jimmy (make-employee :name \"Jimmy\" ...)))
(access employee jimmy :name))
Subtopics
[Access]
Accessor macro for [defrec] structures.
[Change]
Mutator macro for [defrec] structures.
[Make]
Constructor macro for [defrec] structures.")
(DEFREFINEMENT
(EVENTS)
"Prove that equiv1 refines equiv2
Example:
(defrefinement equiv1 equiv2)
is an abbreviation for
(defthm equiv1-refines-equiv2
(implies (equiv1 x y) (equiv2 x y))
:rule-classes (:refinement))
See [refinement].
General Form:
(defrefinement equiv1 equiv2
:rule-classes rule-classes
:instructions instructions
:hints hints
:otf-flg otf-flg
:event-name event-name
:doc doc)
where equiv1 and equiv2 are known [equivalence] relations,
event-name, if supplied, is a symbol and all other arguments are as
specified in the documentation for [defthm]. The defrefinement
macro expands into a call of defthm. The name supplied is
equiv1-refines-equiv2, unless event-name is supplied, in which case
it is used as the name. The term supplied states that equiv1
refines equiv2. The rule-class :refinement is added to the
rule-classes specified, if it is not already there. All other
arguments to the generated defthm form are as specified by the
other keyword arguments above.")
(DEFSTOBJ
(EVENTS STOBJ)
"Define a new single-threaded object
Note: Novices are advised to avoid defstobj, perhaps instead using
community books [std::defaggregate] or
books/data-structures/structures.lisp. At the least, consider using
([set-verify-guards-eagerness] 0) to avoid [guard] verification. On
the other hand, after you learn to use defstobj, see [defabsstobj]
for another way to introduce single-threaded objects.
Example:
(defconst *mem-size* 10) ; for use of *mem-size* just below
(defstobj st
(reg :type (array (unsigned-byte 31) (8))
:initially 0)
(p-c :type (unsigned-byte 31)
:initially 555)
halt ; = (halt :type t :initially nil)
(mem :type (array (unsigned-byte 31) (*mem-size*))
:initially 0 :resizable t))
General Form:
(defstobj name
(field1 :type type1 :initially val1 :resizable b1)
...
(fieldk :type typek :initially valk :resizable bk)
:renaming alist
:inline flg
:congruent-to old-stobj-name
:non-memoizable nm-flg)
where name is a new symbol, each fieldi is a symbol, each typei is
either a type-indicator (a [type-spec] or [stobj] name) or of the
form (ARRAY type-indicator max), each vali is an object satisfying
typei, and each bi is t or nil. Each pair :initially vali and
:resizable bi may be omitted; more on this below. The :renaming
alist argument is optional and allows the user to override the
default function names introduced by this event. The :inline flg
Boolean argument is also optional and declares to ACL2 that the
generated access and update functions for the stobj should be
implemented as macros under the hood (which has the effect of
inlining the function calls). The optional :congruent-to
old-stobj-name argument specifies an existing stobj with exactly
the same structure, and is discussed below. The optional
:non-memoizable nm-flg Boolean argument is ignored when nm-flg is
nil; otherwise, it instructs ACL2 to lay down faster code for
functions that return the new stobj but disallows [memoization] of
any function that takes the new stobj as an argument. We describe
further restrictions on the fieldi, typei, vali, and on alist
below. We recommend that you read about single-threaded objects
(stobjs) in ACL2 before proceeding; see [stobj].
The effect of this event is to introduce a new single-threaded object
(i.e., a ``[stobj]''), named name, and the associated recognizers,
creator, accessors, updaters, constants, and, for fields of ARRAY
type, length and resize functions.
The Single-Threaded Object Introduced
The defstobj event effectively introduces a new global variable,
named name, which has as its initial logical value a list of k
elements, where k is the number of ``field descriptors'' provided.
The elements are listed in the same order in which the field
descriptors appear. If the :type of a field is (ARRAY
type-indicator (max)) then max is a non-negative integer or a
symbol introduced by [defconst]) whose value is a non-negative
integer, and the corresponding element of the stobj is initially of
length specified by max.
Whether the value :type is of the form (ARRAY type-indicator (max))
or, otherwise, just type-indicator, then type-indicator is
typically a type-spec; see [type-spec]. However, type-indicator can
also be the name of a stobj that was previously introduced (by
defstobj or [defabsstobj]). We ignore this ``nested stobj'' case
below; see [nested-stobjs] for a discussion of stobjs within
stobjs.
The keyword value :initially val specifies the initial value of a
field, except for the case of a :type (ARRAY type-indicator (max)),
in which case val is the initial value of the corresponding array.
Note that the actual representation of the stobj in the underlying
Lisp may be quite different; see [stobj-example-2]. For the moment
we focus entirely on the logical aspects of the object.
In addition, the defstobj event introduces functions for recognizing
and creating the stobj and for recognizing, accessing, and updating
its fields. For fields of ARRAY type, length and resize functions
are also introduced. Constants are introduced that correspond to
the accessor functions.
Restrictions on the Field Descriptions in Defstobj
Each field descriptor is of the form:
(fieldi :TYPE typei :INITIALLY vali)
Note that the type and initial value are given in ``keyword
argument'' format and may be given in either order. The typei and
vali ``arguments'' are not evaluated. If omitted, the type defaults
to t (unrestricted) and the initial value defaults to nil.
Each typei must be either a [type-spec] or else a list of the form
(ARRAY type-spec (max)). (Again, we are ignoring the case of nested
stobjs, discussed elsewhere; see [nested-stobjs].) The latter forms
are said to be ``array types.'' Examples of legal typei are:
(INTEGER 0 31)
(SIGNED-BYTE 31)
(ARRAY (SIGNED-BYTE 31) (16))
(ARRAY (SIGNED-BYTE 31) (*c*)) ; where *c* has a non-negative integer value
The typei describes the objects which are expected to occupy the
given field. Those objects in fieldi should satisfy typei. We are
more precise below about what we mean by ``expected.'' We first
present the restrictions on typei and vali.
Non-Array Types
When typei is a [type-spec] it restricts the contents, x, of fieldi
according to the ``meaning'' formula given in the table for
[type-spec]. For example, the first typei above restricts the field
to be an integer between 0 and 31, inclusive. The second restricts
the field to be an integer between -2^30 and (2^30)-1, inclusive.
The initial value, vali, of a field description may be any ACL2
object but must satisfy typei. Note that vali is not a form to be
evaluated but an object. A form that evaluates to vali could be
written 'vali, but defstobj does not expect you to write the quote
mark. For example, the field description
(days-off :initially (saturday sunday))
describes a field named days-off whose initial value is the list
consisting of the two symbols SATURDAY and SUNDAY. In particular,
the initial value is NOT obtained by applying the function saturday
to the variable sunday! Had we written
(days-off :initially '(saturday sunday))
it would be equivalent to writing
(days-off :initially (quote (saturday sunday)))
which would initialize the field to a list of length two, whose first
element is the symbol quote and whose second element is a list
containing the symbols saturday and sunday.
Array Types
When typei is of the form (ARRAY type-spec (max)), the field is
supposed to be a list of items, initially of length specified by
max, each of which satisfies the indicated type-spec. Max must be a
non-negative integer or a defined constant evaluating to a
non-negative integer. Thus, each of
(ARRAY (SIGNED-BYTE 31) (16))
(ARRAY (SIGNED-BYTE 31) (*c*)) ; given previous event (defconst *c* 16)
restricts the field to be a list of integers, initially of length 16,
where each integer in the list is a (SIGNED-BYTE 31). We sometimes
call such a list an ``array'' (because it is represented as an
array in the underlying Common Lisp). The elements of an array
field are indexed by position, starting at 0. Thus, the maximum
legal index of an array field one less than is specified by max.
Note that the value of max must be less than the Common Lisp
constant array-dimension-limit, and also (though this presumably
follows) less than the Common Lisp constant array-total-size-limit.
Note also that the ARRAY type requires that the max be enclosed in
parentheses. This makes ACL2's notation consistent with the Common
Lisp convention of describing the (multi-)dimensionality of arrays.
But ACL2 currently supports only single dimensional arrays in
stobjs.
For array fields, the initial value vali must be an object satisfying
the [type-spec] of the ARRAY description. The initial value of the
field is a list of max repetitions of vali.
Array fields can be ``resized,'' that is, their lengths can be
changed, if :resizable t is supplied as shown in the example and
General Form above. The new length must satisfy the same
restriction as does max, as described above. Each array field in a
defstobj event gives rise to a length function, which gives the
length of the field, and a resize function, which modifies the
length of the field if :resizable t was supplied with the field
when the defstobj was introduced and otherwise causes an error. If
:resizable t was supplied and the resize function specifies a new
length k, then: if k is less than the existing array length, the
array is shortened simply by dropping elements with index at least
k; otherwise, the array is extended to length k by mapping the new
indices to the initial value (supplied by :initially, else default
nil).
Array resizing is relatively slow, so we recommend using it somewhat
sparingly.
The Default Function Names
To recap, in
(defstobj name
(field1 :type type1 :initially val1)
...
(fieldk :type typek :initially valk)
:renaming alist
:doc doc-string
:inline inline-flag)
name must be a new symbol, each fieldi must be a symbol, each typei
must be a [type-spec] or (ARRAY type-spec (max)), and each vali
must be an object satisfying typei.
Roughly speaking, for each fieldi, a defstobj introduces a recognizer
function, an accessor function, and an updater function. The
accessor function, for example, takes the stobj and returns the
indicated component; the updater takes a new component value and
the stobj and return a new stobj with the component replaced by the
new value. But that summary is inaccurate for array fields.
The accessor function for an array field does not take the stobj and
return the indicated component array, which is a list of length
specified by max. Instead, it takes an additional index argument
and returns the indicated element of the array component.
Similarly, the updater function for an array field takes an index,
a new value, and the stobj, and returns a new stobj with the
indicated element replaced by the new value.
These functions --- the recognizer, accessor, and updater, and also
length and resize functions in the case of array fields --- have
``default names.'' The default names depend on the field name,
fieldi, and on whether the field is an array field or not. For
clarity, suppose fieldi is named c. The default names are shown
below in calls, which also indicate the arities of the functions.
In the expressions, we use x as the object to be recognized by
field recognizers, i as an array index, v as the ``new value'' to
be installed by an updater, and name as the single-threaded object.
non-array field array field
recognizer (cP x) (cP x)
accessor (c name) (cI i name)
updater (UPDATE-c v name) (UPDATE-cI i v name)
length (c-LENGTH name)
resize (RESIZE-c k name)
Finally, a recognizer and a creator for the entire single-threaded
object are introduced. The creator returns the initial stobj, but
may only be used in limited contexts; see [with-local-stobj]. If
the single-threaded object is named name, then the default names
and arities are as shown below.
top recognizer (nameP x)
creator (CREATE-name)
For example, the event
(DEFSTOBJ $S
(X :TYPE INTEGER :INITIALLY 0)
(A :TYPE (ARRAY (INTEGER 0 9) (3)) :INITIALLY 9))
introduces a stobj named $S. The stobj has two fields, X and A. The A
field is an array. The X field contains an integer and is initially
0. The A field contains a list of integers, each between 0 and 9,
inclusively. Initially, each of the three elements of the A field
is 9.
This event introduces the following sequence of definitions:
(DEFUN XP (X) ...) ; recognizer for X field
(DEFUN AP (X) ...) ; recognizer of A field
(DEFUN $SP ($S) ...) ; top-level recognizer for stobj $S
(DEFUN CREATE-$S () ...) ; creator for stobj $S
(DEFUN X ($S) ...) ; accessor for X field
(DEFUN UPDATE-X (V $S) ...) ; updater for X field
(DEFUN A-LENGTH ($S) ...) ; length of A field
(DEFUN RESIZE-A (K $S) ...) ; resizer for A field
(DEFUN AI (I $S) ...) ; accessor for A field at index I
(DEFUN UPDATE-AI (I V $S) ...) ; updater for A field at index I
Avoiding the Default Function Names
If you do not like the default names listed above you may use the
optional :renaming alist to substitute names of your own choosing.
Each element of alist should be of the form (fn1 fn2), where fn1 is
a default name and fn2 is your choice for that name.
For example
(DEFSTOBJ $S
(X :TYPE INTEGER :INITIALLY 0)
(A :TYPE (ARRAY (INTEGER 0 9) (3)) :INITIALLY 9)
:renaming ((X XACCESSOR) (CREATE-$S MAKE$S)))
introduces the following definitions
(DEFUN XP (X) ...) ; recognizer for X field
(DEFUN AP (X) ...) ; recognizer of A field
(DEFUN $SP ($S) ...) ; top-level recognizer for stobj $S
(DEFUN MAKE$S () ...) ; creator for stobj $S
(DEFUN XACCESSOR ($S) ...) ; accessor for X field
(DEFUN UPDATE-X (V $S) ...) ; updater for X field
(DEFUN A-LENGTH ($S) ...) ; length of A field
(DEFUN RESIZE-A (K $S) ...) ; resizer for A field
(DEFUN AI (I $S) ...) ; accessor for A field at index I
(DEFUN UPDATE-AI (I V $S) ...) ; updater for A field at index I
Note that even though the renaming alist substitutes ``XACCESSOR''
for ``X'' the updater for the X field is still called ``UPDATE-X.''
That is because the renaming is applied to the default function
names, not to the field descriptors in the event.
Use of the :renaming alist may be necessary to avoid name clashes
between the default names and and pre-existing function symbols.
Constants
Defstobj events also introduce constant definitions (see [defconst]).
One constant is introduced for each accessor function by prefixing
and suffixing a `*' character on the function name. The value of
that constant is the position of the field being accessed. For
example, if the accessor functions are a, b, and c, in that order,
then the following constant definitions are introduced.
(defconst *a* 0)
(defconst *b* 1)
(defconst *c* 2)
These constants are used for certain calls of [nth] and [update-nth]
that are displayed to the user in proof output. For example, for
stobj st with accessor functions a, b, and c, in that order, the
term (nth '2 st) would be printed during a proof as (nth *c* st).
Also see [term], in particular the discussion there of untranslated
terms, and see [nth-aliases-table].
Inspecting the Effects of a Defstobj
Because the stobj functions are introduced as ``sub-events'' of the
defstobj the history commands :[pe] and :[pc] will not print the
definitions of these functions but will print the superior defstobj
event. To see the definitions of these functions use the history
command :[pcb!].
To see an s-expression containing the definitions what constitute the
raw Lisp implementation of the event, evaluate the form
(nth 4 (global-val 'cltl-command (w state)))
immediately after the defstobj event has been processed.
A defstobj is considered redundant only if the name, field
descriptors, renaming alist, and inline flag are identical to a
previously executed defstobj. Note that a redundant defstobj does
not reset the [stobj] fields to their initial values.
Inlining and Performance
The :inline keyword argument controls whether or not accessor,
updater, and length functions are inlined (as macros under the
hood, in raw Lisp). If :inline t is provided then these are
inlined; otherwise they are not. The advantage of inlining is
potentially better performance; there have been contrived examples,
doing essentially nothing except accessing and updating array
fields, where inlining reduced the time by a factor of 10 or more;
and inlining has sped up realistic examples by a factor of at least
2. Inlining may get within a factor of 2 of C execution times for
such contrived examples, and within a few percent of C execution
times on realistic examples.
A drawback to inlining is that redefinition may not work as expected,
much as redefinition may not work as expected for macros: defined
functions that call a macro, or inlined stobj function, will not
see a subsequent redefinition of the macro or inlined function.
Another drawback to inlining is that because inlined functions are
implemented as macros in raw Lisp, tracing (see [trace$]) will not
show their calls. These drawbacks are avoided by default, but the
user who is not concerned about them is advised to specify :inline
t.
Specifying Congruent Stobjs
Two stobjs are may be considered to be ``congruent'' if they have the
same structure, that is, their defstobj events are identical when
ignoring field names. In particular, every stobj is congruent to
itself. In order to tell ACL2 that a new stobj st2 is indeed to be
considered as congruent to an existing stobj st1, the defstobj
event introducing st2 is given the keyword argument :congruent-to
st1. Congruence is an equivalence relation: when you specify a new
stobj to be congruent to an old one, you are also specifying that
the new stobj is congruent to all other stobjs that are congruent
to the old one. Thus, continuing the example above, if you specify
that st3 is :congruent-to st2, then st1, st2, and st3 will all be
congruent to each other.
When two stobjs are congruent, ACL2 allows you to substitute one for
another in a function call. Any number of stobjs may be replaced
with congruent stobjs in the call, provided no two get replaced
with the same stobj. The return values are correspondingly
modified: if stobj st1 is replaced by st2 at an argument position,
and if st1 is returned in the output [signature] of the function,
then st2 is returned in place of st1.
The following example illustrates congruent stobjs. For more examples
of how to take advantage of congruent stobjs, and also of how to
misuse them, see community book
books/misc/congruent-stobjs-test.lisp.
(defstobj st1 fld1)
(defstobj st2 fld2 :congruent-to st1)
(defstobj st3 fld3 :congruent-to st2) ; equivalently, :congruent-to st1
(defun f (st1 st2 st3)
(declare (xargs :stobjs (st1 st2 st3)))
(list (fld2 st1) (fld3 st2) (fld1 st3)))
(update-fld1 1 st1)
(update-fld1 2 st2) ; notice use of update-fld1 on st2
(update-fld1 3 st3) ; notice use of update-fld1 on st3
(assert-event (equal (f st3 st2 st1) '(3 2 1)))
The following example shows an error that occurs when stobj arguments
are repeated, i.e., at least two stobj arguments (in this case,
three) get replaced by the same stobj.
ACL2 !>(f st1 st1 st1)
ACL2 Error in TOP-LEVEL: The form ST1 is being used, as an argument
to a call of F, where the single-threaded object ST2 was expected,
even though these are congruent stobjs. See :DOC defstobj, in particular
the discussion of congruent stobjs. Note: this error occurred in
the context (F ST1 ST1 ST1).
ACL2 !>")
(DEFSTUB
(EVENTS)
"Stub-out a function symbol
Examples:
ACL2 !>(defstub subr1 (* * state) => (mv * state))
ACL2 !>(defstub add-hash (* * hashtable) => hashtable)
General Form:
(defstub name (args-sig) => output-sig)
Name is a new function symbol and ((name . args-sig) => output-sig)
is a [signature]. See also the ``Old Style'' heading below.
A defstub macro call expands into an [encapsulate] event (see
[encapsulate]). Thus, no axioms are available about name but it may
be used wherever a function of the given signature is permitted.
Exception: if output-sig is of the form (mv ...), then a
:[type-prescription] rule is introduced stating that name returns a
value satisfying [true-listp].
Old Style:
Old Style General Form:
(defstub name formals output)
(defstub name formals output)
where name is a new function symbol, formals is its list of formal
parameters, and output is either a symbol (indicating that the
function returns one result) or a term of the form (mv s1 ... sn),
where each si is a symbol (indicating that the function returns n
results). Whether and where the symbol [state] occurs in formals
and output indicates how the function handles [state]. It should be
the case that (name formals output) is in fact a signature (see
[signature]).
Note that with the old style notation it is impossible to stub-out a
function that uses any single-threaded object other than state. The
old style is preserved for compatibility with earlier versions of
ACL2.")
(DEFTHEORY
(EVENTS THEORIES)
"Define a theory (to [enable] or [disable] a set of rules)
Example:
(deftheory interp-theory
(set-difference-theories
(universal-theory :here)
(universal-theory 'interp-section)))
General Form:
(deftheory name term)
where name is a new symbolic name (see [name]) and term is a term
that when evaluated will produce a theory (see [theories]). Except
for the variable [world], term must contain no free variables. Term
is evaluated with [world] bound to the current world (see [world])
and the resulting theory is then converted to a runic theory (see
[theories]) and associated with name. Henceforth, this runic theory
is returned as the value of the theory expression (theory name).
The value returned is the length of the resulting theory. For
example, in the following, the theory associated with 'FOO has 54
[rune]s:
ACL2 !>(deftheory foo (union-theories '(binary-append)
(theory 'minimal-theory)))
Summary
Form: ( DEFTHEORY FOO ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
54
ACL2 !>
Note that the theory being defined depends on the context. For
example, consider the following (contrived) example book.
(in-package \"ACL2\")
(defund foo (x) (consp x)) ; defund disables foo
(local (in-theory (enable foo)))
(deftheory my-theory (current-theory :here))
(in-theory (disable foo))
(defthm foo-property
(implies (consp x)
(foo x))
:hints ((\"Goal\" :in-theory (enable my-theory))))
At the time foo-property is proved admissible during book
certification (see [certify-book]), the [local] [in-theory] event
has previously been evaluated, so the [definition] of foo is
[enable]d. Thus, the :in-theory hint on foo-property will [enable]
foo, and the theorem proves. HOWEVER, when the book is later
included (see [include-book]), the [local] event is skipped, so the
definition of foo is [disable]d at the time the [theory] my-theory
is defined. Hence, unlike the case for the admissibility pass of
the book's certification, that theory does not include the
definition of foo when the book is included.
There is, however, a way to ensure that a [theory] defined in a book
is the same at [include-book] time as it was during the
admissibility pass of the book's certification; see
[deftheory-static].
Note that a deftheory event is never redundant, see
[redundant-events].")
(DEFTHEORY-STATIC
(EVENTS THEORIES)
"Define a `static' theory (to [enable] or [disable] a set of rules)
This macro provides a variant of [deftheory], such that the resulting
theory is the same at [include-book] time as it was at
[certify-book] time.
We assume that the reader is familiar with [theories]; see
[deftheory]. We begin here by illustrating how deftheory-static
differs from [deftheory]. Suppose for example that the following
events are the first two events in a book, where that book is
certified in the initial ACL2 [world] (see [ground-zero]).
(deftheory my-theory
(current-theory :here))
(deftheory-static my-static-theory
(current-theory :here))
Now suppose we include that book after executing the following event.
(in-theory (disable car-cons))
Suppose that later we execute (in-theory (theory 'my-theory)). Then
the rule car-cons will be disabled, because it was disabled at the
time the expression (current-theory :here) was evaluated when
processing the deftheory of my-theory while including the book.
However, if we execute (in-theory (theory 'my-static-theory)), then
the rule car-cons will be enabled, because the value of the theory
my-static-theory was saved at the time the book was certified.
General Form:
(deftheory-static name term)
The arguments are handled the same as for [deftheory]. Thus, name is
a new symbolic name (see [name]), and term is a term that when
evaluated will produce a theory (see [theories]). Except for the
variable [world], term must contain no free variables. Term is
evaluated with [world] bound to the current world (see [world]) and
the resulting theory is then converted to a runic theory (see
[theories]) and associated with name. Henceforth, this runic theory
is returned as the value of the theory expression (theory name).
As for [deftheory], the value returned is the length of the resulting
theory.
We conclude with an optional discussion about the implementation of
deftheory-static, for those familiar with [make-event]. The
following macroexpansion of the deftheory-static form above shows
how this works (see [trans1]).
ACL2 !>:trans1 (deftheory-static my-static-theory
(current-theory :here))
(MAKE-EVENT (LET ((WORLD (W STATE)))
(LIST 'DEFTHEORY
'MY-STATIC-THEORY
(LIST 'QUOTE (CURRENT-THEORY :HERE)))))
ACL2 !>
The idea is that upon evaluation of this make-event form, the first
step is to evaluate the indicated [let] expression to obtain a form
(deftheory my-theory '(...)), where ``(...)'' is a list of all
[rune]s in current theory. If this form is in a book being
certified, then the resulting deftheory form is stored in the
book's certificate, and is used when the book is included later.")
(DEFTHM
(EVENTS)
"Prove and name a theorem
Examples:
(defthm assoc-of-app
(equal (app (app a b) c)
(app a (app b c))))
The following nonsensical example illustrates all the optional
arguments but is illegal because not all combinations are
permitted. See [hints] for a complete list of [hints].
(defthm main
(implies (hyps x y z) (concl x y z))
:rule-classes (:REWRITE :GENERALIZE)
:instructions (induct prove promote (dive 1) x
(dive 2) = top (drop 2) prove)
:hints ((\"Goal\"
:do-not '(generalize fertilize)
:in-theory (set-difference-theories
(current-theory :here)
'(assoc))
:induct (and (nth n a) (nth n b))
:use ((:instance assoc-of-append
(x a) (y b) (z c))
(:functional-instance
(:instance p-f (x a) (y b))
(p consp)
(f assoc)))))
:otf-flg t)
General Form:
(defthm name term
:rule-classes rule-classes
:instructions instructions
:hints hints
:otf-flg otf-flg)
where name is a new symbolic name (see [name]), term is a term
alleged to be a theorem, and [rule-classes], [instructions],
[hints], and [otf-flg] are as described in their respective
[documentation]. The keyword arguments above are all optional,
however you may not supply both :[instructions] and :[hints], since
one drives the proof checker and the other drives the theorem
prover. If :[rule-classes] is not specified, the list (:rewrite) is
used; if you wish the theorem to generate no rules, specify
:[rule-classes] nil.
When ACL2 processes a defthm event, it first tries to prove the
[term] using the indicated hints (see [hints]) or [instructions]
(see [proof-checker]). If it is successful, it stores the rules
described by the rule-classes (see [rule-classes]), proving the
necessary corollaries.
Subtopics
[Otf-flg]
Allow more than one initial subgoal to be pushed for induction")
(DEFTHMD
(EVENTS)
"Prove and name a theorem and then disable it
Use defthmd instead of [defthm] when you want to disable a theorem
immediately after proving it. This macro has been provided for
users who prefer working in a mode where theorems are only enabled
when explicitly directed by :[in-theory]. Specifically, the form
(defthmd NAME TERM ...)
expands to:
(progn
(defthmd NAME TERM ...)
(with-output
:off summary
(in-theory (disable NAME)))
(value-triple '(:defthmd NAME))).
Note that defthmd commands are never redundant (see
[redundant-events]). Even if the defthm event is redundant, then
the [in-theory] event will still be executed.
The summary for the [in-theory] event is suppressed. See [defthm] for
documentation of defthm.")
(DEFTTAG
(INTERFACING-TOOLS EVENTS)
"Introduce a trust tag (ttag)
Introduction. This event is intended for advanced users who, in
essence, want to build extensions of ACL2. The typical intended use
is to create [books] that extend the functionality of ACL2 in ways
not allowed without a so-called ``active trust tag''. A trust tag
thus represents a contract: The writer of such a book is
guaranteeing that the book extends ACL2 in a ``correct'' way as
defined by the writer of the book. The writer of the book will
often have a small section of the book in the scope of an active
trust tag that can be inspected by potential users of that book:
<initial part of book, which does not use trust tags>
(defttag :some-ttag) ; install :some-ttag as an active trust tag
<various code that requires an active trust tag>
(defttag nil) ; remove active trust tag
<final part of book, which does not use trust tags>
Why might trust tags be needed? The evaluation of certain functions
can introduce bugs and even unsoundness, but can be useful in
restricted ways that avoid such issues. For example, [sys-call] can
be used in an unsafe way, for example to overwrite files, or worse;
see [sys-call] for a frightening example from Bob Boyer. The
following example shows that the function [sys-call] is restricted
by default, but can be called after installing an active trust tag.
ACL2 !>(sys-call \"pwd\" nil)
ACL2 Error in TOP-LEVEL: The SYS-CALL function cannot be called unless
a trust tag is in effect. See :DOC defttag.
ACL2 !>(defttag t) ; Install :T as an active trust tag.
TTAG NOTE: Adding ttag :T from the top level loop.
T
ACL2 !>(sys-call \"pwd\" nil) ; print the current directory and return NIL
/u/kaufmann
NIL
ACL2 !>(defttag nil) ; Remove the active trust tag (using value NIL).
NIL
ACL2 !>(sys-call \"pwd\" nil) ; Now we get the error again:
ACL2 Error in TOP-LEVEL: The SYS-CALL function cannot be called unless
a trust tag is in effect. See :DOC defttag.
ACL2 !>
Of course, using [sys-call] with the Linux command pwd is not likely
to cause any soundness problems! So suppose we want to create a
function that prints the working directory. We might put the
following [events] into a book that is to be certified.
(in-package \"ACL2\")
(defttag :pwd-ttag)
(defun print-working-dir ()
(declare (xargs :mode :program))
(sys-call \"pwd\" nil))
(defttag nil) ; optional (books end with this implicitly)
We can certify this book with a specification that :pwd-ttag is a
legal trust tag:
(certify-book \"pwd\" 0 t :ttags (:pwd-ttag))
One can now use this book by executing [include-book] with keyword
parameter :ttags (:pwd-ttag) and then calling function
print-working-dir:
(include-book \"pwd\" :ttags (:pwd-ttag))
(print-working-dir) ; working directory is printed to terminal
Detailed documentation.
General Form:
(defttag tag-name)
where tag-name is a symbol.
Note however that if tag-name is not nil, then it is converted to a
``corresponding [keyword]'': a symbol in the \"KEYWORD\" package with
the same [symbol-name] as tag-name. Thus, for example, (defttag
foo) is equivalent to (defttag :foo). Moreover, a non-nil symbol
with a [symbol-name] of \"NIL\" is illegal for trust tags; thus, for
example, (defttag :nil) is illegal.
This event introduces or removes a so-called active trust tag (or
``ttag'', pronounced ``tee tag''). An active ttag is a [keyword]
symbol that is associated with potentially unsafe evaluation. For
example, calls of [sys-call] are illegal unless there is an active
trust tag. An active trust tag can be installed using a defttag
event. If one introduces an active ttag and then writes definitions
with calls [sys-call], presumably in a defensibly ``safe'' way,
then responsibility for those calls is attributed to that ttag.
This attribution (or blame!) is at the level of [books]; a book's
[certificate] contains a list of ttags that are active in that
book, or in a book that is included (possibly [local]ly), or in a
book included in a book that is included (either inclusion being
potentially [local]), and so on. We explain all this in more detail
below.
(Defttag :tag-name) is essentially equivalent to
(table acl2-defaults-table :ttag :tag-name)
and hence is [local] to any [books] and [encapsulate] [events] in
which it occurs; see [ACL2-defaults-table]. We say more about the
scope of defttag forms below.
Note: This is an event! It does not print the usual event summary but
nevertheless executes the above [table] event and hence changes the
ACL2 logical [world], and is so recorded. Although no event summary
is printed, it is important to note that the ``TTAG NOTE'',
discussed below, is always printed for a non-nil :tag-name (unless
deferred; see [set-deferred-ttag-notes]).
Active ttags. Suppose tag-name is a non-nil symbol. Then (defttag
:tag-name) sets :tag-name to be the (unique) ``active ttag.'' There
must be an active ttag in order for there to be any mention of
certain function and macro symbols, including [sys-call]; evaluate
the form (strip-cars *ttag-fns-and-macros*) to see the full list of
such symbols. On the other hand, (defttag nil) removes the active
ttag, if any; there is then no active ttag. The scope of a defttag
form in a book being certified or included is limited to subsequent
forms in the same book before the next defttag (if any) in that
book. Similarly, if a defttag form is evaluated in the top-level
loop, then its effect is limited to subsequent forms in the
top-level loop before the next defttag in the top-level loop (if
any). Moreover, [certify-book] is illegal when a ttag is active; of
course, in such a circumstance one can execute (defttag nil) in
order to allow book certification.
Ttag notes and the ``certifier.'' When a defttag is executed with an
argument other than nil, output is printed, starting on a fresh
line with: TTAG NOTE. For example:
ACL2 !>(defttag :foo)
TTAG NOTE: Adding ttag :FOO from the top level loop.
:FOO
ACL2 !>
If the defttag occurs in an included book, the message looks like
this.
TTAG NOTE (for included book): Adding ttag :FOO from file /u/smith/acl2/my-book.lisp.
The ``TTAG NOTE'' message is always printed on a single line. The
intention is that one can search the standard output for all such
notes in order to find all defttag events. In a sense, defttag
events can allow you to define your own system on top of ACL2 (for
example, see [progn!]). So in order for someone else (who we might
call the ``certifier'') to be confident that your collection of
[books] is meaningful, that certifier should certify all the
user-supplied books from scratch and check either that no :ttags
were supplied to [certify-book], or else look for every TTAG NOTE
in the standard output in order to locate all defttag [events] with
non-nil tag name. In this way, the certifier can in principle
decide whether to be satisfied that those defttag events did not
allow inappropriate forms in the user-supplied books.
In order to eliminate much of the output from TTAG NOTEs, see
[set-deferred-ttag-notes]. Note however that the resulting security
is somewhat less; therefore, a TTAG NOTE is printed when invoking
set-deferred-ttag-notes to defer printing of ttag notes.
Allowed ttags when certifying and including books. A defttag form may
not be evaluated unless its argument is a so-called ``allowed''
ttag. All ttags are allowed in the interactive top-level loop.
However, during [certify-book] and [include-book], the set of
allowed ttags is restricted according to the :ttags keyword
argument. If this argument is omitted then no ttag is allowed, so a
defttag call will fail during book certification or inclusion in
this case. This restriction applies even to defttag forms already
evaluated in the so-called certification [world] at the time
[certify-book] is called. But note that (defttag nil) is always
legal.
A :ttags argument of [certify-book] and [include-book] can have value
:all, indicating that every ttag is allowed, i.e., no restriction
is being placed on the arguments, just as in the interactive
top-level loop. In the case of include-book, an omitted :ttags
argument or an argument of :default is treated as :all, except that
warnings will occur when the book's [certificate] includes ttags;
but for certify-book, an omitted ttags argument is treated as nil.
Otherwise, if the :ttags argument is supplied but not :all, then
its value is a true list of ttag specifications, each having one of
the following forms, where sym is a non-nil symbol which is treated
as the corresponding [keyword].
(1) :sym
(2) (:sym)
(3) (:sym x1 x2 ... xk), where k > 0 and each xi is a string, except
that one xi may be nil.
In Case (1), (defttag :sym) is allowed to occur in at most one book
or else in the top-level loop (i.e., the certification world for a
book under certification or a book being included). Case (2) allows
(defttag :sym) to occur in an unlimited number of books. For case
(3) the xi specify where (defttag :sym) may occur, as follows. The
case that xi is nil refers to the top-level loop, while all other
xi are filenames, where the \".lisp\" extension is optional and
relative pathnames are considered to be relative to the connected
book directory (see [cbd]). Note that the restrictions on (defttag
:sym) apply equally to any equivalent for based on the notion of
``corresponding keyword'' discussed above, e.g., (defttag
acl2::sym).
An error message, as shown below, illustrates how ACL2 enforcess the
notion of allowed ttags. Suppose that you call [certify-book] with
argument :ttags (:foo), where you have already executed (defttag
:foo) in the certification world (i.e., before calling
[certify-book]). Then ACL2 immediately associates the ttag :foo
with nil, where again, nil refers to the top-level loop. If ACL2
then encounters (defttag foo) inside that book, you will get the
following error (using the full book name for the book, as shown):
ACL2 Error in ( TABLE ACL2-DEFAULTS-TABLE ...): The ttag :FOO associated
with file /u/smith/work/my-book.lisp is not among the set of ttags permitted
in the current context, specified as follows:
((:FOO NIL)).
See :DOC defttag.
In general the structure displayed by the error message, which is
((:FOO NIL)) in this case, represents the currently allowed ttags
with elements as discussed in (1) through (3) above. In this case,
that list's unique element is (:FOO NIL), meaning that ttag :FOO is
only allowed at the top level (as represented by NIL).
Associating ttags with books and with the top-level loop. When a book
is certified, each form (defttag tag) that is encountered for
non-nil tag in that book or an included book is recorded in the
generated [certificate], which associates the keyword corresponding
to tag with the [full-book-name] of the book containing that
deftag. If such a defttag form is encountered outside a book, hence
in the [portcullis] of the book being certified or one of its
included books, then that keyword is associated with nil in the
generated [certificate]. Note that the notion of ``included book''
here applies to the recursive notion of a book either included
directly in the book being certified or else included in such a
book, where we account even for [local]ly included books.
For examples of ways to take advantage of ttags, see [hacker],
[include-raw], [quicklisp], and more generally [interfacing-tools].
See also [ttags-seen], [progn!], [remove-untouchable],
[set-raw-mode], and [sys-call].
Subtopics
[Push-untouchable]
Add name or list of names to the list of untouchable symbols
[Remove-untouchable]
Remove names from lists of untouchable symbols
[Set-deferred-ttag-notes]
Modify the verbosity of TTAG NOTE printing
[Set-raw-mode]
Enter or exit ``raw mode,'' a raw Lisp environment
[Set-raw-mode-on!]
Enter ``raw mode,'' a raw Lisp environment")
(DEFUN
(EVENTS PROGRAMMING)
"Define a function symbol
Examples:
(defun app (x y)
(if (consp x)
(cons (car x) (app (cdr x) y))
y))
(defun fact (n)
(declare (xargs :guard (and (integerp n)
(>= n 0))))
(if (zp n)
1
(* n (fact (1- n)))))
General Form:
(defun fn (var1 ... varn) doc-string dcl ... dcl body),
where fn is the symbol you wish to define and is a new symbolic name
(see [name]), (var1 ... varn) is its list of formal parameters (see
[name]), and body is its body. The definitional axiom is logically
admissible provided certain restrictions are met. These are
sketched below.
Note that ACL2 does not support the use of lambda-list keywords (such
as &optional) in the formals list of functions. We do support some
such keywords in macros and often you can achieve the desired
syntax by defining a macro in addition to the general version of
your function. See [defmacro]. Doc-string, if non-nil, is an
optional string that can provide documentation but is essentially
ignored by ACL2.
The declarations (see [declare]), dcl, are also optional. If more
than one dcl form appears, they are effectively grouped together as
one. Perhaps the most commonly used ACL2 specific declaration is of
the form (declare (xargs :guard g :measure m)). This declaration in
the defun of some function fn has the effect of making the
``[guard]'' for fn be the term g and the ``measure'' be the term m.
The notion of ``measure'' is crucial to ACL2's definitional
principle. The notion of ``guard'' is not, and is discussed
elsewhere; see [verify-guards] and see
[set-verify-guards-eagerness]. Note that the :measure is ignored in
:[program] mode; see [defun-mode].
We now briefly discuss the ACL2 definitional principle, using the
following definition form which is offered as a more or less
generic example.
(defun fn (x y)
(declare (xargs :guard (g x y)
:measure (m x y)))
(if (test x y)
(stop x y)
(step (fn (d x) y))))
Note that in our generic example, fn has just two arguments, x and y,
the [guard] and measure terms involve both of them, and the body is
a simple case split on (test x y) leading to a ``non-recursive''
branch, (stop x y), and a ``recursive'' branch. In the recursive
branch, fn is called after ``decrementing'' x to (d x) and some
step function is applied to the result. Of course, this generic
example is quite specific in form but is intended to illustrate the
more general case.
Provided this definition is admissible under the logic, as outlined
below, it adds the following axiom to the logic.
Defining Axiom:
(fn x y)
=
(if (test x y)
(stop x y)
(step (fn (d x) y)))
Note that the [guard] of fn has no bearing on this logical axiom.
This defining axiom is actually implemented in the ACL2 system by a
:[definition] rule, namely
(equal (fn x y)
(if (test a b)
(stop a b)
(step (fn (d a) b)))).
See [definition] for a discussion of how definition rules are
applied. Roughly speaking, the rule causes certain instances of (fn
x y) to be replaced by the corresponding instances of the body
above. This is called ``opening up'' (fn x y). The instances of (fn
x y) opened are chosen primarily by heuristics which determine that
the recursive calls of fn in the opened body (after simplification)
are more desirable than the unopened call of fn.
This discussion has assumed that the definition of fn was admissible.
Exactly what does that mean? First, fn must be a previously
unaxiomatized function symbol (however, see
[ld-redefinition-action]). Second, the formal parameters must be
distinct variable names. Third, the [guard], measure, and body
should all be terms and should mention no free variables except the
formal parameters. Thus, for example, body may not contain
references to ``global'' or ``special'' variables; ACL2 constants
or additional formals should be used instead.
The final conditions on admissibility concern the termination of the
recursion. Roughly put, all applications of fn must terminate. In
particular, there must exist a binary relation, rel, and some unary
predicate mp such that rel is well-founded on objects satisfying
mp, the measure term m must always produce something satisfying mp,
and the measure term must decrease according to rel in each
recursive call, under the hypothesis that all the tests governing
the call are satisfied. By the meaning of well-foundedness, we know
there are no infinitely descending chains of successively
rel-smaller mp-objects. Thus, the recursion must terminate.
The only primitive well-founded relation in ACL2 is [o<] (see [o<]),
which is known to be well-founded on the [o-p]s (see [o-p]). For
the proof of well-foundedness, see [proof-of-well-foundedness].
However it is possible to add new well-founded relations. For
details, see [well-founded-relation]. We discuss later how to
specify which well-founded relation is selected by defun and in the
present discussion we assume, without loss of generality, that it
is [o<] on the [o-p]s.
For example, for our generic definition of fn above, with measure
term (m x y), two theorems must be proved. The first establishes
that m produces an ordinal:
(o-p (m x y)).
The second shows that m decreases in the (only) recursive call of fn:
(implies (not (test x y))
(o< (m (d x) y) (m x y))).
Observe that in the latter formula we must show that the ``m-size''
of (d x) and y is ``smaller than'' the m-size of x and y, provided
the test, (test x y), in the body fails, thus leading to the
recursive call (fn (d x) y).
See [o<] for a discussion of this notion of ``smaller than.'' It
should be noted that the most commonly used ordinals are the
natural numbers and that on natural numbers, [o<] is just the
familiar ``less than'' relation ([<]). Thus, it is very common to
use a measure m that returns a nonnegative integer, for then (o-p
(m x y)) becomes a simple conjecture about the type of m and the
second formula above becomes a conjecture about the less-than
relationship of nonnegative integer arithmetic.
The most commonly used measure function is [ACL2-count], which
computes a nonnegative integer size for all ACL2 objects. See
[ACL2-count].
Probably the most common recursive scheme in Lisp [programming] is
when some formal is supposed to be a list and in the recursive call
it is replaced by its [cdr]. For example, (test x y) might be
simply (atom x) and (d x) might be (cdr x). In that case,
(acl2-count x) is a suitable measure because the [ACL2-count] of a
[cons] is strictly larger than the [ACL2-count]s of its [car] and
[cdr]. Thus, ``recursion by [car]'' and ``recursion by [cdr]'' are
trivially admitted if [ACL2-count] is used as the measure and the
definition protects every recursive call by a test insuring that
the decremented argument is a [consp]. Similarly, ``recursion by
[1-]'' in which a positive integer formal is decremented by one in
recursion, is also trivially admissible. See [built-in-clause] to
extend the class of trivially admissible recursive schemes.
We now turn to the question of which well-founded relation defun
uses. It should first be observed that defun must actually select
both a relation (e.g., [o<]) and a domain predicate (e.g., [o-p])
on which that relation is known to be well-founded. But, as noted
elsewhere (see [well-founded-relation]), every known well-founded
relation has a unique domain predicate associated with it and so it
suffices to identify simply the relation here.
The [xargs] field of a [declare] permits the explicit specification
of any known well-founded relation with the keyword
:[well-founded-relation]. An example is given below. If the [xargs]
for a defun specifies a well-founded relation, that relation and
its associated domain predicate are used in generating the
termination conditions for the definition.
If no :[well-founded-relation] is specified, defun uses the
:[well-founded-relation] specified in the [ACL2-defaults-table].
See [set-well-founded-relation] to see how to set the default
well-founded relation (and, implicitly, its domain predicate). The
initial default well-founded relation is [o<] (with domain
predicate [o-p]).
This completes the brief sketch of the ACL2 definitional principle.
Optionally, see [ruler-extenders] for a more detailed discussion of
the termination analysis and resulting proof obligations for
admissibility, as well as a discussion of the relation to how ACL2
stores induction schemes.
On very rare occasions ACL2 will seem to \"hang\" when processing a
definition, especially if there are many subexpressions of the body
whose function symbol is [if] (or which macroexpand to such an
expression). In those cases you may wish to supply the following to
[xargs]: :normalize nil. This is an advanced feature that turns off
ACL2's usual propagation upward of if tests along with potential
simplification with [type-set] reasoning and the expansion of calls
of a few built-in functions.
When a defun form is submitted, ACL2 sometimes computes and stores a
[type-prescription] rule for the function. See
[type-prescription-debugging] for relevant discussion.
The following example illustrates all of the available declarations
and most hint keywords, but is completely nonsensical. For
documentation, see [xargs] and see [hints].
(defun example (x y z a b c i j)
(declare (ignore a b c)
(type integer i j)
(xargs :guard (symbolp x)
:measure (- i j)
:ruler-extenders :basic
:well-founded-relation my-wfr
:hints ((\"Goal\"
:do-not-induct t
:do-not '(generalize fertilize)
:expand ((assoc x a) (member y z))
:restrict ((<-trans ((x x) (y (foo x)))))
:hands-off (length binary-append)
:in-theory (set-difference-theories
(current-theory :here)
'(assoc))
:induct (and (nth n a) (nth n b))
:use ((:instance assoc-of-append
(x a) (y b) (z c))
(:functional-instance
(:instance p-f (x a) (y b))
(p consp)
(f assoc)))))
:guard-hints ((\"Subgoal *1/3'\"
:use ((:instance assoc-of-append
(x a) (y b) (z c)))))
:mode :logic
:normalize nil
:verify-guards nil
:non-executable t
:otf-flg t))
(example-body x y z i j))
Subtopics
[Defn]
Definition with [guard] t
[Defnd]
[disable]d definition with [guard] t
[Defun-inline]
Define a potentially inlined function symbol and associated macro
[Defun-mode]
Determines whether a function definition is a logical act
[Defun-notinline]
Define a not-to-be-inlined function symbol and associated macro
[Defun-nx]
Define a non-executable function symbol
[Defund]
Define a function symbol and then disable it
[Defund-inline]
Define a potentially disabled, inlined function symbol and
associated macro
[Defund-notinline]
Define a disabled, not-to-be-inlined function symbol and associated
macro
[Mutual-recursion]
Define some mutually recursive functions
[Ruler-extenders]
Control for ACL2's termination and induction analyses
[Set-bogus-defun-hints-ok]
Allow unnecessary ([xargs] :hints ...).
[Set-ignore-ok]
Allow unused formals and locals without an ignore or ignorable
declaration
[Set-irrelevant-formals-ok]
Allow irrelevant formals in definitions
[Set-measure-function]
Set the default measure function symbol
[Set-well-founded-relation]
Set the default well-founded relation
[Xargs]
Extra arguments, for example to give [hints] to [defun]")
(DEFUN-INLINE
(DEFUN EVENTS)
"Define a potentially inlined function symbol and associated macro
You may be able to improve performance by replacing an event (defun f
...) with a corresponding event (defun-inline f ...), in order to
encourage the host Lisp compiler to inline calls of f.
Example Form:
(defun-inline lng (x)
(declare (xargs :guard (true-listp x)))
(if (endp x) 0 (1+ (lng (cdr x)))))
General Form:
(defun-inline fn (var1 ... varn) doc-string dcl ... dcl body)
satisfying the same requirements as in the General Form for [defun].
The effect is to define a macro fn and a function fn$inline (i.e.,
a symbol in the same package as fn but whose [symbol-name] has the
suffix \"$INLINE\", such that each call of fn expands to a call of
the function symbol fn$inline on the same arguments. Moreover,
[table] [events] are generated that allow the use of fn in [theory]
expressions to represent fn$inline and that cause any untranslated
(user-level) call of fn$inline to be printed as the corresponding
call of fn. Doc-string, if non-nil, is an optional string that can
provide documentation but is essentially ignored by ACL2.
A form (defun-inline f ...) actually defines a function named
f$inline and a corresponding macro named f whose calls expand to
calls of f$inline, while providing the illusion that there is just
the ``function'' f. For example, the Example Form above
macroexpands in one step to the following form.
(progn (defmacro lng (non-stobj-var0)
(list 'lng$inline non-stobj-var0))
(add-macro-fn lng lng$inline)
(defun lng$inline (x)
(declare (xargs :guard (true-listp x)))
(if (endp x) 0 (1+ (lng (cdr x))))))
Note that the above call of [add-macro-fn] generates the
aforementioned two table events (see [add-macro-fn]), which provide
the illusion that we are just defining a function lng, as you can
see in the following log: lng appears rather than lng$inline.
ACL2 !>(set-gag-mode nil)
<state>
ACL2 !>(thm (equal (lng (append x y))
(+ (lng x) (lng y)))
:hints ((\"Goal\" :in-theory (enable lng))))
[.. output omitted ..]
Subgoal *1/2
(IMPLIES (AND (NOT (ENDP X))
(EQUAL (LNG (APPEND (CDR X) Y))
(+ (LNG (CDR X)) (LNG Y))))
(EQUAL (LNG (APPEND X Y))
(+ (LNG X) (LNG Y)))).
[.. output omitted ..]
Under the hood, ACL2 arranges that every function symbol with suffix
\"$INLINE\" is presented to the compiler as one whose calls we would
prefer to inline. Technically: the Common Lisp form (declaim
(inline f$inline)) is generated for a function symbol f$inline
before that symbol's definition is submitted. However, the Common
Lisp spec explicitly avoids requiring that the compiler respect
this declaim form. Fortunately, Common Lisp implementations often
do respect it.
Also see [defund-inline], see [defun-notinline], and see
[defund-notinline].
Remarks.
(1) None of these macros (including defun-inline) is supported for
use inside a [mutual-recursion].
(2) Every function symbol defined in ACL2 whose [symbol-name] has the
suffix \"$INLINE\" is proclaimed to be inline; similarly for
\"$NOTINLINE\" and notinline.
(3) No special treatment for inlining (or notinlining) is given for
function symbols locally defined by [flet], with two exceptions:
when explicitly declared inline or notinline by the flet form, and
for symbols discussed in (1) and (2) above that, at some point in
the current ACL2 session, were defined as function symbols in ACL2
(even if not currently defined because of undoing or being
[local]).
(4) The function symbol actually being defined by (defun-inline foo
...) is foo$inline. As mentioned above, one can be oblivious to
this fact when writing [theory] expressions or perusing prover
output. However, for other purposes (for example, [verify-guards]
and [defabsstobj] :exports) you will need to supply the name of the
function symbol rather than the name of the macro; e.g., for the
above form (defun-inline foo ...), you may subsequently issue the
event (verify-guards foo$inline) but not (verify-guards foo).
(5) Obscure Remark. Suppose that you certify a book with compilation
(the default) in one host Lisp, saving the expansion file. Suppose
that you then compile in another host Lisp by using [include-book]
with argument :load-compiled-file :comp. Then in subsequent
sessions, including that book with the second host Lisp will not
result in any inline or notinline behavior for functions defined in
the book. This may be fixed in a future release if someone
complains.")
(DEFUN-MODE
(DEFUN)
"Determines whether a function definition is a logical act
Two ``[defun-mode]s'' are supported, :[program] and :[logic]. Roughly
speaking, :[program] mode allows you to prototype a function for
execution without any proof burdens, while :[logic] mode allows you
to add a new definitional axiom to the logic. The system comes up
in :[logic] mode. Execution of functions whose [defun-mode] is
:[program] may render ACL2 unsound! See [defun-mode-caveat].
Note that calls of [local] and of many [events] are skipped in
:program mode; see [program].
When you define a function in the ACL2 logic, that function can be
run on concrete data. But it is also possible to reason deductively
about the function because each definition extends the underlying
logic with a definitional axiom. To ensure that the logic is sound
after the addition of this axiom, certain restrictions have to be
met, namely that the recursion terminates. This can be quite
challenging.
Because ACL2 is a [programming] language, you often may wish simply
to program in ACL2. For example, you may wish to define your system
and test it, without any logical burden. Or, you may wish to define
``utility'' functions --- functions that are executed to help
manage the task of building your system but functions whose logical
properties are of no immediate concern. Such functions might be
used to generate test data or help interpret the results of tests.
They might create files or explore the ACL2 database. The
termination arguments for such functions are an unnecessary burden
provided no axioms about the functions are ever used in deductions.
Thus, ACL2 introduces the idea of the ``[defun-mode]'' of a function.
The :mode keyword of [defun]'s [declare] xarg allows you to specify
the [defun-mode] of a given definition. If no :mode keyword is
supplied, the default [defun-mode] is used; see
[default-defun-mode].
There are two [defun-mode]s, each of which is written as a keyword:
:[program] --- logically undefined but executable outside deductive
contexts.
:[logic] --- axiomatically defined as per the ACL2 definitional
principle.
It is possible to change the [defun-mode] of a function from
:[program] to :[logic]. We discuss this below.
We think of functions having :[program] mode as ``dangerous''
functions, while functions having :[logic] mode are ``safe.'' The
only requirement enforced on :[program] mode functions is the
syntactic one: each definition must be well-formed ACL2. Naively
speaking, if a :[program] mode function fails to terminate then no
harm is done because no axiom is added (so inconsistency is
avoided) and some invocations of the function may simply never
return. This simplistic justification of :[program] mode execution
is faulty because it ignores the damage that might be caused by
``mis-guarded'' functions. See [defun-mode-caveat].
We therefore implicitly describe an imagined implementation of
[defun-mode]s that is safe and, we think, effective. But please see
[defun-mode-caveat].
The default [defun-mode] is :[logic]. This means that when you
[defun] a function the system will try to prove termination. If you
wish to introduce a function of a different [defun-mode] use the
:mode [xargs] keyword. Below we show fact introduced as a function
in :[program] mode.
(defun fact (n)
(declare (xargs :mode :program))
(if (or (not (integerp n)) (= n 0))
1
(* n (fact (1- n)))))
No axiom is added to the logic as a result of this definition. By
introducing fact in :[program] mode we avoid the burden of a
termination proof, while still having the option of executing the
function. For example, you can type
ACL2 !>(fact 3)
and get the answer 6. If you type (fact -1) you will get a hard lisp
error due to ``infinite recursion.''
However, the ACL2 theorem prover knows no axioms about fact. In
particular, if the term (fact 3) arises in a proof, the theorem
prover is unable to deduce that it is 6. From the perspective of
the theorem prover it is as though fact were an undefined function
symbol of arity 1. Thus, modulo certain important issues (see
[defun-mode-caveat]), the introduction of this function in
:[program] mode does not imperil the soundness of the system ---
despite the fact that the termination argument for fact was omitted
--- because nothing of interest can be proved about fact. Indeed,
we do not allow fact to be used in logical contexts such as
conjectures submitted for proof.
It is possible to convert a function from :[program] mode to :[logic]
mode at the cost of proving that it is admissible. This can be done
by invoking
(verify-termination fact)
which is equivalent to submitting the [defun] of fact, again, but in
:[logic] mode.
(defun fact (n)
(declare (xargs :mode :logic))
(if (or (not (integerp n)) (= n 0))
1
(* n (fact (1- n)))))
This particular event will fail because the termination argument
requires that n be nonnegative. A repaired [defun], for example
with [=] replaced by [<=], will succeed, and an axiom about fact
will henceforth be available.
Technically, [verify-termination] submits a redefinition of the
:[program] mode function. This is permitted, even when
[ld-redefinition-action] is nil, because the new definition is
identical to the old (except for its :mode and, possibly, other
non-logical properties).
See [guard] for a discussion of how to restrict the execution of
functions. [Guard]s may be ``verified'' for functions in :[logic]
mode; see [verify-guards].
Subtopics
[Logic]
To set the default [defun-mode] to :logic
[Program]
To set the default [defun-mode] to :[program]")
(DEFUN-MODE-CAVEAT
(COMMON-LISP)
"Potential soundness issue for functions with [defun-mode] :[program]
Technically speaking, in the current implementation, the execution of
functions having [defun-mode] :[program] may damage the ACL2 system
in a way that renders it unsound. In practice, we have never seen
this happen; so, the explanations below can be viewed as extremely
paranoid. Nevertheless, here we document this concern, even if it
should be taken with more than a grain of salt.
See [defun-mode] for a discussion of [defun-mode]s. That discussion
describes an imagined implementation that is slightly different
from this one. This note explains that the current implementation
is open to unsoundness.
For discussion of a different soundness issue that is also related to
function execution, see [generalized-booleans].
The execution of a function having [defun-mode] :[program] may
violate Common Lisp [guard]s on the subroutines used. (This may be
true even for calls of a function on arguments that satisfy its
[guard], because ACL2 has not verified that its [guard] is
sufficient to protect its subroutines.) When a [guard] is violated
at runtime all bets are off. That is, no guarantees are made either
about the answer being ``right'' or about the continued rationality
of the ACL2 system itself.
For example, suppose you make the following [defun]:
(defun crash (i)
(declare (xargs :mode :program :guard (integerp i)))
(car i))
Note that the declared guard does not in fact adequately protect the
subroutines in the body of crash; indeed, satisfying the guard to
crash will guarantee that the [car] expression is in violation of
its guard. Because this function is admitted in :[program]-mode, no
checks are made concerning the suitability of the guard.
Furthermore, in the current ACL2 implementation, crash is executed
directly in Common Lisp. Thus if you call crash on an argument
satisfying its guard you will cause an erroneous computation to
take place.
ACL2 !>(crash 7)
Error: Caught fatal error [memory may be damaged]
...
There is no telling how much damage is done by this errant
computation. In some lisps your ACL2 job may actually crash back to
the operating system. In other lisps you may be able to recover
from the ``hard error'' and resume ACL2 in a damaged but apparently
functional image.
THUS, HAVING A FUNCTION WITH [defun-mode] :[program] IN YOUR SYSTEM
ABSOLVES US, THE ACL2 IMPLEMENTORS, FROM RESPONSIBILITY FOR THE
SOUNDNESS OF OUR SYSTEM.
Furthermore
ACL2 DOES NOT YET PROVIDE ANY MEANS OF REGAINING ASSURANCES OF
SOUNDNESS AFTER THE INTRODUCTION OF A FUNCTION IN :[program] MODE,
EVEN IF IT IS ULTIMATELY CONVERTED TO :[logic] MODE (since its
execution could have damaged the system in a way that makes it
possible to verify its termination and [guard]s unsoundly).
Finally,
THE VAST MAJORITY OF ACL2 SYSTEM CODE IS IN :[program] MODE AND SO
ALL BETS ARE OFF FROM BEFORE YOU START!
This hopeless state of current affairs will change, we think. We
think we have defined our functions ``correctly'' in the sense that
they can be converted, without ``essential'' modification, to
:[logic] mode. We think it very unlikely that a mis-guarded
function in :[program] mode (whether ours or yours) will cause
unsoundness without some sort of hard lisp error accompanying it.
We think that ultimately we can make it possible to execute your
functions (interpretively) without risk to the system, even when
some have :[program] mode. In that imagined implementation, code
using functions having :[program] mode would run more slowly, but
safely. These functions could be introduced into the logic ex post
facto, whereupon the code's execution would speed up because Common
Lisp would be allowed to execute it directly. We therefore ask that
you simply pretend that this is that imagined implementation,
introduce functions in :[program] mode, use them as convenient and
perhaps ultimately introduce some of them in :[logic] mode and
prove their properties. If you use the system this way we can
develop (or dismiss) this style of formal system development. BUT
BE ON THE LOOKOUT FOR SCREWUPS DUE TO DAMAGE CAUSED BY THE
EXECUTION OF YOUR FUNCTIONS HAVING :[program] MODE!")
(DEFUN-NOTINLINE
(DEFUN EVENTS)
"Define a not-to-be-inlined function symbol and associated macro
See [defun-inline] for an analogous utility that supports inlining.
The present utility is probably far less useful; it tells the
compiler not to inline calls of the function being defined. Also
see [defund-notinline] for a variant of this event that disables
the newly-defined function symbol.
Under the hood, (defun-inline f ...) and (defun-notinline f ...)
cause evaluation of Common Lisp forms (declaim (inline f$inline))
and (declaim (notinline f$notinline)), respectively. According to
the Common Lisp spec, the compiler need not respect the first of
these (for inline), but it must respect the second of these (for
notinline). Fortunately, Common Lisp implementations often do
respect the first of these as well.")
(DEFUN-NX
(DEFUN EVENTS)
"Define a non-executable function symbol
Example:
(set-state-ok t)
(defun-nx foo (x state)
(mv-let (a b c)
(cons x state)
(list a b c b a)))
; Note ``ill-formed'' call of foo just below.
(defun bar (state y)
(foo state y))
The macro defun-nx introduces definitions using the [defun] macro,
always in :[logic] mode, such that the calls of the resulting
function cannot be evaluated. Such a definition is admitted without
enforcing syntactic restrictions for executability, in particular
for single-threadedness (see [stobj]) and multiple-values passing
(see [mv] and see [mv-let]). After such a definition is admitted,
the usual syntactic rules for [state] and user-defined [stobj]s are
relaxed for calls of the function it defines. Also see [non-exec]
for a way to designate subterms of function bodies, or subterms of
code to be executed at the top level, as non-executable.
The syntax of defun-nx is identical to that of [defun]. A form
(defun-nx name (x1 ... xk) ... body)
expands to the following form.
(defun name (x1 ... xk)
(declare (xargs :non-executable t :mode :logic))
...
(prog2$ (throw-nonexec-error 'name (list x1 ... xk))
body))
Note that because of the insertion of the above call of
throw-nonexec-error, no formal is ignored when using defun-nx.
During proofs, the error is silent; it is ``caught'' by the proof
mechanism and generally results in the introduction of a call of
[hide] during a proof. If an error message is produced by
evaluating a call of the function on a list of arguments that
includes state or user-defined [stobj]s, these arguments will be
shown as symbols such as |<state>| in the error message. In the
case of a user-defined stobj bound by [with-local-stobj] or
[stobj-let], the symbol printed will include the suffix {instance},
for example, |<st>{instance}|.
It is harmless to include :non-executable t in your own [xargs]
[declare] form; defun-nx will still lay down its own such
declaration, but ACL2 can tolerate the duplication.
Note that defund-nx is also available. It has an effect identical to
that of defun-nx except that as with [defund], it leaves the
function disabled.
If you use guards (see [guard]), please be aware that even though
syntactic restrictions are relaxed for defun-nx, guard verification
proceeds exactly as for [defun]. If you want ACL2 to skip a form
for purposes of generating guard proof obligations, use the macro
[non-exec], which generates a call of throw-nonexec-error that
differs somewhat from the one displayed above. See [non-exec].
See [defun] for documentation of defun.")
(DEFUN-SK
(EVENTS)
"Define a function whose body has an outermost quantifier
Examples:
(defun-sk exists-x-p0-and-q0 (y z)
(exists x
(and (p0 x y z)
(q0 x y z))))
(defun-sk exists-x-p0-and-q0 (y z) ; equivalent to the above
(exists (x)
(and (p0 x y z)
(q0 x y z))))
(defun-sk forall-x-y-p0-and-q0 (z)
(forall (x y)
(and (p0 x y z)
(q0 x y z)))
:strengthen t)
General Form:
(defun-sk fn (var1 ... varn) body
&key rewrite quant-ok skolem-name thm-name witness-dcls strengthen)
where fn is the symbol you wish to define and is a new symbolic name
(see [name]), (var1 ... varn) is its list of formal parameters (see
[name]), and body is its body, which must be quantified as
described below. The other arguments are explained below.
For a simple example, see [defun-sk-example]. For a more elaborate
example, see [Tutorial4-Defun-Sk-Example]. See
[quantifier-tutorial] for a careful beginner's introduction that
takes you through typical kinds of quantifier-based reasoning in
ACL2. Also see [quantifiers] for an example illustrating how the
use of recursion, rather than explicit quantification with
defun-sk, may be preferable.
Below we describe the defun-sk event precisely. First, let us
consider the examples above. The first example, again, is:
(defun-sk exists-x-p0-and-q0 (y z)
(exists x
(and (p0 x y z)
(q0 x y z))))
It is intended to represent the predicate with formal parameters y
and z that holds when for some x, (and (p0 x y z) (q0 x y z))
holds. In fact defun-sk is a macro that adds the following two
[events], as shown just below. The first event guarantees that if
this new predicate holds of y and z, then the term shown,
(exists-x-p0-and-q0-witness y z), is an example of the x that is
therefore supposed to exist. (Intuitively, we are axiomatizing
exists-x-p0-and-q0-witness to pick a witness if there is one. We
comment below on the use of [defun-nx]; for now, consider defun-nx
to be [defun].) Conversely, the second event below guarantees that
if there is any x for which the term in question holds, then the
new predicate does indeed hold of y and z.
(defun-nx exists-x-p0-and-q0 (y z)
(let ((x (exists-x-p0-and-q0-witness y z)))
(and (p0 x y z) (q0 x y z))))
(defthm exists-x-p0-and-q0-suff
(implies (and (p0 x y z) (q0 x y z))
(exists-x-p0-and-q0 y z)))
Now let us look at the third example from the introduction above:
(defun-sk forall-x-y-p0-and-q0 (z)
(forall (x y)
(and (p0 x y z)
(q0 x y z))))
The intention is to introduce a new predicate (forall-x-y-p0-and-q0
z) which states that the indicated conjunction holds of all x and
all y together with the given z. This time, the axioms introduced
are as shown below. The first event guarantees that if the
application of function forall-x-y-p0-and-q0-witness to z picks out
values x and y for which the given term (and (p0 x y z) (q0 x y z))
holds, then the new predicate forall-x-y-p0-and-q0 holds of z.
Conversely, the (contrapositive of) the second axiom guarantees
that if the new predicate holds of z, then the given term holds for
all choices of x and y (and that same z).
(defun-nx forall-x-y-p0-and-q0 (z)
(mv-let (x y)
(forall-x-y-p0-and-q0-witness z)
(and (p0 x y z) (q0 x y z))))
(defthm forall-x-y-p0-and-q0-necc
(implies (not (and (p0 x y z) (q0 x y z)))
(not (forall-x-y-p0-and-q0 z))))
The examples above suggest the critical property of defun-sk: it
indeed does introduce the quantified notions that it claims to
introduce.
Notice that the [defthm] event just above, forall-x-y-p0-and-q0-necc,
may not be of optimal form as a rewrite rule. Users sometimes find
that when the quantifier is forall, it is useful to state this rule
in a form where the new quantified predicate is a hypothesis
instead. In this case that form would be as follows:
(defthm forall-x-y-p0-and-q0-necc
(implies (forall-x-y-p0-and-q0 z)
(and (p0 x y z) (q0 x y z))))
ACL2 will turn this into one :[rewrite] rule for each conjunct, (p0 x
y z) and (q0 x y z), with hypothesis (forall-x-y-p0-and-q0 z) in
each case. In order to get this effect, use :rewrite :direct, in
this case as follows.
(defun-sk forall-x-y-p0-and-q0 (z)
(forall (x y)
(and (p0 x y z)
(q0 x y z)))
:rewrite :direct)
We now turn to a detailed description of defun-sk, starting with a
discussion of its arguments as shown in the \"General Form\" above.
The third argument, body, must be of the form
(Q bound-vars term)
where: Q is the symbol [forall] or [exists], in the \"ACL2\" package;
bound-vars is a variable or true list of variables disjoint from
(var1 ... varn) and not including [state]; and term is a term. The
case that bound-vars is a single variable v is treated exactly the
same as the case that bound-vars is (v).
The result of this event is to introduce a ``Skolem function,'' whose
name is the keyword argument skolem-name if that is supplied, and
otherwise is the result of modifying fn by suffixing \"-WITNESS\" to
its name. The following definition and one of the following two
theorems (as indicated) are introduced for skolem-name and fn in
the case that bound-vars (see above) is a single variable v. The
name of the [defthm] event may be supplied as the value of the
keyword argument :thm-name; if it is not supplied, then it is the
result of modifying fn by suffixing \"-SUFF\" to its name in the case
that the quantifier is [exists], and \"-NECC\" in the case that the
quantifier is [forall].
(defun-nx fn (var1 ... varn)
(let ((v (skolem-name var1 ... varn)))
term))
(defthm fn-suff ;in case the quantifier is EXISTS
(implies term
(fn var1 ... varn)))
(defthm fn-necc ;in case the quantifier is FORALL
(implies (not term)
(not (fn var1 ... varn))))
In the forall case, however, the keyword pair :rewrite :direct may be
supplied after the body of the defun-sk form, in which case the
contrapositive of the above form is used instead:
(defthm fn-necc ;in case the quantifier is FORALL
(implies (fn var1 ... varn)
term))
This is often a better choice for the \"-NECC\" rule, provided ACL2 can
parse term as a :[rewrite] rule. A second possible value of the
:rewrite argument of defun-sk is :default, which gives the same
behavior as when :rewrite is omitted. Otherwise, the value of
:rewrite should be the term to use as the body of the fn-necc
theorem shown above; ACL2 will attempt to do the requisite proof in
this case. If that term is weaker than the default, the properties
introduced by defun-sk may of course be weaker than they would be
otherwise. Finally, note that the :rewrite keyword argument for
defun-sk only makes sense if the quantifier is forall; it is thus
illegal if the quantifier is exists. Enough said about :rewrite!
In the case that bound-vars is a list of at least two variables, say
(bv1 ... bvk), the definition above (with no keywords) is the
following instead, but the theorem remains unchanged.
(defun-nx fn (var1 ... varn)
(mv-let (bv1 ... bvk)
(skolem-name var1 ... varn)
term))
In order to emphasize that the last element of the list, body, is a
term, defun-sk checks that the symbols [forall] and [exists] do not
appear anywhere in it. However, on rare occasions one might
deliberately choose to violate this convention, presumably because
[forall] or [exists] is being used as a variable or because a macro
call will be eliminating ``calls of'' [forall] and [exists]. In
these cases, the keyword argument quant-ok may be supplied a
non-nil value. Then defun-sk will permit [forall] and [exists] in
the body, but it will still cause an error if there is a real
attempt to use these symbols as quantifiers.
The use of [defun-nx] above, rather than [defun], disables certain
checks that are required for evaluation, in particular the
single-threaded use of [stobj]s. However, there is a price: calls
of these defined functions cannot be evaluated; see [defun-nx].
Normally that is not a problem, since these notions involve
quantifiers. But you are welcome to replace this [declare] form
with your own, as follows: if you supply a list of declare forms to
keyword argument :witness-dcls, these will become the declare forms
in the generated [defun]. Note that if your value of witness-dcls
does not contain the form (declare (xargs :non-executable t)), then
the appropriate wrapper for non-executable functions will not be
added automatically, i.e., [defun] will be used in place of
defun-nx. Note also that if [guard] verification is attempted, then
it will likely fail with an error message complaining that ``guard
verification may depend on local properties.'' In that case, you
may wish to delay guard verification, as in the following example.
(encapsulate
()
(defun-sk foo (x)
(exists n (and (integerp n)
(< n x)))
:witness-dcls ((declare (xargs :guard (integerp x)
:verify-guards nil))))
(verify-guards foo))
Defun-sk is a macro implemented using [defchoose]. Hence, it should
only be executed in [defun-mode] :[logic]; see [defun-mode] and see
[defchoose]. Advanced feature: If argument :strengthen t is passed
to defun-sk, then :strengthen t will generate the extra constraint
that that is generated for the corresponding defchoose event; see
[defchoose]. You can use the command :[pcb!] to see the event
generated by a call of the defun-sk macro.
If you find that the rewrite rules introduced with a particular use
of defun-sk are not ideal, even when using the :rewrite keyword
discussed above (in the forall case), then at least two reasonable
courses of action are available for you. Perhaps the best option is
to prove the [rewrite] rules you want. If you see a pattern for
creating rewrite rules from your defun-sk events, you might want to
write a macro that executes a defun-sk followed by one or more
[defthm] events. Another option is to write your own variant of the
defun-sk macro, say, my-defun-sk, for example by modifying a copy
of the definition of defun-sk from the ACL2 sources.
If you want to represent nested quantifiers, you can use more than
one defun-sk event. For example, in order to represent
(forall x (exists y (p x y z)))
you can use defun-sk twice, for example as follows.
(defun-sk exists-y-p (x z)
(exists y (p x y z)))
(defun-sk forall-x-exists-y-p (z)
(forall x (exists-y-p x z)))
Some distracting and unimportant warnings are inhibited during
defun-sk.
Note for ACL2(r) users (see [real]): In ACL2(r), the keyword
:CLASSICALP is also supported. Its legal values are t (the default)
and nil, and it determines whether or not (respectively) ACL2(r)
will consider fn to be a classical function. It must be the case
that the value is t (perhaps implicitly, by default) if and only if
body is classical.
Note that this way of implementing quantifiers is not a new idea.
Hilbert was certainly aware of it 60 years ago! Also see
[conservativity-of-defchoose] for a technical argument that
justifies the logical conservativity of the [defchoose] event in
the sense of the paper by Kaufmann and Moore entitled ``Structured
Theory Development for a Mechanized Logic'' (Journal of Automated
Reasoning 26, no. 2 (2001), pp. 161-203).
Subtopics
[Defun-sk-example]
A simple example using [defun-sk]
[Exists]
Existential quantifier
[Forall]
Universal quantifier
[Quantifier-tutorial]
A Beginner's Guide to Reasoning about Quantification in ACL2
[Quantifiers]
Issues about quantification in ACL2")
(DEFUN-SK-EXAMPLE
(DEFUN-SK)
"A simple example using [defun-sk]
For a more through, systematic beginner's introduction to
quantification in ACL2, see [quantifier-tutorial].
The following example illustrates how to do proofs about functions
defined with [defun-sk]. The events below can be put into a
certifiable book (see [books]). The example is contrived and rather
silly, in that it shows how to prove that a quantified notion
implies itself, where the antecedent and conclusion are defined
with different [defun-sk] events. But it illustrates the formulas
that are generated by [defun-sk], and how to use them. Thanks to
Julien Schmaltz for presenting this example as a challenge.
(in-package \"ACL2\")
(encapsulate
(((p *) => *)
((expr *) => *))
(local (defun p (x) x))
(local (defun expr (x) x)))
(defun-sk forall-expr1 (x)
(forall (y) (implies (p x) (expr y))))
(defun-sk forall-expr2 (x)
(forall (y) (implies (p x) (expr y)))))
; We want to prove the theorem my-theorem below. What axioms are there that
; can help us? If you submit the command
; :pcb! forall-expr1
; then you will see the following two key events. (They are completely
; analogous of course for FORALL-EXPR2.)
; (DEFUN FORALL-EXPR1 (X)
; (LET ((Y (FORALL-EXPR1-WITNESS X)))
; (IMPLIES (P X) (EXPR Y))))
;
; (DEFTHM FORALL-EXPR1-NECC
; (IMPLIES (NOT (IMPLIES (P X) (EXPR Y)))
; (NOT (FORALL-EXPR1 X)))
; :HINTS
; ((\"Goal\" :USE FORALL-EXPR1-WITNESS)))
; We see that the latter has value when FORALL-EXPR1 occurs negated in a
; conclusion, or (therefore) positively in a hypothesis. A good rule to
; remember is that the former has value in the opposite circumstance: negated
; in a hypothesis or positively in a conclusion.
; In our theorem, FORALL-EXPR2 occurs positively in the conclusion, so its
; definition should be of use. We therefore leave its definition enabled,
; and disable the definition of FORALL-EXPR1.
; (thm
; (implies (and (p x) (forall-expr1 x))
; (forall-expr2 x))
; :hints ((\"Goal\" :in-theory (disable forall-expr1))))
;
; ; which yields this unproved subgoal:
;
; (IMPLIES (AND (P X) (FORALL-EXPR1 X))
; (EXPR (FORALL-EXPR2-WITNESS X)))
; Now we can see how to use FORALL-EXPR1-NECC to complete the proof, by
; binding y to (FORALL-EXPR2-WITNESS X).
; We use defthmd below so that the following doesn't interfere with the
; second proof, in my-theorem-again that follows.
(defthmd my-theorem
(implies (and (p x) (forall-expr1 x))
(forall-expr2 x))
:hints ((\"Goal\"
:use ((:instance forall-expr1-necc
(x x)
(y (forall-expr2-witness x)))))))
; The following illustrates a more advanced technique to consider in such
; cases. If we disable forall-expr1, then we can similarly succeed by having
; FORALL-EXPR1-NECC applied as a :rewrite rule, with an appropriate hint in how
; to instantiate its free variable. See :doc hints.
(defthm my-theorem-again
(implies (and (P x) (forall-expr1 x))
(forall-expr2 x))
:hints ((\"Goal\"
:in-theory (disable forall-expr1)
:restrict ((forall-expr1-necc
((y (forall-expr2-witness x))))))))")
(DEFUND
(DEFUN EVENTS)
"Define a function symbol and then disable it
Use defund instead of [defun] when you want to disable a function
immediately after its definition in :[logic] mode. This macro has
been provided for users who prefer working in a mode where
functions are only enabled when explicitly directed by
:[in-theory]. Specifically, the form
(defund NAME FORMALS ...)
expands to:
(progn
(defun NAME FORMALS ...)
(with-output
:off summary
(in-theory (disable NAME)))
(value-triple '(:defund NAME))).
Only the :[definition] rule (and, for recursively defined functions,
the :[induction] rule) for the function are disabled. In
particular, defund does not disable either the :[type-prescription]
or the :[executable-counterpart] rule. Also, the summary for the
[in-theory] event is suppressed.
If the function is defined in :[program] mode, either because the
[default-defun-mode] is :[program] or because :mode :program has
been specified in an [xargs] form of a [declare] form, then no
[in-theory] event is executed. (More precisely, [in-theory] events
are ignored when the [default-defun-mode] is :[program], and if
:mode :program is specified then defund does not generate an
[in-theory] event.)
Note that defund commands are never redundant (see
[redundant-events]) when the [default-defun-mode] is :[logic],
because the [in-theory] event will always be executed.
See [defun] for documentation of defun.")
(DEFUND-INLINE
(DEFUN EVENTS)
"Define a potentially disabled, inlined function symbol and associated
macro
Defund-inline is a variant of [defun-inline], the difference being
that defund-inline disables the newly-defined function symbol. See
[defun-inline].")
(DEFUND-NOTINLINE
(DEFUN EVENTS)
"Define a disabled, not-to-be-inlined function symbol and associated
macro
Defund-notinline is a variant of [defun-notinline], the difference
being that defund-notinline disables the newly-defined function
symbol. See [defun-notinline].")
(DEFUNS
(MUTUAL-RECURSION)
"An alternative to [mutual-recursion]
Example:
(DEFUNS
(evenlp (x)
(if (consp x) (oddlp (cdr x)) t))
(oddlp (x)
(if (consp x) (evenlp (cdr x)) nil)))
General Form:
(DEFUNS defuns-tuple1 ... defuns-tuplen)
is equivalent to
(MUTUAL-RECURSION
(DEFUN . defuns-tuple1)
...
(DEFUN . defuns-tuplen))
In fact, defuns is the more primitive of the two and
[mutual-recursion] is just a macro that expands to a call of
[defun] after stripping off the [defun] at the [car] of each
argument to [mutual-recursion]. We provide and use
[mutual-recursion] rather than defuns because by leaving the
[defun]s in place, [mutual-recursion] forms can be processed by the
Emacs tags program. See [mutual-recursion].")
(DELETE-ASSOC
(ALISTS ACL2-BUILT-INS)
"Remove the first pair from an association list for a given key
General Forms:
(delete-assoc key alist)
(delete-assoc key alist :test 'eql) ; same as above (eql as equality test)
(delete-assoc key alist :test 'eq) ; same, but eq is equality test
(delete-assoc key alist :test 'equal) ; same, but equal is equality test
(Delete-assoc key alist) returns an alist that is the same as the
list alist, except that the first pair in alist with a [car] of key
is deleted, if there is one; otherwise alist is returned. Note that
the order of the elements of alist is unchanged (though one may be
deleted).
The [guard] for a call of delete-assoc depends on the test. In all
cases, the second argument must satisfy [alistp]. If the test is
[eql], then either the first argument must be suitable for [eql]
(see [eqlablep]) or the second argument must satisfy
[eqlable-alistp]. If the test is [eq], then either the first
argument must be a symbol or the second argument must satisfy
[symbol-alistp].
See [equality-variants] for a discussion of the relation between
delete-assoc and its variants:
(delete-assoc-eq key alist) is equivalent to (delete-assoc key alist
:test 'eq);
(delete-assoc-equal key alist) is equivalent to (delete-assoc key
alist :test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function delete-assoc-equal.
Function: <delete-assoc-equal>
(defun delete-assoc-equal (key alist)
(declare (xargs :guard (alistp alist)))
(cond ((endp alist) nil)
((equal key (caar alist)) (cdr alist))
(t (cons (car alist)
(delete-assoc-equal key (cdr alist))))))")
(DELETE-ASSOC-EQ (POINTERS)
"See [delete-assoc].")
(DELETE-ASSOC-EQUAL (POINTERS)
"See [delete-assoc].")
(DELETE-INCLUDE-BOOK-DIR
(BOOKS-REFERENCE)
"Unlink keyword for :dir argument of [ld] and [include-book]
Example Forms:
; Remove association of a directory with :smith for include-book and ld:
(delete-include-book-dir :smith)
General Form:
(delete-include-book-dir kwd)
where kwd is a [keywordp]. The effect of this event is to modify the
meaning of the :dir keyword argument of [include-book] and [ld] as
indicated by the example above, namely by removing association of a
directory with the indicated keyword for purposes of the :dir
argument of [include-book] and [ld]. See [add-include-book-dir] for
how to associate a new directory with a keyword.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
This macro is [local] to any [books] and [encapsulate] [events] in
which it occurs; see [add-include-book-dir] for a discussion of
this aspect of both macros. For non-local associations of keywords
with directories, see [add-include-book-dir!] and
[delete-include-book-dir!]. Note that delete-include-book-dir may
only be used to remove keywords added by calls of
[add-include-book-dir], and [delete-include-book-dir!] may only be
used to remove keywords added by calls of [add-include-book-dir!]")
(DELETE-INCLUDE-BOOK-DIR!
(BOOKS-REFERENCE)
"Non-[local]ly unlink keyword for :dir argument of [ld] and
[include-book]
Please see [delete-include-book-dir], which has completely analogous
syntax and semantics, but is used for removing associations
previously placed by [add-include-book-dir]. By contrast,
delete-include-book-dir! removes associations previously placed by
[add-include-book-dir!].
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
This macro is essentially a [table] event that updates the table
include-book-dir!-table, which associates keywords with absolute
pathnames. However, as with [delete-include-book-dir], direct table
updates are disallowed; you must use delete-include-book-dir! to
remove from the table and [add-include-book-dir!] to add to the
table.
It is illegal to call delete-include-book-dir! in a [local] context.
For an explanation, see [add-include-book-dir!].")
(DENOMINATOR
(NUMBERS ACL2-BUILT-INS)
"Divisor of a ratio in lowest terms
Completion Axiom (completion-of-denominator):
(equal (denominator x)
(if (rationalp x)
(denominator x)
1))
[Guard] for (denominator x):
(rationalp x)")
(DIGIT-CHAR-P
(CHARACTERS ACL2-BUILT-INS)
"The number, if any, corresponding to a given character
(digit-char-p ch) is the integer corresponding to the character ch in
base 10. For example, (digit-char-p #\\3) is equal to the integer 3.
More generally, an optional second argument specifies the radix
(default 10, as indicated above).
The [guard] for digit-char-p (more precisely, for the function
our-digit-char-p that calls of this macro expand to) requires its
second argument to be an integer between 2 and 36, inclusive, and
its first argument to be a character.
Digit-char-p is a Common Lisp function, though it is implemented in
the ACL2 logic as an ACL2 macro. See any Common Lisp documentation
for more information.
Macro: <digit-char-p>
(defmacro digit-char-p (ch &optional (radix '10))
(cons 'our-digit-char-p
(cons ch (cons radix 'nil))))
Function: <our-digit-char-p>
(defun our-digit-char-p (ch radix)
(declare (xargs :guard (and (characterp ch)
(integerp radix)
(<= 2 radix)
(<= radix 36))))
(let ((l (assoc ch
'((#\\0 . 0)
(#\\1 . 1)
(#\\2 . 2)
(#\\3 . 3)
(#\\4 . 4)
(#\\5 . 5)
(#\\6 . 6)
(#\\7 . 7)
(#\\8 . 8)
(#\\9 . 9)
(#\\a . 10)
(#\\b . 11)
(#\\c . 12)
(#\\d . 13)
(#\\e . 14)
(#\\f . 15)
(#\\g . 16)
(#\\h . 17)
(#\\i . 18)
(#\\j . 19)
(#\\k . 20)
(#\\l . 21)
(#\\m . 22)
(#\\n . 23)
(#\\o . 24)
(#\\p . 25)
(#\\q . 26)
(#\\r . 27)
(#\\s . 28)
(#\\t . 29)
(#\\u . 30)
(#\\v . 31)
(#\\w . 32)
(#\\x . 33)
(#\\y . 34)
(#\\z . 35)
(#\\A . 10)
(#\\B . 11)
(#\\C . 12)
(#\\D . 13)
(#\\E . 14)
(#\\F . 15)
(#\\G . 16)
(#\\H . 17)
(#\\I . 18)
(#\\J . 19)
(#\\K . 20)
(#\\L . 21)
(#\\M . 22)
(#\\N . 23)
(#\\O . 24)
(#\\P . 25)
(#\\Q . 26)
(#\\R . 27)
(#\\S . 28)
(#\\T . 29)
(#\\U . 30)
(#\\V . 31)
(#\\W . 32)
(#\\X . 33)
(#\\Y . 34)
(#\\Z . 35)))))
(cond ((and l (< (cdr l) radix)) (cdr l))
(t nil))))")
(DIGIT-TO-CHAR
(CHARACTERS ACL2-BUILT-INS)
"Map a digit to a character
Example:
ACL2 !>(digit-to-char 8)
#\\8
For an integer n from 0 to 15, (digit-to-char n) is the character
corresponding to n in hex notation, using uppercase letters for
digits exceeding 9. If n is in the appropriate range, that result
is of course also the binary, octal, and decimal digit.
The [guard] for digit-to-char requires its argument to be an integer
between 0 and 15, inclusive.
Function: <digit-to-char>
(defun
digit-to-char (n)
(declare (xargs :guard (and (integerp n) (<= 0 n) (<= n 15))))
(case n (1 #\\1)
(2 #\\2)
(3 #\\3)
(4 #\\4)
(5 #\\5)
(6 #\\6)
(7 #\\7)
(8 #\\8)
(9 #\\9)
(10 #\\A)
(11 #\\B)
(12 #\\C)
(13 #\\D)
(14 #\\E)
(15 #\\F)
(otherwise #\\0)))")
(DIMENSIONS
(ARRAYS ACL2-BUILT-INS)
"Return the :dimensions from the [header] of a 1- or 2-dimensional
array
Example Form:
(dimensions 'delta1 a)
General Form:
(dimensions name alist)
where name is arbitrary and alist is a 1- or 2-dimensional array.
This function returns the dimensions list of the array alist. That
list will either be of the form (dim1) or (dim1 dim2), depending on
whether alist is a 1- or 2-dimensional array. Dim1 and dim2 will be
integers and each exceed by 1 the maximum legal corresponding
index. Thus, if dimensions returns, say, '(100) for an array a
named 'delta1, then (aref1 'delta1 a 99) is legal but (aref1
'delta1 a 100) violates the [guard]s on [aref1]. Dimensions
operates in virtually constant time if alist is the semantic value
of name. See [arrays].
Function: <dimensions>
(defun
dimensions (name l)
(declare (xargs :guard (or (array1p name l) (array2p name l))))
(cadr (assoc-keyword :dimensions (cdr (header name l)))))")
(DISABLE
(THEORIES THEORY-FUNCTIONS)
"Deletes names from current theory
Example:
(disable fact (fact) associativity-of-app)
General Form:
(disable name1 name2 ... namek)
where each namei is a runic designator; see [theories]. The result is
the theory that contains all the names in the current theory except
those listed. Note that this is merely a function that returns a
theory. The result is generally a very long list of [rune]s and you
will probably regret printing it.
For related utilities, see [enable] and see [e/d].
The standard way to ``disable'' a fixed set of names, is as follows;
see [hints] and see [in-theory].
:in-theory (disable name1 name2 ... namek) ; in a hint
(in-theory (disable name1 name2 ... namek)) ; as an event
(local ; often desirable, to avoid exporting from the current context
(in-theory (disable name1 name2 ... namek)))
Note that all the names are implicitly quoted. If you wish to disable
a computed list of names, lst, use the theory expression
(set-difference-theories (current-theory :here) lst).")
(DISABLE-FORCING
(FORCE)
"To disallow forced case-splits
General Form:
ACL2 !>:disable-forcing ; disallow forced case splits
See [force] and see [case-split] for a discussion of forced case
splits, which are inhibited by this command.
Disable-forcing is actually a macro that [disable]s the executable
counterpart of the function symbol force; see [force]. When you
want to use [hints] to turn off forced case splits, use a form such
as one of the following (these are equivalent).
:in-theory (disable (:executable-counterpart force))
:in-theory (disable (force))
The following example shows how this works. First evaluate these
forms.
(defstub f1 (x) t)
(defstub f2 (x) t)
(defaxiom ax (implies (case-split (f2 x)) (f1 x)))
(thm (f1 x))
You will see the application of the rule, ax, in the proof of the
[thm] call above. However, if you first evaluate (disable-forcing),
then there will be no application of ax. To restore forced case
splitting, see [enable-forcing].")
(DISABLE-IMMEDIATE-FORCE-MODEP
(FORCE)
"[force]d hypotheses are not attacked immediately
General Form:
ACL2 !>:disable-immediate-force-modep
This event causes ACL2 to delay [force]d hypotheses to the next
forcing round, rather than attacking them immediately. See
[immediate-force-modep]. Or for more basic information, first see
[force] for a discussion of [force]d case splits.
Disable-immediate-force-modep is a macro that [disable]s the
executable counterpart of the function symbol
[immediate-force-modep]. When you want to [disable] this mode in
[hints], use a form such as one of the following (these are
equivalent).
:in-theory (disable (:executable-counterpart immediate-force-modep))
:in-theory (disable (immediate-force-modep))")
(DISABLEDP
(THEORIES)
"Determine whether a given name or rune is disabled
Examples:
:disabledp foo ; returns a list of all disabled runes whose base
; symbol is foo (see [rune])
(disabledp 'foo) ; same as above (i.e., :disabledp foo)
:disabledp (:rewrite bar . 1) ; returns t if the indicated rune is
; disabled, else nil
(disabledp (:rewrite bar . 1)); same as immediately above
(disabledp '(:definition binary-append))
; returns t if the indicated definition is disabled, else nil
(disabledp '(:d append))
; same as above
Also see [pr], which gives much more information about the rules
associated with a given event.
Disabledp takes one argument, which is a symbol, a [rune], or a runic
abbreviation such as (:d append) (see [theories]). In the former
case it returns the list of disabled runes associated with that
name, in the sense that the rune's ``base symbol'' is that name
(see [rune]) or, if the event named is a [defmacro] event, then the
list of disabled runes associated with the function corresponding
to that macro name, if any (see [macro-aliases-table]). In the
other cases, where the argument is a [rune] or a runic abbreviation
for a rune, disabledp returns t if the rune is disabled, and nil
otherwise.
Remark for users of the [break-rewrite] utility. Inside the :[brr]
loop, the computation performed by disabledp takes place with
respect to the state of the proof that is currently underway,
rather than the global state. For example, if you break while the
prover is working on Subgoal 3, and the [hints] supplied for the
proof specify (\"Subgoal 3\" :in-theory (disable foo)), then disabled
will return the runes associated with foo, regardless of whether or
not those runes are disabled globally.")
(DISASSEMBLE$
(COMPILATION DEBUGGING)
"Disassemble a function
The macro disassemble$ provides a convenient interface to the
underlying disassemble utility of the host Common Lisp
implementation, which prints assembly code for a given function
symbol at the terminal. If the argument is instead a macro alias
for a function symbol (see [macro-aliases-table]), then it prints
assembly code for that function symbol instead.
Disassemble$ works by including the community book
books/misc/disassemble.lisp, which defines the supporting function
disassemble$-fn, and then by calling that function. Note that the
arguments to disassemble$ are evaluated. Also note that
disassemble$ is intended as a top-level utility for the ACL2 loop,
not to be called in code; for such a purpose, include the above
book and call disassemble$-fn directly.
Example Forms:
(disassemble$ 'foo)
(disassemble$ 'foo :recompile t)
General Forms:
(disassemble$ form)
(disassemble$ form :recompile flg)
where form evaluates to a function symbol or a macro alias for a
function symbol and flg evaluates to any value. If flg is nil, then
the existing definition of that function symbol is disassembled.
But if flg is supplied and has a value other than nil or :default,
and if that function symbol is defined in the ACL2 loop (not merely
in raw Lisp; for example, see [set-raw-mode]), then the disassembly
will be based on a recompilation of that ACL2 definition. Normally
this recompilation is not necessary, but for some host Lisps, it
may be useful; in particular, for CCL the above book arranges that
source code information is saved, so that the output is annotated
with such information. When recompilation takes place, the previous
definition is restored after disassembly is complete. Finally, if
flg is omitted or has the value :default --- i.e., in the default
case --- then recompilation may take place or not, depending on the
host Lisp. The values of (@ host-lisp) for which recompilation
takes place by default may be found by looking at the above book,
or by including it and evaluating the constant
*host-lisps-that-recompile-by-default*. As of this writing, CCL is
the only such Lisp (because that is the one for which we can obtain
source annotation in the output by recompiling).")
(DIVE-INTO-MACROS-TABLE
(PROOF-CHECKER ACL2-PC::DV)
"Right-associated function information for the [proof-checker]
Examples:
ACL2 !>(dive-into-macros-table (w state))
((CAT . EXPAND-ADDRESS-CAT)
(LXOR . EXPAND-ADDRESS-LXOR)
This table associates macro names with functions used by the
[proof-checker]'s DV and numeric diving commands (e.g., 3) in order
to dive properly into subterms. See [proof-checker], in particular
the documentation for DV.
This table can be extended easily. See [add-dive-into-macro] and also
see [remove-dive-into-macro].
The symbol associated with a macro should be a function symbol taking
four arguments, in this order:
* car-addr
the first number in the list given to the [proof-checker]'s DV
command
* raw-term
the untranslated term into which we will dive
* term
the translated term into which we will dive
* wrld
the current ACL2 logical [world]
The function will normally return a list of positive integers,
representing the (one-based) address for diving into term that
corresponds to the single-address dive into raw-term by
car-address. However, it can return (cons str alist), where str is
a string suitable for [fmt] and args is the corresponding alist for
[fmt].
Referring to the example above, expand-address-cat would be such a
function, which will be called on raw-term values that are calls of
cat. See the community book books/misc/rtl-untranslate.lisp for the
definition of such a function.
See [table] for a general discussion of tables.
Subtopics
[Add-dive-into-macro]
Associate [proof-checker] diving function with macro name
[Remove-dive-into-macro]
Removes association of [proof-checker] diving function with macro
name")
(DMR
(DEBUGGING BREAK-REWRITE ACCUMULATED-PERSISTENCE)
"Dynamically monitor rewrites and other prover activity
In addition to utilities that allow you to set breakpoints or print
rewriting information to the screen --- see [break-rewrite] ---
ACL2 provides a utility for watching the activity of the rewriter
and some other proof processes, in real time. This utility is
called ``dmr'', which is an acronym for ``dynamically monitor
rewrites''. The utility comes in two parts: an ACL2 component that
frequently updates a file (the ``dmr file'') containing the
relevant information, and an Emacs component that frequently
updates an Emacs buffer (the ``dmr buffer'') with the contents of
that file. Other editors could, in principle, be programmed to
display that file; anyone developing such a capability is invited
to contribute it to the ACL2 community.
The dmr utility can be extremely helpful for expensive proofs,
especially when ACL2 is not providing any output to the terminal.
The [break-rewrite] and [accumulated-persistence] utilities may be
a bit easier to use, so you might want to try those first. But the
dmr utility can be a very helpful debugging aide, as it can
visually give you a sense of where ACL2 is spending its time.
The Emacs portion of this utility is already loaded if you load the
distributed Emacs file emacs/emacs-acl2.el. Otherwise, invoke the
following Emacs command, say by typing Control-X Control-E after
the right parenthesis, where DIR is the directory of your ACL2
distribution.
(load \"<DIR>/emacs/monitor.el\") ; absolute pathnames might work best
You only need to do that once. Then each time you want to observe the
rewriter in action, invoke the following to see it displayed in a
buffer, which we call the ``dmr buffer'':
Control-t 1
But first you will need to enable monitoring at the ACL2 level:
(dmr-start)
Monitoring has some cost. So if you have started it, then at some
point you may want to turn it off when not using it. Any time the
dmr buffer (generally called \"acl2-dmr-<user_name>\") is not
visible, Emacs monitoring is turned off. You can also turn off
Emacs monitoring explicitly, with:
Control-t 2
At the ACL2 level you can disable monitoring as follows:
(dmr-stop)
Interpreting the dmr buffer display.
We explain the dmr buffer display by way of the following example. It
is a snapshot of a dmr buffer taken from one of the community
books,
books/workshops/2004/legato/support/proof-by-generalization-mult.lisp.
0. (DEFTHM . WP-ZCOEF-G-MULTIPLIES)
1. SIMPLIFY-CLAUSE
2. Rewriting (to simplify) the atom of literal 18; argument(s) 1
4. Rewriting (to simplify) the expansion; argument(s) 3|2
7. Applying (:DEFINITION WP-ZCOEF-G)
* 8. Rewriting (to simplify) the rewritten body; argument(s) 2|1|2|2
* 13. Applying (:REWRITE MOD-ZERO . 2)
* 14. Rewriting (to establish) the atom of hypothesis 4
* 15. Applying (:META META-INTEGERP-CORRECT)
Each line indicates an ACL2 activity that leads to the activity shown
on the line just below it. Moreover, lines are sometimes collapsed
to make the display more compact. Consider for example the first
few lines. Above, we are proving a theorem named
WP-ZCOEF-G-MULTIPLIES. Lines 1 and 2 show the clause simplification
process invokes the rewriter on the 18th literal. (Recall that a
clause is a disjunction of literals; for example the clause {(NOT
A), (NOT B), C} would be displayed as (IMPLIES (AND A B) C).) This
18th literal mentioned on line 2 is a function call (f arg1 ...),
and ``argument(s) 1'' indicates that the rewriter, which works
inside-out, is considering the first argument (``arg1''). Thus the
display could instead have shown the following.
2. Rewriting (to simplify) the atom of literal 18
3. Rewriting (to simplify) the first argument
4. Rewriting (to simplify) the expansion; argument(s) 3|2
But it saved space to combine lines 2 and 3. Line 4 suggests that the
above arg1 is a function call that has been opened up because of an
:expand hint or, perhaps, an expansion directed explicitly by the
prover (as can happen during induction). The annotation
``argument(s) 3|2'' then indicates that the rewriter is diving into
the third argument of the expansion, and then into the second
argument of that. Let us call the result term7 (since it is the one
to be considered on line 7).
Now consider the next two lines:
7. Applying (:DEFINITION WP-ZCOEF-G)
* 8. Rewriting (to simplify) the rewritten body; argument(s) 2|1|2|2
Line 7 is saying that term7 (defined above) is modified by applying
the definition of WP-ZCOEF-G to it. Line 8 then says that the body
of this definition has been rewritten (with its formals bound to
the actuals from term7) and the rewriter is diving into the
subterms of that rewritten body, as indicated. Notice also that
line 8 is the first line marked with an asterisk (``*'') in the
margin. This line is the first that is different from what was
shown the previous time the display was updated (about 1/10 second
earlier, by default). When a line is marked with an asterisk, so
are all the lines below it; so the lines without an asterisk are
those that have been stable since the last display. In this example
we may see line 7 marked without an asterisk for a while, which
suggests that the rule (:DEFINITION WP-ZCOEF-G) is expensive. (Also
see [accumulated-persistence].) In general, a line that persists
for awhile without a leading asterisk can suggest why the proof is
taking a long time.
Finally, note the indentation of line 14 relative to line 13. Extra
indentation occurs when an attempt is being made to relieve a
hypothesis (i.e., rewrite it to t). In particular, rewrites that
will be incorporated directly into a (top-level) literal are all
indented just two spaces, starting with the first rewrite directly
under a process such as SIMPLIFY-CLAUSE (shown line 1 above). If
the indentation is at least the value of raw Lisp variable
*dmr-indent-max* (by default, 20), then the indentation is
restricted to that column, but ACL2 prints {n} where n is the
column that would have been used for indentation if there were no
maximum.
You can move the cursor around in the dmr buffer even while it is
being updated. But emacs will attempt to keep the cursor no later
than the first asterisk (``*'') in the margin. Thus, you can move
the cursor around in the stable part of the display, and emacs will
keep the cursor in that stable part.
WARNING: Things could go terribly wrong if the same user runs two
different ACL2 sessions with dmr active, because the same file will
be written by two different ACL2 processes.
WARNING: For dmr to work, emacs and ACL2 need to be run on the same
machine because the file used to communicate between ACL2 and emacs
is under /tmp. Except, you can probably hack around that
restriction by changing *dmr-file-name* in ACL2 (in raw Lisp) and
correspondingly in Emacs file monitor.el.
More generally, advanced users are welcome to search for the string
User-settable dmr variables
in ACL2 files interface-raw.lisp and emacs/monitor.el in order to
customize their dmr environments.
In order to update the dmr file with the latest stack information,
interrupt ACL2 and then evaluate: (dmr-flush). In order to support
resumption of the interrupted proof (assuming your host Common Lisp
supports resumption), evaluation of (dmr-start) will automatically
enable the debugger if it is not already enabled and not fully
disabled with value :never (see [set-debugger-enable]). If such
automatic enabling takes place, then (dmr-stop) will restore the
old setting of the debugger unless, after (dmr-start) enables the
debugger but before (dmr-stop) is called, you call
[set-debugger-enable] (or more precisely: function
set-debugger-enable-fn is called).
Note for users of the experimental extension ACL2(p) (see
[parallelism]): when waterfall-parallelism has been set to a
non-nil value (see [set-waterfall-parallelism]), statistics about
parallel execution are printed instead of the usual information.")
(DO-NOT
(HINTS)
"Instruct the theorem prover not to do certain things.
See [hints] for documentation about the :do-not keyword for prover
:hints.
See [do-not-hint] for documentation about the do-not macro that
controls a mechanism for automatically suggesting :do-not and
:do-not-induct hints.")
(DO-NOT-INDUCT (POINTERS)
"See [hints] for keyword :do-not-induct.")
(DOC
(DOCUMENTATION)
"[Documentation] at the terminal
The :doc command may be used at the ACL2 prompt to access the ACL2
system [documentation]. Usually it may also access documentation
defined in books. However, most users will probably access the ACL2
documentation in other ways; see [documentation]. In particular,
consider using the {ACL2+Books Manual |
http://www.cs.utexas.edu/users/moore/acl2/v7-2/combined-manual/index.html},
for topics documented in the ACL2 community [books] or in the ACL2
system (where the latter are rearranged).
Alternatively, consider using the ACL2-doc Emacs browser; see
[ACL2-doc].
Examples:
ACL2 !>:doc DEFTHM ; print documentation of DEFTHM
ACL2 !>:doc logical-name ; print documentation of LOGICAL-NAME
General Form:
ACL2>:doc name")
(DOCUMENTATION
(ACL2)
"Information about options for downloading and viewing the ACL2
documentation, contributing documentation, and the available tools
for documenting your own books.
Available Documentation
If you are new to ACL2, see the [ACL2-tutorial] for introductory
tours, tutorials, and information about textbooks about ACL2. The
{ACL2 home page | http://www.cs.utexas.edu/users/moore/acl2} also
provides many links to academic publications about ACL2, including
the ACL2 Workshop series.
Beyond these resources, there is a vast ACL2+Books Manual with
reference material covering the ACL2 system itself and also many
[community-books]. There are a few ways to access the manual:
* The online version (recommended). If you expect to have an internet
connection while using the documentation, you may prefer to use
the online version of the {ACL2+Books Manual |
http://www.cs.utexas.edu/users/moore/acl2/v7-2/combined-manual/index.html}.
* A local version. If you sometimes work without an internet
connection, you can {download | download/} a local copy of any
web-based XDOC manual using the \"down arrow\" icon at the top of
the page. You can alternately build your own copy of the
manual; see Building the manual in [books-certification].
* The ACL2-Doc Emacs version. If you would like to view the
documentation using Emacs instead of a web browser, there is a
feature-rich Emacs-based documentation browser provided by the
ACL2 system. See [ACL2-doc] for details.
While you are using ACL2, you can get documentation at the terminal
with the :[doc] command, e.g., by typing :doc rewrite. This is
often handy, but note that it won't show you any documentation for
books that you haven't loaded yet!
Separately from the ACL2+Books Manual, the ACL2 User's Manual is
distributed with ACL2. This is much like the ACL2+Books Manual but
it does not include documentation from the books. A web-based copy
is included with the ACL2 distribution in directory doc/manual/,
and you can easily get to it by opening file doc/home-page.html in
your browser.
Documenting Your Books
Documentation is written using [xdoc], and may be found in the
[community-books]. Everyone is welcome to edit and contribute to
that documentation. In particular, you are welcome to edit the book
that contains ACL2 system documentation,
books/system/doc/acl2-doc.lisp. (Please do not edit ACL2 source
file doc.lisp, which is generated from that book. More generaly,
edit only files under the books/ directory.)
You can also use XDOC to document your own books and to build custom
manuals for your organization.
Other Resources
If you want documentation on an ACL2 function or macro that is not
documented, there are still several alternatives.
ACL2 !>:args fn
will print the arguments and some other relevant information about
the named function or macro. This information is all gleaned from
the definition and hence this is a definitive way to determine if
fn is defined as a function or macro.
You might also want to type:
ACL2 !>:pc fn
which will print the [command] that introduced fn. You should see
[command-descriptor] for details on the kinds of input you can give
the :[pc] command.
Subtopics
[ACL2-doc]
A custom Emacs browser for reading ACL2 [documentation]
[Args]
args, [guard], type, [constraint], etc., of a function symbol
[Broken-link]
Placeholder for link to documentation that resides in the community
books
[Doc]
[Documentation] at the terminal
[Documentation-copyright]
Copyright and authorship of documentation
[Finding-documentation]
Searching the documentation
[Pointers]
Links pointing to relevant documentation topics")
(DOCUMENTATION-COPYRIGHT
(COPYRIGHT DOCUMENTATION)
"Copyright and authorship of documentation
There are two manuals associated with ACL2: the ACL2 User's Manual
and the ACL2+Books Manual. See [documentation]. The former is
distributed with ACL2, you can reach many links into it from the
ACL2 home page. The latter may be preferred for routine browsing,
since it extends the ACL2 User's Manual with documentation obtained
from the [community-books].
The ACL2 User's Manual is copyrighted under the terms of the LICENSE
file distributed with ACL2. Its original authors are the ACL2
authors, but it is now defined in an ACL2 community book,
books/system/doc/acl2-doc.lisp, so that members of the ACL2
community may contribute to it.
The ACL2+Books Manual is a mechanically generated mashup derived from
both the ACL2 User's Manual and the [community-books]. The
ACL2+Books Manual thus has contributions from many authors. At the
top of each topic, in a line under the topic name, you will
generally find either ``ACL2 Sources'' or the name of a Community
Book. In the former case, the text is from the ACL2 User's Manual
and is authored, copyrighted, and licensed as per the ACL2
[copyright]. When a book is named, the content was extracted from
that book which may be inspected for authorship, copyright, and
license terms.
There are two standard tools for browsing these manuals, other than
using the :[doc] command at the terminal.
* The ACL2 [Xdoc] Fancy Viewer. This tool, written by Jared Davis, is
included with the web-based version of each manual. Information
on copyright and licensing are provided in {its LICENSE file |
LICENSE}.
* The [ACL2-doc] Emacs browser. This tool, authored by Matt Kaufmann
and J Strother Moore, is distributed with ACL2 and is licensed
under the terms of the LICENSE file distributed with ACL2.")
(DOUBLE-REWRITE
(REWRITE)
"Cause a term to be rewritten twice
Logically, double-rewrite is the [identity] function: (double-rewrite
x) is equal to x. However, the ACL2 rewriter treats calls of
double-rewrite in the following special manner. When it encounters
a term (double-rewrite u), it first rewrites u in the current
context, and then the rewriter rewrites the result.
Such double-rewriting is rarely necessary, but it can be useful when
rewriting under non-trivial equivalence relations (see
[equivalence]). The following example will illustrate the issue.
; Define an equivalence relation.
(defun my-equiv (x y)
(equal x y))
(defequiv my-equiv)
; Define a unary function whose argument is preserved by my-equiv.
(defun foo (x)
(declare (ignore x))
t)
(defcong my-equiv equal (foo x) 1)
; Define some other unary functions.
(defun g (x) x)
(defun h1 (x) x)
(defun h2 (x) x)
; Prove some lemmas and then disable the functions above.
(defthm lemma-1
(my-equiv (h1 x) (h2 x)))
(defthm lemma-2
(foo (h2 x)))
(defthm lemma-3
(implies (foo x)
(equal (g x) x)))
(in-theory (union-theories (theory 'minimal-theory)
'(lemma-1 lemma-2 lemma-3
my-equiv-implies-equal-foo-1)))
; Attempt to prove a simple theorem that follows ``obviously'' from the
; events above.
(thm (equal (g (h1 a)) (h1 a)))
We might expect the proof of this final thm to succeed by the
following reasoning. It is immediate from lemma-3 provided we can
establish (foo (h1 a)). By the defcong event above, we know that
(foo (h1 a)) equals (foo (h2 a)) provided (my-equiv (h1 a) (h2 a));
but this is immediate from lemma-1. And finally, (foo (h2 a)) is
true by lemma-2.
Unfortunately, the proof fails. But fortunately, ACL2 gives the
following useful warning when lemma-3 is submitted:
ACL2 Warning [Double-rewrite] in ( DEFTHM LEMMA-3 ...): In the :REWRITE
rule generated from LEMMA-3, equivalence relation MY-EQUIV is maintained
at one problematic occurrence of variable X in hypothesis (FOO X),
but not at any binding occurrence of X. Consider replacing that occurrence
of X in this hypothesis with (DOUBLE-REWRITE X). See :doc double-
rewrite for more information on this issue.
We can follow the warning's advice by changing lemma-3 to the
following.
(defthm lemma-3
(implies (foo (double-rewrite x))
(equal (g x) x)))
With this change, the proof succeeds for the final thm above.
In practice, it should suffice for users to follow the advice given
in the ``Double-rewrite'' warnings, by adding calls of
double-rewrite around certain variable occurrences. But this can
cause inefficiency in large proof efforts. For that reason, and for
completeness, it seems prudent to explain more carefully what is
going on; and that is what we do for the remainder of this
[documentation] topic. Optionally, also see the paper ``Double
Rewriting for Equivalential Reasoning in ACL2'' by Matt Kaufmann
and J Strother Moore, in the proceedings of the 2006 ACL2 Workshop
(paper is published in ACM Digital Library,
{http://portal.acm.org/toc.cfm?id=1217975 |
http://portal.acm.org/toc.cfm?id=1217975}).
Suggesting congruence rules.
Sometimes the best way to respond to a ``Double-rewrite'' warning may
be to prove a congruence rule. Consider for example this rule.
(defthm insert-sort-is-id
(perm (insert-sort x) x))
Assuming that perm has been identified as an [equivalence] relation
(see [defequiv]), we will get the following warning.
ACL2 Warning [Double-rewrite] in ( DEFTHM INSERT-SORT-IS-ID ...):
In a :REWRITE rule generated from INSERT-SORT-IS-ID, equivalence relation
PERM is maintained at one problematic occurrence of variable X in the
right-hand side, but not at any binding occurrence of X. Consider
replacing that occurrence of X in the right-hand side with
(DOUBLE-REWRITE X). See :doc double-rewrite for more information on
this issue.
The problem is that the second occurrence of x (the right-hand side
of the rule insert-sort-is-id) is in a context where perm is to be
maintained, yet in this example, the argument x of insert-sort on
the left-hand side of that rule is in a context where perm will not
be maintained. This can lead one to consider the possibility that
perm could be maintained in that left-hand side occurrence of x,
and if so, to prove the following congruence rule.
(defcong perm perm (insert-sort x) 1)
This will eliminate the above warning for insert-sort-is-id. More
important, this [defcong] event would probably be useful, since it
would allow rewrite rules with equivalence relation perm to operate
on the first argument of any call of insert-sort whose context
calls for maintaining perm.
Details on double-rewrite.
The reader who wants these details may first wish to see
[equivalence] for relevant review.
The ACL2 rewriter takes a number of contextual arguments, including
the generated equivalence relation being maintained (see
[congruence]) and an association list that maps variables to terms.
We call the latter alist the unify-subst because it is produced by
unifying (actually matching) a pattern against a current term; let
us explain this point by returning to the example above. Consider
what happens when the rewriter is given the top-level goal of the
thm above.
(equal (g (h1 a)) (h1 a))
This rewrite is performed with the empty alist (unify-subst), and is
begun by rewriting the first argument (in that same empty
unify-subst):
(g (h1 a))
Note that the only equivalence relation being maintained at this
point is equal. Now, the rewriter notices that the left-hand side
of lemma-3, which is (g x), matches (g (h1 a)). The rewriter thus
creates a unify-subst binding x to (h1 a): ((x . (h1 a))). It now
attempts to rewrite the hypothesis of lemma-3 to t under this
unify-subst.
Consider what happens now if the hypothesis of lemma-3 is (foo x). To
rewrite this hypothesis under a unify-subst of ((x . (h1 a))), it
will first rewrite x under this unify-subst. The key observation
here is that this rewrite takes place simply by returning the value
of x in the unify-subst, namely (h1 a). No further rewriting is
done! The efficiency of the ACL2 rewriter depends on such caching
of previous rewriting results.
But suppose that, instead, the hypothesis of lemma-3 is (foo
(double-rewrite x)). As before, the rewriter dives to the first
argument of this call of foo. But this time the rewriter sees the
call (double-rewrite x), which it handles as follows. First, x is
rewritten as before, yielding (h1 a). But now, because of the call
of double-rewrite, the rewriter takes (h1 a) and rewrites it under
the empty unify-subst. What's more, because of the defcong event
above, this rewrite takes place in a context where it suffices to
maintain the equivalence relation my-equiv. This allows for the
application of lemma-1, hence (h1 a) is rewritten (under
unify-subst = nil) to (h2 a). Popping back up, the rewriter will
now rewrite the call of foo to t using lemma-2.
The example above explains how the rewriter treats calls of
double-rewrite, but it may leave the unfortunate impression that
the user needs to consider each :[rewrite] or :[linear] rule
carefully, just in case a call of double-rewrite may be
appropriate. Fortunately, ACL2 provides a ``[Double-rewrite]''
warning to inform the user of just this sort of situation. If you
don't see this warning when you submit a (:[rewrite] or :[linear])
rule, then the issue described here shouldn't come up for that
rule. Such warnings may appear for hypotheses or right-hand side of
a :[rewrite] rule, and for hypotheses or full conclusion (as
opposed to just the trigger term) of a :[linear] rule.
If you do see a ``[Double-rewrite]'' warning, then should you add the
indicated call(s) of double-rewrite? At the time of writing this
[documentation], the answer is not clear. Early experiments with
double rewriting suggested that it may be too expensive to call
double-rewrite in every instance where a warning indicates that
there could be an advantage to doing so. And at the time of this
writing, the ACL2 regression suite has about 1900 such warnings
(but note that books were developed before double-rewrite or the
``[Double-rewrite]'' warning were implemented), which suggests that
one can often do fine just ignoring such warnings. However, it
seems advisable to go ahead and add the calls of double-rewrite
indicated by the warnings unless you run across efficiency problems
caused by doing so. Of course, if you decide to ignore all such
warnings you can execute the event:
([set-inhibit-warnings] \"Double-rewrite\").
Finally, we note that it is generally not necessary to call
double-rewrite in order to get its effect in the following case,
where the discussion above might have led one to consider a call of
double-rewrite: a hypothesis is a variable, or more generally, we
are considering a variable occurrence that is a branch of the
top-level IF structure of a hypothesis. The automatic handling of
this case, by a form of double rewriting, was instituted in ACL2
Version_2.9 and remains in place with the introduction of
double-rewrite. Here is a simple illustrative example. Notice that
foo-holds applies to prove the final [thm] below, even without a
call of double-rewrite in the hypothesis of foo-holds, and that
there is no ``[Double-rewrite]'' warning when submitting foo-holds.
(encapsulate
(((foo *) => *)
((bar *) => *))
(local (defun foo (x) (declare (ignore x)) t))
(local (defun bar (x) (declare (ignore x)) t))
(defthm foo-holds
(implies x
(equal (foo x) t)))
(defthm bar-holds-propositionally
(iff (bar x) t)))
(thm (foo (bar y)))")
(DYNAMICALLY-MONITOR-REWRITES (POINTERS)
"See [dmr].")
(E/D
(THEORIES THEORY-FUNCTIONS)
"Enable/disable rules
The macro e/d creates theory expressions for use in [in-theory] hints
and events. It provides a convenient way to [enable] and [disable]
simultaneously, without having to write arcane theory expressions.
For related utilities, see [enable] and see [disable].
Examples:
(e/d (lemma1 lemma2)) ; equivalent to (enable lemma1 lemma2)
(e/d () (lemma)) ; equivalent to (disable lemma)
(e/d (lemma1) (lemma2 lemma3)) ; Enable lemma1 then disable lemma2, lemma3.
(e/d () (lemma1) (lemma2)) ; Disable lemma1 then enable lemma2.
General Form:
(e/d enables-0 disables-0 ... enables-n disables-n)
where each enables-i and disables-i is a list of runic designators;
see [theories], see [enable], and see [disable].
The e/d macro takes any number of lists suitable for the [enable] and
[disable] macros, and creates a theory that is equal to
(current-theory :here) after executing the following commands.
(in-theory (enable . enables-0))
(in-theory (disable . disables-0))
...
(in-theory (enable . enables-n))
(in-theory (disable . disables-n))")
(EARLY-TERMINATION
(PARALLEL-PROGRAMMING)
"Early termination for [pand] and [por].
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
The evaluation of (and expr1 expr2) returns nil if expr1 evaluates to
nil, avoiding the evaluation of expr2. More generally, the
evaluation of (and expr1 expr2 ... exprk) terminates with a return
value of nil as soon as any expri evaluates to nil --- no exprj is
evaluated in this case for j > i. This so-called ``lazy
evaluation'' of [and] terms can thus save some computation; roughly
speaking, the smaller the i, the more computation is saved.
If the above call of [and] is replaced by its parallel version,
[pand], then there can be even more opportunity for skipping work.
The arguments to [pand] can be evaluated in parallel, in which case
the first such evaluation that returns with a value of nil, if any,
causes the remaining such evaluations to abort.
Consider the following functions that compute whether a tree is valid
(see [granularity] for a discussion of the granularity form).
(defun valid-tip (x)
(declare (xargs :guard t))
(or (eq x 'A)
(eq x 'T)
(eq x 'C)
(eq x 'G)))
(defun pvalid-tree (x depth)
(declare (xargs :guard (natp depth)))
(if (atom x)
(valid-tip x)
(pand (declare (granularity (< depth 10)))
(pvalid-tree (car x) (1+ depth))
(pvalid-tree (cdr x) (1+ depth)))))
We would like to stop execution as soon as any tip is found to be
invalid. So, when computing the conjunction of terms by using
[pand], once one of those terms evaluates to nil, the computations
for the other terms are aborted and the [pand] call returns nil. By
using [pand], we can in principle attain a speedup factor greater
than the number of available cores.
The concept of early termination also applies to [por], except that
early termination occurs when an argument evaluates to non-nil.")
(EC-CALL
(GUARD ACL2-BUILT-INS)
"Execute a call in the ACL2 logic instead of raw Lisp
The name ``ec-call'' represents ``executable-counterpart call.'' This
utility is intended for users who are familiar with guards. See
[guard] for a general discussion of guards.
Logically, ec-call behaves like the identity macro; during proofs,
(ec-call TERM) is typically replaced quickly by TERM during a proof
attempt. However, ec-call causes function calls to be evaluated in
the ACL2 logic rather than raw Lisp, as explained below.
General Form:
(ec-call (fn term1 ... termk))
where fn is a known function symbol other than those in the list that
is the value of the constant *ec-call-bad-ops*. (But see the Final
Note below for an exception pertaining to inlining.) In particular,
fn is not a macro. Semantically, (ec-call (fn term1 ... termk))
equals (fn term1 ... termk). However, this use of ec-call has two
effects.
(1) [Guard] verification generates no proof obligations from the
guard of fn for this call. Indeed, guards need not have been
verified for fn.
(2) During evaluation, after the arguments of fn are evaluated as
usual, the executable counterpart of fn is called, rather than
fn as defined in raw Lisp. That is, the call of fn is made on
its evaluated arguments as though this call is being made in
the ACL2 top-level loop, rather than in raw Lisp. In
particular, the [guard] of fn is checked, at least by default
(see [set-guard-checking]).
Note that in the term (ec-call (fn term1 ... termk)), only the
indicated call of fn is made in the logic; each termi is evaluated
in the normal manner. If you want an entire term evaluated in the
logic, wrap ec-call around each function call in the term (other
than calls of if and ec-call).
Technical Remark (probably best ignored). During evaluation of a call
of [defconst] or [defpkg] in raw Lisp, a form (ec-call (fn term1
... termk)) is treated as (fn term1 ... termk), that is, without
calling the executable counterpart of fn. This situation occurs
when loading a compiled file (or expansion file) on behalf of an
[include-book] event. The reason is technical: executable
counterparts are defined below a book's events in the book's
compiled file. End of Technical Remark.
Here is a small example. We define foo recursively but with guard
verification inhibited on the recursive call, which is to be
evaluated in the ACL2 logic.
ACL2 !>(defun foo (x y)
(declare (xargs :guard (consp y)))
(if (consp x)
(cons (car x) (ec-call (foo (cdr x) (cdr y))))
(car y)))
The admission of FOO is trivial, using the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT X). We could deduce no constraints on the type of FOO.
Computing the guard conjecture for FOO....
The guard conjecture for FOO is trivial to prove. FOO is compliant
with Common Lisp.
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO
ACL2 !>(foo '(2 3 4 5) '(6 7))
ACL2 Error in TOP-LEVEL: The guard for the function call (FOO X Y),
which is (CONSP Y), is violated by the arguments in the call
(FOO '(4 5) NIL). To debug see :DOC print-gv, see :DOC trace, and
see :DOC wet. See :DOC set-guard-checking for information about suppressing
this check with (set-guard-checking :none), as recommended for new
users.
ACL2 !>
The error above arises because eventually, foo recurs down to a value
of parameter y that violates the guard. This is clear from tracing
(see [trace$] and see [trace]). Each call of the executable
counterpart of foo (the so-called ``*1*'' function for foo) checks
the guard and then invokes the raw Lisp version of foo. The raw
Lisp version calls the executable counterpart on the recursive
call. When the guard check fails we get a violation.
ACL2 !>(trace$ foo)
((FOO))
ACL2 !>(foo '(2 3 4 5) '(6 7))
1> (ACL2_*1*_ACL2::FOO (2 3 4 5) (6 7))
2> (FOO (2 3 4 5) (6 7))
3> (ACL2_*1*_ACL2::FOO (3 4 5) (7))
4> (FOO (3 4 5) (7))
5> (ACL2_*1*_ACL2::FOO (4 5) NIL)
ACL2 Error in TOP-LEVEL: The guard for the function call (FOO X Y),
which is (CONSP Y), is violated by the arguments in the call
(FOO '(4 5) NIL). To debug see :DOC print-gv, see :DOC trace, and
see :DOC wet. See :DOC set-guard-checking for information about suppressing
this check with (set-guard-checking :none), as recommended for new
users.
ACL2 !>
If we turn off guard errors then we can see the trace as above, but
where we avoid calling the raw Lisp function when the guard fails
to hold.
ACL2 !>:set-guard-checking nil
Masking guard violations but still checking guards except for self-
recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING
:NONE. See :DOC set-guard-checking.
ACL2 >(foo '(2 3 4 5) '(6 7))
1> (ACL2_*1*_ACL2::FOO (2 3 4 5) (6 7))
2> (FOO (2 3 4 5) (6 7))
3> (ACL2_*1*_ACL2::FOO (3 4 5) (7))
4> (FOO (3 4 5) (7))
5> (ACL2_*1*_ACL2::FOO (4 5) NIL)
6> (ACL2_*1*_ACL2::FOO (5) NIL)
7> (ACL2_*1*_ACL2::FOO NIL NIL)
<7 (ACL2_*1*_ACL2::FOO NIL)
<6 (ACL2_*1*_ACL2::FOO (5))
<5 (ACL2_*1*_ACL2::FOO (4 5))
<4 (FOO (3 4 5))
<3 (ACL2_*1*_ACL2::FOO (3 4 5))
<2 (FOO (2 3 4 5))
<1 (ACL2_*1*_ACL2::FOO (2 3 4 5))
(2 3 4 5)
ACL2 >
Final note: although in general, the form (ec-call (fn term1 ...
termk)) is only legal if fn is a function symbol, such a form is
also legal if fn is introduced with [defun-inline], or with
[define] using keyword argument :inline t. In those cases, fn is a
macro whose calls expand to corresponding calls of fn$INLINE, the
symbol in the same package as fn but with the string \"$INLINE\"
added as a suffix to the [symbol-name] of fn. We do not however
extend this exception to macros in general, even when
[add-macro-fn] has been invoked. Consider the following example.
(encapsulate
()
(defun foo () nil)
(defun bar () t)
(defmacro mac () nil)
(add-macro-alias mac foo)
(local (add-macro-alias mac bar))
(defun h () (ec-call (mac)))
(defthm bad (h)))
Consider what would happen if this were legal, where (ec-call (mac))
used the macro-alias, foo, for mac. Then in the first pass of the
[encapsulate] form above, the final [defthm] event would prove,
since (ec-call (mac)) is treated as (ec-call (bar)). But on the
second pass, ACL2 would store bad as a theorem even though (h)
would evaluate to nil, since the macro-alias of mac is foo on the
second pass.")
(EIGHTH
(NTH ACL2-BUILT-INS)
"Eighth member of the list
See any Common Lisp documentation for details.")
(ELIM
(RULE-CLASSES)
"Make a destructor elimination rule
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
The following example of an :elim rule is an important one, and is
built into ACL2.
(defaxiom car-cdr-elim
(implies (consp x)
(equal (cons (car x) (cdr x)) x))
:rule-classes :elim)
The class of :elim rules is fundamentally quite different from the
more common class of :[rewrite] rules. Briefly put, a :rewrite rule
replaces instances of its left-hand side with corresponding
instances of its right-hand side. But an :elim rule, on the other
hand, has the effect of generalizing so-called ``destructor''
function applications to variables. In essence, applicability of a
:rewrite rule is based on matching its left-hand side, while
applicability of an :elim rule is based on the presence of at least
one destructor term.
For example, a conjecture about (car x) and (cdr x) can be replaced
by a conjecture about new variables x1 and x2, as shown in the
following example. (Run the command :mini-proveall and search for
CAR-CDR-ELIM to see the full proof containing this excerpt.)
Subgoal *1/1'
(IMPLIES (AND (CONSP X)
(TRUE-LISTP (REV (CDR X))))
(TRUE-LISTP (APP (REV (CDR X)) (LIST (CAR X))))).
The destructor terms (CAR X) and (CDR X) can be eliminated by using
CAR-CDR-ELIM to replace X by (CONS X1 X2), (CAR X) by X1 and (CDR X)
by X2. This produces the following goal.
Subgoal *1/1''
(IMPLIES (AND (CONSP (CONS X1 X2))
(TRUE-LISTP (REV X2)))
(TRUE-LISTP (APP (REV X2) (LIST X1)))).
This simplifies, using primitive type reasoning, to
Subgoal *1/1'''
(IMPLIES (TRUE-LISTP (REV X2))
(TRUE-LISTP (APP (REV X2) (LIST X1)))).
The resulting conjecture is often simpler and hence more amenable to
proof.
The application of an :elim rule thus replaces a variable by a term
that contains applications of so-called ``destructor'' functions to
that variable. The example above is typical: the variable x is
replaced by the term (cons (car x) (cdr x)), which applies a
so-called ``constructor'' function, [cons], to applications (car x)
and (cdr x) of destructor functions [car] and [cdr] to that same
variable, x. But that is only part of the story. ACL2 then
generalizes the destructor applications (car x) and (cdr x) to new
variables x1 and x2, respectively, and ultimately the result is a
simpler conjecture.
More generally, the application of an :elim rule replaces a variable
by a term containing applications of destructors; there need not be
a clear-cut notion of ``constructor.'' But the situation described
above is typical, and we will focus on it, giving full details when
we introduce the ``General Form'' below.
Notice that the situation can be complicated a bit by a rule's
hypotheses. For example, the replacement specified by the rule
car-cdr-elim (shown near the beginning of this discussion) is only
valid if the variable being replaced is a cons structure. Thus,
when ACL2 applies car-cdr-elim to replace a variable v, it will
split into two cases: one case in which (consp v) is true, in which
v is replaced by (cons (car v) (cdr v)) and then (car v) and (cdr
v) are generalized to new variables; and one case in which (consp
v) is false. In practice, (consp v) is often provable, perhaps even
literally present as a hypotheses; then of course there is no need
to introduce the second case. That is why there is no such second
case in the example above.
You might find :elim rules to be useful whenever you have in mind a
data type that can be built up from its fields with a
``constructor'' function and whose fields can be accessed by
corresponding ``destructor'' functions. So for example, if you have
a ``house'' data structure that represents a house in terms of its
address, price, and color, you might have a rule like the
following.
Example:
(implies (house-p x)
(equal (make-house (address x)
(price x)
(color x))
x))
The application of such a rule is entirely analogous to the
application of the rule car-cdr-elim discussed above. We discuss
such rules and their application more carefully below.
General Form:
(implies hyp (equiv lhs x))
where equiv is a known equivalence relation (see [defequiv]); x is a
variable symbol; and lhs contains one or more terms (called
``destructor terms'') of the form (fn v1 ... vn), where fn is a
function symbol and the vi are distinct variable symbols, v1, ...,
vn include all the variable symbols in the formula, no fn occurs in
lhs in more than one destructor term, and all occurrences of x in
lhs are inside destructor terms.
To use an :elim rule, the theorem prover waits until a conjecture has
been maximally simplified. It then searches for an instance of some
destructor term (fn v1 ... vn) in the conjecture, where the
instance for x is some variable symbol, vi, and every occurrence of
vi outside the destructor terms is in an equiv-hittable position.
If such an instance is found, then the theorem prover instantiates
the :elim formula as indicated by the destructor term matched;
splits the conjecture into two goals, according to whether the
instantiated hypothesis, hyp, holds; and in the case that it does
hold, generalizes all the instantiated destructor terms in the
conjecture to new variables and then replaces vi in the conjecture
by the generalized instantiated lhs. An occurrence of vi is
``equiv-hittable'' if sufficient congruence rules (see [defcong])
have been proved to establish that the propositional value of the
clause is not altered by replacing that occurrence of vi by some
equiv-equivalent term.
If an :elim rule is not applied when you think it should have been,
and the rule uses an equivalence relation, equiv, other than equal,
it is most likely that there is an occurrence of the variable that
is not equiv-hittable. Easy occurrences to overlook are those in
the governing hypotheses. If you see an unjustified occurrence of
the variable, you must prove the appropriate congruence rule to
allow the :elim to fire.
Further examples of how ACL2 :elim rules are used may be found in the
corresponding discussion of ``Elimation of Destructors'' for Nqthm,
in Section 10.4 of A Computational Logic Handbook.")
(EMACS
(ACL2-TUTORIAL)
"Emacs support for ACL2
Many successful ACL2 users run in an shell under the Emacs editor. If
you do so, then you may wish to load the distributed file
emacs/emacs-acl2.el. The file begins with considerable comments
describing what it offers. It is intended to work both with GNU
Emacs and XEmacs.
In particular, the above file provides the ACL2-Doc browser, a
convenient tool for viewing, in Emacs, documentation for both the
ACL2 system and the documented community books. See [ACL2-Doc].
If you are not comfortable with Emacs, you may prefer to use an
Eclipse-based interface; see [ACL2-sedan].")
(EMBEDDED-EVENT-FORM
(EVENTS)
"Forms that may be embedded in other [events]
Examples:
(defun hd (x) (if (consp x) (car x) 0))
(local (defthm lemma23 ...))
(progn (defun fn1 ...)
(local (defun fn2 ...))
...)
General Form:
An embedded event form is a term, x, such that:
* x is a call of an event function other than [defpkg] (see [events]
for a listing of the event functions);
* x is of the form ([local] x1) where x1 is an embedded event form;
* x is of the form ([skip-proofs] x1) where x1 is an embedded event
form;
* x is of the form ([make-event] &), where & is any term whose
expansion is an embedded event (see [make-event]);
* x is of the form ([with-output] ... x1), ([with-prover-step-limit]
... x1 ...), or ([with-prover-time-limit] ... x1), where x1 is
an embedded event form;
* x is a call of [encapsulate], [progn], [progn!], or [include-book];
* x macroexpands to one of the forms above; or
* [intended only for the implementation] x is (RECORD-EXPANSION x1 x2),
where x1 and x2 are embedded event forms.
However, we add the following restrictions for [local] contexts.
* An embedded event form may not set the [ACL2-defaults-table] when in
the context of [local]. Thus for example, the form
(local (table acl2-defaults-table :defun-mode :program))
is not an embedded event form, nor is the form (local (program)),
since the latter sets the [ACL2-defaults-table] implicitly. An
example at the end of the discussion below illustrates why
there is this restriction.
* A call of [defaxiom] is illegal in the context of [local]. Without
this restriction, one could locally assert a strong axiom like
(equal t nil) and then non-locally prove that formula, leaving
you in an ACL2 logical [world] in which it appears that the
formula is actually provable without such an axiom.
* A call of [add-include-book-dir!] or [delete-include-book-dir!] is
illegal in the context of [local]. For an explanation, see
[add-include-book-dir!].
Only embedded event forms are allowed in a book after its initial
[in-package] form. See [books]. However, you may find that
[make-event] allows you to get the effect you want for a form that
is not an embedded event form. For example, you can put the
following into a book, which assigns the value 17 to [state] global
variable x:
(make-event (er-progn (assign x 17)
(value '(value-triple nil)))
:check-expansion t)
When an embedded event is executed while [ld-skip-proofsp] is
'[include-book], those parts of it inside [local] forms are
ignored. Thus,
(progn (defun f1 () 1)
(local (defun f2 () 2))
(defun f3 () 3))
will define f1, f2, and f3 when [ld-skip-proofsp] is nil or t, but
will define only f1 and f3 when [ld-skip-proofsp] is
'[include-book].
Discussion:
[Encapsulate], [progn], and [include-book] place restrictions on the
kinds of forms that may be processed. These restrictions ensure
that the non-local [events] are indeed admissible provided that the
sequence of [local] and non-local [events] is admissible when
proofs are done, i.e., when ld-skip-proofs is nil. But [progn!]
places no such restrictions, hence is potentially dangerous and
should be avoided unless you understand the ramifications; so it is
illegal unless there is an active trust tag (see [defttag]).
[Local] permits the hiding of an event or group of [events] in the
sense that [local] [events] are processed when we are trying to
establish the admissibility of a sequence of [events] embedded in
[encapsulate] forms or in [books], but are ignored when we are
constructing the [world] produced by assuming that sequence. Thus,
for example, a particularly ugly and inefficient :[rewrite] rule
might be made [local] to an [encapsulate] that ``exports'' a
desirable theorem whose proof requires the ugly lemma.
To see why we can't allow just anything as an embedded event,
consider allowing the form
(if (ld-skip-proofsp state)
(defun foo () 2)
(defun foo () 1))
followed by
(defthm foo-is-1 (equal (foo) 1)).
When we process the [events] with [ld-skip-proofsp] is nil, the
second [defun] is executed and the [defthm] succeeds. But when we
process the [events] with [ld-skip-proofsp] '[include-book], the
second [defun] is executed, so that foo no longer has the same
definition it did when we proved foo-is-1. Thus, an invalid formula
is assumed when we process the [defthm] while skipping proofs.
Thus, the first form above is not a legal embedded event form.
If you encounter a situation where these restrictions seem to prevent
you from doing what you want to do, then you may find make-event to
be helpful. See [make-event].
[Defpkg] is not allowed because it affects how things are read after
it is executed. But all the forms embedded in an event are read
before any are executed. That is,
(encapsulate nil
(defpkg \"MY-PKG\" nil)
(defun foo () 'my-pkg::bar))
makes no sense since my-pkg::bar must have been read before the
[defpkg] for \"MY-PKG\" was executed.
Finally, let us elaborate on the restriction mentioned earlier
related to the [ACL2-defaults-table]. Consider the following form.
(encapsulate
()
(local (program))
(defun foo (x)
(if (equal 0 x)
0
(1+ (foo (- x))))))
See [local-incompatibility] for a discussion of how [encapsulate]
processes event forms. Briefly, on the first pass through the
[events] the definition of foo will be accepted in [defun] mode
:[program], and hence accepted. But on the second pass the form
(local (program)) is skipped because it is marked as [local], and
hence foo is accepted in [defun] mode :[logic]. Yet, no proof has
been performed in order to admit foo, and in fact, it is not hard
to prove a contradiction from this definition!")
(ENABLE
(THEORIES THEORY-FUNCTIONS)
"Adds names to current theory
Example:
(enable fact (fact) associativity-of-app)
General Form:
(enable name1 name2 ... namek)
where each namei is a runic designator; see [theories]. The result is
the theory that contains all the names in the current theory plus
those listed. Note that this is merely a function that returns a
theory. The result is generally a very long list of [rune]s and you
will probably regret printing it.
For related utilities, see [disable] and see [e/d].
The standard way to ``enable'' a fixed set of names, is as follows;
see [hints] and see [in-theory].
:in-theory (enable name1 name2 ... namek) ; in a hint
(in-theory (enable name1 name2 ... namek)) ; as an event
(local ; often desirable, to avoid exporting from the current context
(in-theory (enable name1 name2 ... namek)))
Note that all the names are implicitly quoted. If you wish to enable
a computed list of names, lst, use the theory expression
(union-theories (current-theory :here) lst).")
(ENABLE-FORCING
(FORCE)
"To allow forced case splits
General Form:
ACL2 !>:enable-forcing ; allowed forced case splits
See [force] and see [case-split] for a discussion of forced case
splits, which are turned back on by this command. See
[disable-forcing] for an example showing how to turn off forced
case splits.
Enable-forcing is actually a macro that [enable]s the executable
counterpart of the function symbol force; see [force]. When you
want to use [hints] to turn on forced case splits, use a form such
as one of the following (these are equivalent).
:in-theory (enable (:executable-counterpart force))
:in-theory (enable (force))")
(ENABLE-IMMEDIATE-FORCE-MODEP
(FORCE)
"[force]d hypotheses are attacked immediately
General Form:
ACL2 !>:enable-immediate-force-modep
This event causes ACL2 to attack [force]d hypotheses immediately
instead of delaying them to the next forcing round. See
[immediate-force-modep]. Or for more basic information, first see
[force] for a discussion of [force]d case splits.
Enable-immediate-force-modep is a macro that [enable]s the executable
counterpart of the function symbol [immediate-force-modep]. When
you want to [enable] this mode in [hints], use a form such as one
of the following (these are equivalent).
:in-theory (enable (:executable-counterpart immediate-force-modep))
:in-theory (enable (immediate-force-modep))")
(ENCAPSULATE
(EVENTS)
"Hide some [events] and/or constrain some functions
Encapsulate provides a way to execute a sequence of [events] and then
hide some of the resulting effects. There are two kinds of
encapsulations: ``trivial'' and ``non-trivial''. We discuss these
briefly before providing detailed [documentation].
A trivial encapsulation is an event of the following form.
(encapsulate
() ; nil here indicates \"trivial\"
<event-1>
...
<event-k>)
We use the term ``sub-events'' to refer to <event-1> through
<event-k>. Each sub-event <event-i> may be ``[local]'', that is, of
the form (local <event-i'>); the other sub-events are called
``non-local''. When this encapsulate form is submitted to ACL2, it
is processed in two passes. On the first pass, each sub-event is
printed (by default) and processed in sequence; admission of the
encapsulate fails if any <event-i> fails to be admitted. Then a
second pass is made after rolling back the logical [world] to what
it was just before executing the encapsulate form. In the second
pass, only the non-[local] forms <event-i> are evaluated, again in
order, and proofs are skipped.
For example, the following trivial encapsulation exports a single
event, member-equal-reverse. The lemma member-revappend is used (as
a [rewrite] rule) to prove member-equal-reverse on the first pass,
but since member-revappend is [local], it is ignored on the second
(final) pass.
(encapsulate
()
(local
(defthm member-revappend
(iff (member-equal a (revappend x y))
(or (member-equal a x)
(member-equal a y)))
:hints ((\"Goal\" :induct (revappend x y)))))
(defthm member-equal-reverse
(iff (member-equal a (reverse x))
(member-equal a x))))
Of course, one might prefer to prove these [events] at the top level,
rather than within an encapsulation; but the point here is to
illustrate that you can have [local] [events] that do not become
part of the logical [world]. (Such a capability is also provided at
the level of [books]; in particular, see [include-book].)
Note that trivial encapsulates must introduce at least one sub-event,
or else they are treated as no-ops, with no effect on the logical
[world]. Consider the following example.
ACL2 !>(encapsulate nil (local (defun f (x) x)))
To verify that the encapsulated event correctly extends the current
theory we will evaluate it. The theory thus constructed is only ephemeral.
Encapsulated Event:
ACL2 !>>(LOCAL (DEFUN F (X) X))
Since F is non-recursive, its admission is trivial. We observe that
the type of F is described by the theorem (EQUAL (F X) X).
Summary
Form: ( DEFUN F ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
F
End of Encapsulated Event.
ACL2 Observation in ( ENCAPSULATE NIL (LOCAL ...) ...): The submitted
encapsulate event has created no new ACL2 events, and thus is leaving
the ACL2 logical world unchanged. See :DOC encapsulate.
Summary
Form: ( ENCAPSULATE NIL (LOCAL ...) ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
:EMPTY-ENCAPSULATE
ACL2 !>
After the above evaluation, we are left in the [world] with which we
began. For example, if you evaluate the above form in the initial
ACL2 world, you can see the following both before and after that
evaluation.
ACL2 !>:pbt 0
0:x(EXIT-BOOT-STRAP-MODE)
ACL2 !>
On the other hand, non-trivial encapsulations provide a way to
introduce axioms about new function symbols, without introducing
inconsistency and without introducing complete definitions. The
following example illustrates how that works.
(encapsulate
; The following list has a single signature, introducing a function foo of
; one argument that returns one value. (The list is non-empty, so we call
; this a \"non-trivial\" encapsulation.)
( ((foo *) => *) )
; Introduce a ``witness'' (example) for foo, marked as local so that
; it is not exported:
(local (defun foo (x) x))
; Introduce a non-local property to be exported:
(defthm foo-preserves-consp
(implies (consp x)
(consp (foo x))))
)
The form above introduces a new function symbol, foo, with the
indicated property and no definition. In fact, the output from ACL2
concludes as follows.
The following constraint is associated with the function FOO:
(IMPLIES (CONSP X) (CONSP (FOO X)))
To understand this example, we consider how non-trivial
encapsulations are processed. The same two passes are made as for
trivial encapsulations, and the ([local]) definition of foo is
ignored on the second pass, and hence does not appear in the
resulting ACL2 logical [world]. But before the second pass, each
[signature] is stored in the [world]. Thus, when the theorem
foo-preserves-consp is encountered in the second pass, foo is a
known function symbol with the indicated signature.
If any event fails while evaluating a call of encapsulate, the entire
encapsulate call is deemed to have failed, and the logical [world]
is rolled back to what it was immediately before the encapsulate
call.
We now provide detailed documentation. But discussion of redundancy
for encapsulate events may be found elsewhere; see
[redundant-encapsulate].
Other Examples:
(encapsulate (((an-element *) => *))
; The list of signatures above could also be written
; ((an-element (lst) t))
(local (defun an-element (lst)
(if (consp lst) (car lst) nil)))
(local (defthm member-equal-car
(implies (and lst (true-listp lst))
(member-equal (car lst) lst))))
(defthm thm1
(implies (null lst) (null (an-element lst))))
(defthm thm2
(implies (and (true-listp lst)
(not (null lst)))
(member-equal (an-element lst) lst))))
(encapsulate
() ; empty signature: no constrained functions indicated
(local (defthm hack
(implies (and (syntaxp (quotep x))
(syntaxp (quotep y)))
(equal (+ x y z)
(+ (+ x y) z)))))
(defthm nthcdr-add1-conditional
(implies (not (zp (1+ n)))
(equal (nthcdr (1+ n) x)
(nthcdr n (cdr x))))))
General Form:
(encapsulate (signature ... signature)
ev1
...
evn)
where each [signature] is a well-formed signature, each signature
describes a different function symbol, and each evi is an embedded
event form (See [embedded-event-form]). Also see [signature], in
particular for a discussion of how a signature can assign a [guard]
to a function symbol. There must be at least one evi. The evi
inside [local] special forms are called ``local'' [events] below.
[Events] that are not [local] are sometimes said to be ``exported''
by the encapsulation. We make the further restriction that no
[defaxiom] event may be introduced in the scope of an encapsulate
(not even by encapsulate or [include-book] events that are among
the evi). Furthermore, no non-[local] [include-book] event is
permitted in the scope of any encapsulate with a non-empty list of
signatures.
To be well-formed, an encapsulate event must have the properties that
each event in the body (including the [local] ones) can be
successfully executed in sequence and that in the resulting theory,
each function mentioned among the [signature]s was introduced via a
[local] event and has the [signature] listed. (A utility is
provided to assist in debugging failures of such execution; see
[redo-flat].) In addition, the body may contain no ``local
incompatibilities'' which, roughly stated, means that the [events]
that are not [local] must not syntactically require symbols defined
by [local] [events], except for the functions listed in the
[signature]s. See [local-incompatibility]. Finally, no non-[local]
recursive definition in the body may involve in its suggested
induction scheme any function symbol listed among the [signature]s.
See [subversive-recursions].
Observe that if the [signature]s list is empty, the resulting
``trivial'' encapsulate may still be useful for deriving theorems
to be exported whose proofs require lemmas you prefer to hide
(i.e., made [local]). Whether trivial or not (i.e., whether the
signature is empty or not), encapsulate exports the results of
evaluating its non-[local] [events], but its [local] [events] are
ignored for the resulting logical [world].
The result of a non-trivial encapsulate event is an extension of the
logic in which, roughly speaking, the functions listed in the
[signature]s are constrained to have the [signature]s listed and to
satisfy the non-[local] theorems proved about them. In fact, other
functions introduced in the encapsulate event may be considered to
have ``[constraint]s'' as well. (See [constraint] for details,
which are only relevant to functional instantiation.) Since the
[constraint]s were all theorems in the ``ephemeral'' or ``local''
theory, we are assured that the extension produced by encapsulate
is sound. In essence, the [local] definitions of the constrained
functions are just ``witness functions'' that establish the
consistency of the [constraint]s. Because those definitions are
[local], they are not present in the theory produced by
encapsulation. After a non-trivial encapsulate event is admitted,
theorems about the constrained function symbols may then be proved
--- theorems whose proofs necessarily employ only the
[constraint]s. Thus, those theorems may be later functionally
instantiated, as with the :functional-instance lemma instance (see
[lemma-instance]), to derive analogous theorems about different
functions, provided the constraints (see [constraint]) can be
proved about the new functions.
The [default-defun-mode] for the first event in an encapsulation is
the default [defun-mode] ``outside'' the encapsulation. But since
[events] changing the [defun-mode] are permitted within the body of
an encapsulate, the default [defun-mode] may be changed. However,
[defun-mode] changes occurring within the body of the encapsulate
are not exported. In particular, the [ACL2-defaults-table] after an
encapsulate is always the same as it was before the encapsulate,
even though the encapsulate body might contain [defun-mode]
changing [events], :[program] and :[logic]. See [defun-mode]. More
generally, after execution of an encapsulate event, the value of
[ACL2-defaults-table] is restored to what it was immediately before
that event was executed. See [ACL2-defaults-table].
We make some remarks on [guard]s and evaluation. Calls of functions
introduced in the [signature]s list cannot be evaluated in the ACL2
read-eval-print loop. See [defattach] for a way to overcome this
limitation. Moreover, any :[guard] supplied in the signature is
automatically associated in the [world] with its corresponding
function symbol, with no requirement other than that the guard is a
legal term all of whose function symbols are in :[logic] mode with
their [guard]s verified. In particular, there need not be any
relationship between a guard in a signature and the guard in a
local witness function. Finally, note that for functions introduced
non-[local]ly inside a non-trivial encapsulate event, [guard]
verification is illegal unless ACL2 determines that the proof
obligations hold outside the [encapsulate] event as well.
(encapsulate
((f (x) t))
(local (defun f (x) (declare (xargs :guard t)) (consp x)))
;; ERROR!
(defun g (x)
(declare (xargs :guard (f x)))
(car x)))
The order of the [events] in the vicinity of an encapsulate is
confusing. We discuss it in some detail here because when logical
names are being used with theory functions to compute sets of
rules, it is sometimes important to know the order in which
[events] were executed. (See [logical-name] and see
[theory-functions].) What, for example, is the set of function
names extant in the middle of an encapsulation?
If the most recent event is previous and then you execute an
encapsulate constraining an-element with two non-[local] [events]
in its body, thm1 and thm2, then the order of the [events] after
the encapsulation is (reading chronologically forward): previous,
thm1, thm2, an-element (the encapsulate itself). Actually, between
previous and thm1 certain extensions were made to the [world] by
the superior encapsulate, to permit an-element to be used as a
function symbol in thm1.
Remark for ACL2(r) (see [real]). For ACL2(r), [encapsulate] can be
used to introduce classical and non-classical functions, as
determined by the signatures; see [signature]. Those marked as
classical (respectively non-classical) must have classical
(respectively, non-classical) [local] witness functions. A related
requirement applies to functional instantiation; see
[lemma-instance].
Subtopics
[Constraint]
Restrictions on certain functions introduced in [encapsulate]
[events]
[Functional-instantiation]
An analogue in ACL2 of higher-order logical reasoning. Functional
instantiation allows you to prove theorems ``by analogy'' with
previous theorems. See [hints] and see [lemma-instance].
[Redundant-encapsulate]
Redundancy of [encapsulate] [events]
[Signature]
How to specify the arity of a constrained function")
(ENDP
(LISTS ACL2-BUILT-INS)
"Recognizer for empty lists
In the ACL2 logic, (endp x) is the same as (atom x). See [atom].
Unlike [atom], the [guard] for endp requires that x is a [cons] pair
or is nil. Thus, endp is typically used as a termination test for
functions that recur on a [true-listp] argument. See [guard] for
general information about [guard]s.
Endp is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <endp>
(defun endp (x)
(declare (xargs :guard (or (consp x) (eq x nil))))
(atom x))")
(ENTER-BOOT-STRAP-MODE
(HISTORY)
"The first millisecond of the Big Bang
ACL2 functions, e.g., [if], that show enter-boot-strap-mode as their
defining [command] are in fact primitives. It is impossible for the
system to display defining axioms about these symbols.
Enter-boot-strap-mode is a Common Lisp function but not an ACL2
function. It magically creates from nil an ACL2 property list
[world] that lets us start the boot-strapping process. That is,
once enter-boot-strap-mode has created its [world], it is possible
to process the [defconst]s, [defun]s, and [defaxiom]s, necessary to
bring up the rest of the system. Before that [world] is created,
the attempt by ACL2 even to translate a [defun] form, say, would
produce an error because [defun] is undefined.
Several ACL2 functions show enter-boot-strap-mode as their defining
[command]. Among them are [if], [cons], [car], and [cdr]. These
functions are characterized by axioms rather than definitional
equations --- axioms that in most cases are built into our code and
hence do not have any explicit representation among the rules and
formulas in the system.")
(EQ
(EQUAL EQUALITY-VARIANTS ACL2-BUILT-INS)
"Equality of symbols
Eq is the function for determining whether two objects are identical
(i.e., have the exact same store address in the current von Neumann
implementation of Common Lisp). It is the same as [equal] in the
ACL2 logic.
Eq is a Common Lisp function. In order to ensure conformance with
Common Lisp, the ACL2 [guard] on eq requires at least one of the
arguments to eq to be a symbol. Common Lisp guarantees that if x is
a symbol, then x is eq to y if and only if x is [equal] to y. Thus,
the ACL2 user should think of eq as nothing besides a fast means
for checking [equal] when one argument is known to be a symbol. In
particular, it is possible that an eq test will not even require
the cost of a function call but will be as fast as a single machine
instruction.
Function: <eq>
(defun eq (x y)
(declare (xargs :guard (if (symbolp x) t (symbolp y))))
(equal x y))")
(EQL
(EQUAL EQUALITY-VARIANTS ACL2-BUILT-INS)
"Test equality (of two numbers, symbols, or [characters])
(eql x y) is logically equivalent to (equal x y).
Unlike [equal], eql has a [guard] requiring at least one of its
arguments to be a number, a symbol, or a character. Generally, eql
is executed more efficiently than [equal].
For a discussion of the various ways to test against 0, See
[zero-test-idioms].
Eql is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <eql>
(defun eql (x y)
(declare (xargs :guard (or (eqlablep x) (eqlablep y))))
(equal x y))")
(EQLABLE-ALISTP
(ALISTS ACL2-BUILT-INS)
"Recognizer for a true list of pairs whose [car]s are suitable for
[eql]
The predicate eqlable-alistp tests whether its argument is a
[true-listp] of [consp] objects whose [car]s all satisfy
[eqlablep].
Function: <eqlable-alistp>
(defun eqlable-alistp (x)
(declare (xargs :guard t))
(cond ((atom x) (equal x nil))
(t (and (consp (car x))
(eqlablep (car (car x)))
(eqlable-alistp (cdr x))))))")
(EQLABLE-LISTP
(EQLABLEP EQUAL LISTS ACL2-BUILT-INS)
"Recognizer for a true list of objects each suitable for [eql]
The predicate eqlable-listp tests whether its argument is a
[true-listp] of objects satisfying [eqlablep].
Function: <eqlable-listp>
(defun eqlable-listp (l)
(declare (xargs :guard t))
(if (consp l)
(and (eqlablep (car l))
(eqlable-listp (cdr l)))
(equal l nil)))")
(EQLABLEP
(EQUAL ACL2-BUILT-INS)
"The [guard] for the function [eql]
The predicate eqlablep tests whether its argument is suitable for
[eql], at least one of whose arguments must satisfy this predicate
in Common Lisp. (Eqlablep x) is true if and only if its argument is
a number, a symbol, or a character.
Function: <eqlablep>
(defun eqlablep (x)
(declare (xargs :guard t))
(or (acl2-numberp x)
(symbolp x)
(characterp x)))
Subtopics
[Eqlable-listp]
Recognizer for a true list of objects each suitable for [eql]")
(EQUAL
(BASICS ACL2-BUILT-INS)
"True equality
(equal x y) is equal to t or nil, according to whether or not x and y
are the same value.
For a discussion of the various idioms for testing against 0, See
[zero-test-idioms].
Subtopics
[=]
Test equality of two numbers
[Eq]
Equality of symbols
[Eql]
Test equality (of two numbers, symbols, or [characters])
[Eqlable-listp]
Recognizer for a true list of objects each suitable for [eql]
[Eqlablep]
The [guard] for the function [eql]
[Hons-equal]
([hons-equal] x y) is a recursive equality check that optimizes when
parts of its arguments are [normed].")
(EQUALITY-VARIANTS
(PROGRAMMING)
"Versions of a function using different equality tests
The ACL2 environment includes not only a logic but also a programming
language, which is based on Common Lisp. Execution efficiency may
be increased by using fast equality tests: [eq] for symbols and
[eql] for numbers, symbols, and characters (see [eqlablep]).
Several list-processing functions built into ACL2 thus have three
variants, depending on whether the equality function used is [eq],
[eql], or [equal]; a list is provided below. ACL2 has taken
measures to ensure that one can reason about a single logical
function even when one uses these different variants.
Consider for example the case of list membership. Common Lisp
provides a utility for this purposes, [member], which can take a
:TEST keyword argument, default [eql]. So for example, one might
write
(member a x :TEST 'eq)
if either a is a symbol or x is a list of symbols, so that the
fastest equality test ([eq]) may be used when comparing a to
successive elements of the list, x. One might elsewhere write
(member b (foo y)), which is equivalent to (member b (foo y) :TEST
'eql), for example if b is a number. If one wants to reason about
both (member a x :TEST 'eq) and (member b y), it might be helpful
for both calls of member to be the same logically, even though
Common Lisp will execute them differently (using [eq] or [eql],
respectively). ACL2 arranges that in fact, both references to
[member] generate calls of [member-equal] in the theorem prover.
In fact, since [member] can take the optional :TEST keyword argument,
then in ACl2 it must be defined as a macro, not a function (see
[defun]). ACL2 arranges that a call of member generates a
corresponding call of the function [member-equal], regardless of
the value of TEST, in a manner that produces [member-equal] in
prover output. More generally, you can expect ACL2 to treat your
use of [member] as though you had written [member-equal], for
example in the way it stores [rewrite] rules and other kinds of
rules as well (see [rule-classes]). We say little here about how
this is all arranged by ACL2, other than to mention that [mbe] is
utilized (so, you might see mention in proof logs) of the function
[return-last] that implements [mbe]. Such details, which involve a
notion of ``macro alias'' and probably can be ignored by most
users, may be found elsewhere; see [equality-variants-details].
As a convenience to the user, the macro member-eq is provided that
expands to a corresponding call of member with :TEST 'eq, as
follows.
ACL2 !>:trans1 (member-eq (foo x) (bar y))
(MEMBER (FOO X) (BAR Y) :TEST 'EQ)
ACL2 !>
For efficiency we recommend using the -equal equality variant, for
example [member-equal] or ([member] ... :TEST 'equal), in certain
contexts: [defmacro], [defpkg], [defconst], and [value-triple]
forms. However, the implementation of equality variants has been
designed so that when defining a function, one may choose freely in
a definition an equality variant of primitive F, to get efficient
execution but where subsequent reasoning is about F-equal. For
details about the above recommendation and for a discussion of the
implementation, see [equality-variants-details].
The following alphabetical list includes all primitives that have
equality variants. Each macro F listed below takes an optional
:TEST keyword argument of 'eq, 'eql, or 'equal, where 'eql is the
default. For each such F, a function F-equal is defined such that
for logical purposes (in particular theorem proving), each call of
F expands to a corresponding call of F-equal. For convenience, a
macro F-eq is also defined, so that a call of F-eq expands to a
corresponding call of F with :TEST 'eq.
[add-to-set]
[assoc]
[delete-assoc]
[intersection$] ; (see Note below)
[intersectp]
[member]
[no-duplicatesp]
position-ac
[position]
[put-assoc]
[rassoc]
[remove-duplicates]
[remove1]
[remove]
[set-difference$] ; (see Note below)
[subsetp]
[union$] ; (see Note below)
Note: Three of the macros above have names ending with the character,
`$': [intersection$], [set-difference$], and [union$]. In each case
there is a corresponding Common Lisp primitive without the trailing
`$': intersection, set-difference, and union. However, Common Lisp
does not specify the order of elements in the list returned by
those primitives, so ACL2 has its own. Nevertheless, the only use
of the trailing `$' is to distinguish the primitives; associated
functions and macros, for example union-eq and intersection-equal,
do not include the `$' character in their names.
We conclude with a brief discussion of [guards]. The expansion of any
of the above macros depends on the keyword argument, which
generates a function call with a guard suitable for the equality
test being used. Consider for example the call (member x lst :test
'eq), or equivalently, (member-eq x lst). Expanding these macros
leads to a call of [mbe]; you can see how that goes by using
:[trans1]. Ultimately, the guard being checked is that of the
function member-eq-exec, which is as follows.
(if (symbolp x)
(true-listp lst)
(symbol-listp lst))
Care has been taken to ensure that this guard is checked during
evaluation and also that it generates suitable proof obligations
for guard verification (see [verify-guards]). A guard violation
might look something like this:
ACL2 !>(member-eq 3 '(4 5))
ACL2 Error in TOP-LEVEL: The guard for the function call
(MEMBER-EQ-EXEC$GUARD-CHECK X LST), which is
(IF (SYMBOLP X) (TRUE-LISTP LST) (SYMBOL-LISTP LST)), is violated by
the arguments in the call (MEMBER-EQ-EXEC$GUARD-CHECK 3 '(4 5)).
See :DOC set-guard-checking for information about suppressing this
check with (set-guard-checking :none), as recommended for new users.
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
ACL2 !>
Above, member-eq-exec$guard-check is a function generated as part of
ACL2's expansion of member with :test 'eq, and this function symbol
can be quite reasonably ignored. The important thing is that it
refers to the guard for member-eq-exec, which as the name may
suggest is intended to guard the execution of a call of
[member-eq], or a call of [member] with :test 'eq. The important
part of the message above is the guard actually being violated: (IF
(SYMBOLP X) (TRUE-LISTP LST) (SYMBOL-LISTP LST)).
Subtopics
[=]
Test equality of two numbers
[Eq]
Equality of symbols
[Eql]
Test equality (of two numbers, symbols, or [characters])
[Equality-variants-details]
Details about [equality-variants]")
(EQUALITY-VARIANTS-DETAILS
(EQUALITY-VARIANTS)
"Details about [equality-variants]
Here we present details about equality variants, none of which is
likely to be important to the majority of ACL2 users. Please see
[equality-variants] for relevant background.
We begin by presenting [events] that implement the equality variants
for [member], as these illustrate the events introduced for all
macros having equality variants. The definition of [member], just
below, calls the macro let-mbe, which in turn is just an
abbreviation for a combination of [let] and [mbe]. Here is a
simplified version of the definition of this macro. For relevant
background, see [mbe].
(defmacro let-mbe (bindings &key logic exec)
`(let ,bindings
(mbe :logic ,logic
:exec ,exec)))
This use of [let] arranges that each argument of a call of member is
evaluated only once.
The actual definition of the macro let-mbe is a bit more complex, in
order to guarantee that [guard]s are appropriately checked. For
purposes of this discussion we ignore this simplification. (You can
find the definition of let-mbe in ACL2 source file axioms.lisp.)
Consider the following definition from ACL2 source file axioms.lisp.
Notice that it invokes the macro let-mbe, discussed above.
(defmacro member (x l &key (test ''eql))
(declare (xargs :guard (or (equal test ''eq)
(equal test ''eql)
(equal test ''equal))))
(cond
((equal test ''eq)
`(let-mbe ((x ,x) (l ,l))
:logic (member-equal x l)
:exec (member-eq-exec x l)))
((equal test ''eql)
`(let-mbe ((x ,x) (l ,l))
:logic (member-equal x l)
:exec (member-eql-exec x l)))
(t ; (equal test 'equal)
`(member-equal ,x ,l))))
Inspection of the definition above shows that every call of [member]
expands to one that is logically equivalent to the corresponding
call of [member-equal], which is defined as follows.
(defun member-equal (x lst)
(declare (xargs :guard (true-listp lst)))
(cond ((endp lst) nil)
((equal x (car lst)) lst)
(t (member-equal x (cdr lst)))))
The following two definitions model equality variants of [member] for
tests [eq] and [eql], respectively.
(defun member-eq-exec (x lst)
(declare (xargs :guard (if (symbolp x)
(true-listp lst)
(symbol-listp lst))))
(cond ((endp lst) nil)
((eq x (car lst)) lst)
(t (member-eq-exec x (cdr lst)))))
(defun member-eql-exec (x lst)
(declare (xargs :guard (if (eqlablep x)
(true-listp lst)
(eqlable-listp lst))))
(cond ((endp lst) nil)
((eql x (car lst)) lst)
(t (member-eql-exec x (cdr lst)))))
At this point the user can write (member x y) or (member-equal x y)
to call equality variants of member with test eql or equal,
respectively. We thus provide the following macro for the eq
variant.
(defmacro member-eq (x lst)
`(member ,x ,lst :test 'eq))
[Guard] proof obligations generated by calls of member will include
those based on its use of mbe, and are supported by the following
two lemmas.
(defthm member-eq-exec-is-member-equal
(equal (member-eq-exec x l)
(member-equal x l)))
(defthm member-eql-exec-is-member-equal
(equal (member-eql-exec x l)
(member-equal x l)))
Finally, the following two events arrange that in certain contexts
such as [theories] (including the use of [in-theory] in [events]
and [hints]), [member-eq] and [member] are treated as references to
[member-equal].
(add-macro-alias member-eq member-equal)
(add-macro-alias member member-equal)
Note however that these events do not affect printing of calls during
proofs: calls of member and member-eq will be macroexpanded away,
leaving you with calls of member-equal that are displayed in proof
output. For a way to change this behavior, see [add-macro-fn].
We conclude this topic by exploring the following recommendation made
in the [documentation] for [equality-variants].
For efficiency we recommend using the -equal equality variant, for
example [member-equal] or ([member] ... :TEST 'equal), in
certain contexts: [defmacro], [defpkg], [defconst], and
[value-triple] forms.
ACL2 relies on the underlying Common Lisp for evaluation. It also
processes events in the ACL2 logic. In order to guarantee
consistency of its logical and Common Lisp evaluations, ACL2 uses a
``safe mode'' to avoid ill-guarded calls. In particular, consider
the use of [mbe] in execution of a call of an equality variant of a
primitive, F, other than its F-equal variant. The [mbe] call
discussed above requires a connection to be established between the
:logic and :exec forms. For example, if F is called with :TEST 'eql
(either explicitly or as the default), then ACL2 will call both
F-eql-exec and F-equal, and check that the two results are equal.
The following partial log illustrates the point above. We define a
macro that calls [member], and when a call of this macro is
expanded during processing of a subsequent definition, we see that
two membership functions are called on the same arguments.
ACL2 !>(defmacro mac (lst)
(list 'quote (and (true-listp lst)
(member 'c lst :test 'eq))))
Summary
Form: ( DEFMACRO MAC ...)
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
MAC
ACL2 !>(trace$ member-equal member-eq-exec)
((MEMBER-EQUAL) (MEMBER-EQ-EXEC))
ACL2 !>(defun f () (mac (a b c d)))
1> (ACL2_*1*_ACL2::MEMBER-EQ-EXEC C (A B C D))
2> (MEMBER-EQ-EXEC C (A B C D))
<2 (MEMBER-EQ-EXEC (C D))
<1 (ACL2_*1*_ACL2::MEMBER-EQ-EXEC (C D))
1> (ACL2_*1*_ACL2::MEMBER-EQUAL C (A B C D))
2> (MEMBER-EQUAL C (A B C D))
<2 (MEMBER-EQUAL (C D))
<1 (ACL2_*1*_ACL2::MEMBER-EQUAL (C D))
Since F is non-recursive, its admission is trivial.
If performance is an issue then we can avoid such a problem, for
example as follows. In a fresh session, let us define a suitable
wrapper for calling [member] with :TEST 'eq. This time, the trace
in our partial log shows that we have avoided calling two
membership functions.
ACL2 !>(defun mem-eq (x lst)
(declare (xargs :guard (if (symbolp x)
(true-listp lst)
(symbol-listp lst))))
(member x lst :test 'eq))
[[ ... output omitted here ... ]]
MEM-EQ
ACL2 !>(defmacro mac (lst)
(list 'quote (and (true-listp lst)
(mem-eq 'c lst))))
Summary
Form: ( DEFMACRO MAC ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
MAC
ACL2 !>(trace$ member-equal member-eq-exec mem-eq)
((MEMBER-EQUAL)
(MEMBER-EQ-EXEC)
(MEM-EQ))
ACL2 !>(defun f () (mac (a b c d)))
1> (ACL2_*1*_ACL2::MEM-EQ C (A B C D))
2> (MEM-EQ C (A B C D))
<2 (MEM-EQ (C D))
<1 (ACL2_*1*_ACL2::MEM-EQ (C D))
Since F is non-recursive, its admission is trivial.")
(EQUIVALENCE
(RULE-CLASSES)
"Mark a relation as an equivalence relation
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Example:
(defthm r-equal-is-an-equivalence ; assumes that r-equal has been defined
(and (booleanp (r-equal x y))
(r-equal x x)
(implies (r-equal x y) (r-equal y x))
(implies (and (r-equal x y)
(r-equal y z))
(r-equal x z)))
:rule-classes :equivalence)
Also see [defequiv].
General Form:
(and (booleanp (equiv x y))
(equiv x x)
(implies (equiv x y) (equiv y x))
(implies (and (equiv x y)
(equiv y z))
(equiv x z)))
except that the order of the conjuncts and terms and the choice of
variable symbols is unimportant. The effect of such a rule is to
identify equiv as an equivalence relation. Note that only Boolean
2-place function symbols can be treated as equivalence relations.
See [congruence] and see [refinement] for closely related concepts.
The macro form (defequiv equiv) is an abbreviation for a [defthm] of
rule-class :equivalence that establishes that equiv is an
equivalence relation. It generates the formula shown above. See
[defequiv].
When equiv is marked as an equivalence relation, its reflexivity,
symmetry, and transitivity are built into the system in a deeper
way than via :[rewrite] rules. More importantly, after equiv has
been shown to be an equivalence relation, lemmas about equiv, e.g.,
(implies hyps (equiv lhs rhs)),
when stored as :[rewrite] rules, cause the system to rewrite certain
occurrences of (instances of) lhs to (instances of) rhs. Roughly
speaking, an occurrence of lhs in the kth argument of some
fn-expression, (fn ... lhs' ...), can be rewritten to produce (fn
... rhs' ...), provided the system ``knows'' that the value of fn
is unaffected by equiv-substitution in the kth argument. Such
knowledge is communicated to the system via ``congruence lemmas.''
For example, suppose that r-equal is known to be an equivalence
relation. The :[congruence] lemma
(implies (r-equal s1 s2)
(equal (fn s1 n) (fn s2 n)))
informs the rewriter that, while rewriting the first argument of
fn-expressions, it is permitted to use r-equal rewrite-rules. See
[congruence] for details about :[congruence] lemmas. Interestingly,
congruence lemmas are automatically created when an equivalence
relation is stored, saying that either of the equivalence
relation's arguments may be replaced by an equivalent argument.
That is, if the equivalence relation is fn, we store congruence
rules that state the following fact:
(implies (and (fn x1 y1)
(fn x2 y2))
(iff (fn x1 x2) (fn y1 y2)))
Another aspect of equivalence relations is that of ``refinement.'' We
say equiv1 ``refines'' equiv2 iff (equiv1 x y) implies (equiv2 x
y). :[refinement] rules permit you to establish such connections
between your equivalence relations. The value of refinements is
that if the system is trying to rewrite something while maintaining
equiv2 it is permitted to use as a :[rewrite] rule any refinement
of equiv2. Thus, if equiv1 is a refinement of equiv2 and there are
equiv1 rewrite-rules available, they can be brought to bear while
maintaining equiv2. See [refinement].
The system initially has knowledge of two equivalence relations,
equality, denoted by the symbol [equal], and propositional
equivalence, denoted by [iff]. [Equal] is known to be a refinement
of all equivalence relations and to preserve equality across all
arguments of all functions.
Typically there are five steps involved in introducing and using a
new equivalence relation, equiv.
(1) Define equiv,
(2) prove the :equivalence lemma about equiv,
(3) prove the :[congruence] lemmas that show where equiv can be used
to maintain known relations,
(4) prove the :[refinement] lemmas that relate equiv to known
relations other than equal, and
(5) develop the theory of conditional :[rewrite] rules that drive
equiv rewriting.
More will be written about this as we develop the techniques. For
now, here is an example that shows how to make use of equivalence
relations in rewriting.
Among the theorems proved below is
(defthm insert-sort-is-id
(perm (insert-sort x) x))
Here perm is defined as usual with delete and is proved to be an
equivalence relation and to be a congruence relation for [cons] and
[member].
Then we prove the lemma
(defthm insert-is-cons
(perm (insert a x) (cons a x)))
which you must think of as you would (insert a x) = (cons a x).
Now prove (perm (insert-sort x) x). The base case is trivial. The
induction step is
(consp x)
& (perm (insert-sort (cdr x)) (cdr x))
-> (perm (insert-sort x) x).
Opening insert-sort makes the conclusion be
(perm (insert (car x) (insert-sort (cdr x))) x).
Apply insert-is-cons to get
(perm (cons (car x) (insert-sort (cdr x)) x)).
Note that we have proved that perm is a congruence relation for cons.
That allows us to apply the induction hypothesis (rewriting
(insert-sort (cdr x)) to (cdr x)), to make the conclusion be
(perm (cons (car x) (cdr x)) x).
But we know that (cons (car x) (cdr x)) is x, so we get (perm x x)
which is trivial, since perm is an equivalence relation. An
exercise left to the reader is how this proof will change had we
also proved that perm is a congruence relation for insert.
Here are the events.
(encapsulate (((lt * *) => *))
(local (defun lt (x y) (declare (ignore x y)) nil))
(defthm lt-non-symmetric (implies (lt x y) (not (lt y x)))))
(defun insert (x lst)
(cond ((atom lst) (list x))
((lt x (car lst)) (cons x lst))
(t (cons (car lst) (insert x (cdr lst))))))
(defun insert-sort (lst)
(cond ((atom lst) nil)
(t (insert (car lst) (insert-sort (cdr lst))))))
(defun del (x lst)
(cond ((atom lst) nil)
((equal x (car lst)) (cdr lst))
(t (cons (car lst) (del x (cdr lst))))))
(defun mem (x lst)
(cond ((atom lst) nil)
((equal x (car lst)) t)
(t (mem x (cdr lst)))))
(defun perm (lst1 lst2)
(cond ((atom lst1) (atom lst2))
((mem (car lst1) lst2)
(perm (cdr lst1) (del (car lst1) lst2)))
(t nil)))
(defthm perm-reflexive
(perm x x))
(defthm perm-cons
(implies (mem a x)
(equal (perm x (cons a y))
(perm (del a x) y)))
:hints ((\"Goal\" :induct (perm x y))))
(defthm perm-symmetric
(implies (perm x y) (perm y x)))
(defthm mem-del
(implies (mem a (del b x)) (mem a x)))
(defthm perm-mem
(implies (and (perm x y)
(mem a x))
(mem a y)))
(defthm mem-del2
(implies (and (mem a x)
(not (equal a b)))
(mem a (del b x))))
(defthm comm-del
(equal (del a (del b x)) (del b (del a x))))
(defthm perm-del
(implies (perm x y)
(perm (del a x) (del a y))))
(defthm perm-transitive
(implies (and (perm x y) (perm y z)) (perm x z)))
(defequiv perm)
(in-theory (disable perm
perm-reflexive
perm-symmetric
perm-transitive))
(defcong perm perm (cons x y) 2)
(defcong perm iff (mem x y) 2)
(defthm atom-perm
(implies (not (consp x)) (perm x nil))
:rule-classes :forward-chaining
:hints ((\"Goal\" :in-theory (enable perm))))
(defthm insert-is-cons
(perm (insert a x) (cons a x)))
(defthm insert-sort-is-id
(perm (insert-sort x) x))
(defun app (x y) (if (consp x) (cons (car x) (app (cdr x) y)) y))
(defun rev (x)
(if (consp x) (app (rev (cdr x)) (list (car x))) nil))
(defcong perm perm (app x y) 2)
(defthm app-cons
(perm (app a (cons b c)) (cons b (app a c))))
(defthm app-commutes
(perm (app a b) (app b a)))
(defcong perm perm (app x y) 1
:hints ((\"Goal\" :induct (app y x))))
(defthm rev-is-id (perm (rev x) x))
(defun == (x y)
(if (consp x)
(if (consp y)
(and (equal (car x) (car y))
(== (cdr x) (cdr y)))
nil)
(not (consp y))))
(defthm ==-reflexive (== x x))
(defthm ==-symmetric (implies (== x y) (== y x)))
(defequiv ==)
(in-theory (disable ==-symmetric ==-reflexive))
(defcong == == (cons x y) 2)
(defcong == iff (consp x) 1)
(defcong == == (app x y) 2)
(defcong == == (app x y) 1)
(defthm rev-rev (== (rev (rev x)) x))")
(EQUIVALENT-FORMULAS-DIFFERENT-REWRITE-RULES
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Logically equivalent formulas can generate radically different rules
Consider the rewrite rules that would be generated from the three
commands below. In all three cases, the fact being stated relates
the nth element of the reverse of x to the nth element of x. In
fact, the three formulas are simple rearrangements of each other
and are all equivalent. The theorem prover treats all three
formulas equivalently when proving them. But the rules generated
from them are very different.
(defthm nth-rev-1
(implies (and (natp n)
(< n (len x)))
(equal (nth n (rev x))
(nth (- (len x) (+ 1 n)) x))))
(defthm nth-rev-2
(implies (and (natp n)
(< n (len x)))
(equal (nth (- (len x) (+ 1 n)) x)
(nth n (rev x)))))
(defthm nth-rev-3
(implies (and (natp n)
(not (equal (nth n (rev x))
(nth (- (len x) (+ 1 n)) x))))
(not (< n (len x)))))
Here are the three rewrite rules:
nth-rev-1:
Replace instances of (NTH n (REV x))
by (NTH (- (LEN x) (+ 1 n)) x),
if you can establish that n is a natural number less than the length
of x.
nth-rev-2:
Replace instances of (NTH (- (LEN x) (+ 1 n)) x)
by (NTH n (REV x)),
if you can establish that n is a natural number less than the length
of x.
nth-rev-3:
Replace instances of (< n (LEN x))
by NIL
if you can establish that n is a natural number and that (NTH n (REV
x)) is different from (NTH (- (LEN x) (+ 1 n)) x).
As the driver of ACL2, you have to decide which rule you want when
you give the command to prove it.
If you tell the theorem prover to use both nth-rev-1 and nth-rev-2,
ACL2 will enter an infinite loop when it sees any term matching
either NTH expression.
Most users would choose form nth-rev-1 of the rule. It eliminates rev
from the problem -- at the expense of introducing some arithmetic.
But arithmetic is so fundamental it is rarely possible to avoid it
and it is likely to be in the problem already since you're indexing
into (rev x). The nth-rev-2 form of the rule is ``bad'' because it
introduces rev into a problem where it might not have appeared. The
nth-rev-3 version is ``bad'' because it makes the theorem prover
shift its attention from a simple arithmetic inequality to a
complicated property of nth and rev, which might not be in the
problem.
Use your browser's Back Button now to return to
[introduction-to-rewrite-rules-part-1].")
(ER
(ERRORS ACL2-BUILT-INS)
"Print an error message and ``cause an error''
See [fmt] for a general discussion of formatted printing in ACL2. All
calls of er print formatted strings, just as is done by [fmt].
Example Forms:
(er hard 'top-level \"Illegal inputs, ~x0 and ~x1.\" a b)
(er hard? 'top-level \"Illegal inputs, ~x0 and ~x1.\" a b)
(er soft 'top-level \"Illegal inputs, ~x0 and ~x1.\" a b)
The examples above all print an error message to standard output
saying that a and b are illegal inputs. However, the first two
abort evaluation after printing an error message (while logically
returning nil, though in ordinary evaluation the return value is
never seen); while the third returns (mv t nil state) after
printing an error message. The result in the third case can be
interpreted as an ``error'' when programming with the ACL2 [state],
something most ACL2 users will probably not want to do unless they
are building systems of some sort; see [programming-with-state]. If
state is not available in the current context then you will
probably want to use (er hard ...) or (er hard? ...) to cause an
error; for example, if you are returning two values, you may write
(mv (er hard ...) nil).
The difference between the hard and hard? forms is one of guards. Use
hard if you want the call to generate a (clearly impossible) guard
proof obligation of (essentially) NIL. But use hard? if you want to
be able to call this function in guard-verified code, since the
call generates a (trivially satisfied) guard proof obligation of T.
Er is a macro, and the above three examples expand to calls of ACL2
functions, as shown below. See [illegal], see [hard-error], and see
[error1]. The first two have guards of (essentially) NIL and T,
respectively, while [error1] is in :[program] mode.
General forms:
(er hard ctx fmt-string arg1 arg2 ... argk)
==> {macroexpands, in essence, to:}
(ILLEGAL CTX FMT-STRING
(LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk)))
(er hard? ctx fmt-string arg1 arg2 ... argk)
==> {macroexpands, in essence, to:}
(HARD-ERROR CTX FMT-STRING
(LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk)))
(er soft ctx fmt-string arg1 arg2 ... argk)
==> {macroexpands, in essence, to:}
(ERROR1 CTX FMT-STRING
(LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk)))
Technical note for raw Lisp programmers only: It is possible to cause
hard errors to signal actual raw Lisp errors. See [hard-error].")
(ER-PROGN
(ERRORS PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Perform a sequence of state-changing ``error triples''
Example:
(er-progn (check-good-foo-p (f-get-global 'my-foo state) state)
(value (* (f-get-global 'my-foo state)
(f-get-global 'bar state))))
This sequencing primitive is only useful when programming with
[state], something that very few users will probably want to do.
See [state].
Er-progn is used much the way that [progn] is used in Common Lisp,
except that it expects each form within it to evaluate to an
[error-triple] of the form (mv erp val state). The first such form,
if any, that evaluates to such a triple where erp is not nil yields
the error triple returned by the er-progn. If there is no such
form, then the last form returns the value of the er-progn form.
General Form:
(er-progn <expr1> ... <exprk>)
where each <expri> is an expression that evaluates to an error triple
(see [programming-with-state]). The above form is essentially
equivalent to the following (``essentially'' because in fact, care
is taken to avoid variable capture).
(mv-let (erp val state)
<expr1>
(cond (erp (mv erp val state))
(t (mv-let (erp val state)
<expr2>
(cond (erp (mv erp val state))
(t ...
(mv-let (erp val state)
<expr{k-1}>
(cond (erp (mv erp val state))
(t <exprk>)))))))))")
(ERROR-TRIPLE
(ERRORS PROGRAMMING-WITH-STATE)
"A common ACL2 programming idiom
When evaluation returns three values, where the first two are
ordinary (non-[stobj]) objects and the third is the ACL2 [state],
the result may be called an ``error triple'' or ``error-triple''.
If an error triple is (mv erp val state), we think of erp as an
error flag and val as the returned value. By default, if the result
of evaluating a top-level form is an error triple (mv erp val
state), then that result is not printed if erp is non-nil or if val
is the keyword :INVISIBLE, and otherwise val is printed with a
preceding space. For example:
ACL2 !>(+ 3 4) ; ordinary value
7
ACL2 !>(mv nil (+ 3 4) state) ; error triple, error component of nil
7
ACL2 !>(mv t (+ 3 4) state) ; error triple, non-nil error component
ACL2 !>(mv nil :invisible state) ; special case for :INVISIBLE
ACL2 !>
See [programming-with-state] for a discussion of error triples and
how to program with them. Also see [ld-error-triples] and see [ld]
for a discussion of the value :COMMAND-CONVENTIONS for keyword
:LD-POST-EVAL-PRINT.")
(ERROR-TRIPLES-AND-PARALLELISM
(PARALLEL-PROGRAMMING)
"How to avoid error triples in ACL2(p)
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
ACL2 supports the use of error triples in many features; e.g.,
[computed-hints]. (For background on error triples, see
[programming-with-state].) However, ACL2(p) does not support the
use of error triples in some of these features (e.g.,
[computed-hints]) while [waterfall-parallelism] is enabled.
You may see an error message like the following when running ACL2(p)
with [waterfall-parallelism] enabled:
ACL2 Error in ( THM ...): Since we are translating a form in ACL2(p)
intended to be executed with waterfall parallelism enabled, the form
(MY-STATE-MODIFYING-COMPUTED-HINT ID STATE) was expected to represent
an ordinary value, not an error triple (mv erp val state), as would
be acceptable in a serial execution of ACL2. Therefore, the form returning
a tuple of the form (* * STATE) is an error. See :DOC unsupported-
waterfall-parallelism-features and :DOC error-triples-and-parallelism
for further explanation.
In this particular example, the cause of the error was trying to use
a computed hint that returned state, which is not allowed when
executing the waterfall in parallel (see
[unsupported-waterfall-parallelism-features] for other related
information).
Often, the only reason users need to return state is so they can
perform some output during the proof process. In this case, we
suggest using one of the state-free output functions, like [cw] or
[observation-cw]. If the user is concerned about the interleaving
of their output with other output, these calls can be surrounded
with the macro [with-output-lock].
Another frequent reason users return state is so they can cause a
soft error and halt the proof process. In this case, we suggest
instead calling [er] with the hard or hard? severity. By using
these mechanisms, the user avoids modifying [state], a requirement
for much of the code written in ACL2(p).
You may encounter other similar error messages when using
[computed-hints], [custom-keyword-hints], or [override-hints].
Chances are that you are somehow returning an error triple when an
ordinary value is needed. If this turns out not to be the case,
please let the ACL2 implementors know.")
(ERROR1
(ERRORS ACL2-BUILT-INS)
"Print an error message and cause a ``soft error''
(Error1 ctx str alist) returns (mv t nil state). An error message is
first printed using the the ``context'' ctx, as well as the string
str and alist alist that are of the same kind as expected by [fmt].
See [fmt].
Error1 can be interpreted as causing an ``error'' when programming
with the ACL2 [state], something most ACL2 users will probably not
want to do; see [ld-error-triples] and see [er-progn]. In order to
cause errors with :[logic] mode functions, see [hard-error] and see
[illegal]. Better yet, see [er] for a macro that provides a unified
way of signaling errors.
As mentioned above, error1 always returns (mv t nil state). But if a
call (error1 ctx str alist) is encountered during evaluation, then
the string str is first printed using the association list alist
(as in [fmt]). Here is a trivial, contrived example.
ACL2 !>(error1 'my-context
\"Printing 4: ~n0\"
(list (cons #\\0 4))
state)
ACL2 Error in MY-CONTEXT: Printing 4: four
ACL2 !>")
(ERRORS
(PROGRAMMING)
"Support for causing runtime errors, breaks, assertions, etc.
Subtopics
[Assert$]
Cause a hard error if the given test is false
[Assert*]
Create a [guard] proof obligation that given test holds
[Break$]
Cause an immediate Lisp break
[Breaks]
Common Lisp breaks
[Er]
Print an error message and ``cause an error''
[Er-progn]
Perform a sequence of state-changing ``error triples''
[Error-triple]
A common ACL2 programming idiom
[Error1]
Print an error message and cause a ``soft error''
[Hard-error]
Print an error message and stop execution
[Illegal]
Print an error message and stop execution")
(ESCAPE-TO-COMMON-LISP
(COMMON-LISP)
"Escaping to Common Lisp
Example:
ACL2 !>:Q
There is essentially no Common Lisp escape feature in the [lp] (but
see [set-raw-mode]). This is part of the price of purity. To
execute a form in Common Lisp as opposed to ACL2, exit [lp] with
:[q], submit the desired forms to the Common Lisp read-eval-print
loop, and reenter ACL2 with (lp).")
(EVALUATING_APP_ON_SAMPLE_INPUT
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Evaluating App on Sample Input
[{IMAGE}]
{IMAGE}
ACL2 !>(app nil '(x y z))
(X Y Z)
ACL2 !>(app '(1 2 3) '(4 5 6 7))
(1 2 3 4 5 6 7)
ACL2 !>(app '(a b c d e f g) '(x y z)) ; click [here] for an explanation
(A B C D E F G X Y Z)
ACL2 !>(app (app '(1 2) '(3 4)) '(5 6))
(1 2 3 4 5 6)
ACL2 !>(app '(1 2) (app '(3 4) '(5 6)))
(1 2 3 4 5 6)
ACL2!>(let ((a '(1 2))
(b '(3 4))
(c '(5 6)))
(equal (app (app a b) c)
(app a (app b c))))
T
{IMAGE}
As we can see from these examples, ACL2 functions can be executed
more or less as Common Lisp.
The last three examples suggest an interesting property of app.
[{IMAGE}]")
(EVALUATOR-RESTRICTIONS
(META)
"Some restrictions on the use of evaluators in meta-level rules
Note: This topic, which explains some subtleties for evaluators, can
probably be skipped by most readers.
Rules of class :[meta] and of class :[clause-processor] are stated
using so-called ``evaluator'' functions. Here we explain some
restrictions related to evaluators. Below we refer primarily to
:meta rules, but the discussion applies equally to
:clause-processor rules.
In a nutshell, we require that a rule's evaluator does not support
other functions in the rule, and we require that the evaluator not
be introduced under a non-trivial encapsulate. We also require that
no function has an attachment (see [defattach]) that is both
ancestral in the evaluator and also ancestral in the meta or
clause-processor functions. We explain these restrictions in detail
below.
An argument given elsewhere (see [meta], in particular ``Aside for
the logic-minded'') explains that the correctness argument for
applying metatheoretic simplifiers requires that one be able to
``grow'' an evaluator (see [defevaluator]) to handle all functions
in the current ACL2 [world]. Then we may, in essence, functionally
instantiate the original evaluator to the new (``grown'')
evaluator, provided that the new evaluator satisfies all of the
axioms of the original. We therefore require that the evaluator
function does not support the formula of any [defaxiom] event. This
notion of ``support'' (sometimes denoted ``is an ancestor of'') is
defined recursively as follows: a function symbol supports a
formula if either it occurs in that formula, or else it supports
the definition or constraint for some function symbol that occurs
in that formula. Moreover, we require that neither the evaluator
function nor its list version support the definition or constraint
for any other function symbol occurring in the proposed :meta
theorem.
We also require that the evaluator does not support the formula of a
:meta rule's metafunction (nor, if there is one, hypothesis
metafunction) or of a :clause-processor rule's clause-processor
function. This requirement, along with with the analogous
requirement for [defaxiom] [events] stated above, are necessary in
order to carry out the functional instantiation argument alluded to
above, as follows (where the reader may find it useful to have some
familiarity with the paper ``Structured Theory Development for a
Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2
(2001), pages 161-203). By the usual conservativity argument, we
know that the rule follows logically from the axiomatic events for
its supporters. This remains true if we functionally instantiate
the evaluator with one corresponding to all the functions symbols
of the current session, since none of the definitions of supporters
of defaxioms or metafunctions are hit by that functional
substitution.
Notice though that the argument above depends on knowing that the
rule is not itself an axiom about the evaluator! Therefore, we also
restrict evaluators so that they are not defined in the scope of a
superior [encapsulate] event with non-empty signature, in order to
avoid an even more subtle problem. The aforementioned correctness
argument depends on knowing that the rule is provable from the
axioms on the evaluator and metafunction (and hypothesis
metafunction, if any). The additional restriction avoids
unsoundness! The following events, if allowed, produce a proof that
(f x) equals t even though, as shown below, that does not follow
logically from the axioms introduced.
; Introduce our metafunction.
(defun my-cancel (term)
(case-match term
(('f ('g))
*t*)
(& term)))
; Introduce our evaluator and prove our meta rule, but in the same
; encapsulate!
(encapsulate
((f (x) t))
(local (defun f (x) (declare (ignore x)) t))
(defevaluator evl evl-list
((f x)))
(defthm correctness-of-my-cancel
(equal (evl x a)
(evl (my-cancel x) a))
:rule-classes ((:meta :trigger-fns (f)))))
; Prove that (f x) = t.
(encapsulate
()
(local (defstub c () t))
(local (encapsulate
()
(local (defun g () (c)))
(local (in-theory (disable g (g))))
(local (defthm f-g
(equal (f (g)) t)
:rule-classes nil))
(defthm f-c
(equal (f (c)) t)
:hints ((\"Goal\" :use f-g
:in-theory (e/d (g) (correctness-of-my-cancel))))
:rule-classes nil)))
(defthm f-t
(equal (f x) t)
:hints ((\"Goal\" :by (:functional-instance
f-c
(c (lambda () x)))))
:rule-classes nil))
To see that the term (equal (f x) t) does not follow logically from
the axiomatic [events] above, consider following the above
definition of my-cancel with the following [events] instead.
; (defun my-cancel (term) ...) as before, then:
(defun f (x)
(not x))
(defun g ()
nil)
(defevaluator evl evl-list
((f x) (g)))
These events imply the axiomatic events above, because we still have
the definition of my-cancel, we have a stronger [defevaluator]
event, and we can now prove correctness-of-my-cancel exactly as it
is stated above. So, the rule f-t is a logical consequence of the
chronology of the current session. However, in the current session
we can also prove the following rule, which contradicts f-t.
(defthm f-not-t
(equal (f t) nil)
:rule-classes nil)
It follows that the current session logically yields a contradiction!
Erik Reeber has taken the above example and modified it to prove nil
in ACL2 Version_3.1, as follows.
(in-package \"ACL2\")
(defun my-cancel (term)
(case-match term
(('f ('g))
*t*)
(('f2 ('g2))
*t*)
(& term)))
(defun f2 (x)
(not x))
(defun g2 ()
nil)
(encapsulate
((f (x) t))
(local (defun f (x) (declare (ignore x)) t))
(defevaluator evl evl-list
((f x)
(f2 x)
(g2)))
(defthm correctness-of-my-cancel
(equal (evl x a)
(evl (my-cancel x) a))
:rule-classes ((:meta :trigger-fns (f)))))
(encapsulate
()
(local (defstub c () t))
(local (encapsulate
()
(local (defun g () (c)))
(local (in-theory (disable g (g))))
(local (defthm f-g
(equal (f (g)) t)
:rule-classes nil))
(defthm f-c
(equal (f (c)) t)
:hints ((\"Goal\" :use f-g
:in-theory (e/d (g) (correctness-of-my-cancel))))
:rule-classes nil)))
(defthm f-t
(equal (f x) t)
:hints ((\"Goal\" :by (:functional-instance
f-c
(c (lambda () x)))))
:rule-classes nil))
(defun g ()
nil)
; Below is the expansion of the following defevaluator, changed slightly as
; indicated by comments.
; (defevaluator evl2 evl2-list ((f x) (f2 x) (g) (g2)))
(ENCAPSULATE
(((EVL2 * *) => *)
((EVL2-LIST * *) => *))
(SET-INHIBIT-WARNINGS \"theory\")
(LOCAL (IN-THEORY *DEFEVALUATOR-FORM-BASE-THEORY*))
(LOCAL
(MUTUAL-RECURSION (DEFUN EVL2 (X A)
(DECLARE (XARGS :VERIFY-GUARDS NIL
:MEASURE (ACL2-COUNT X)
:WELL-FOUNDED-RELATION O<
:MODE :LOGIC))
(COND ((SYMBOLP X) (CDR (ASSOC-EQ X A)))
((ATOM X) NIL)
((EQ (CAR X) 'QUOTE) (CAR (CDR X)))
((CONSP (CAR X))
(EVL2 (CAR (CDR (CDR (CAR X))))
(PAIRLIS$ (CAR (CDR (CAR X)))
(EVL2-LIST (CDR X) A))))
((EQUAL (CAR X) 'F) ; changed f to f2 just below
(F2 (EVL2 (CAR (CDR X)) A)))
((EQUAL (CAR X) 'F2)
(F2 (EVL2 (CAR (CDR X)) A)))
((EQUAL (CAR X) 'G) (G))
((EQUAL (CAR X) 'G2) (G2))
(T NIL)))
(DEFUN EVL2-LIST (X-LST A)
(DECLARE (XARGS :MEASURE (ACL2-COUNT X-LST)
:WELL-FOUNDED-RELATION O<))
(COND ((ENDP X-LST) NIL)
(T (CONS (EVL2 (CAR X-LST) A)
(EVL2-LIST (CDR X-LST) A)))))))
(DEFTHM EVL2-CONSTRAINT-1
(IMPLIES (SYMBOLP X)
(EQUAL (EVL2 X A)
(CDR (ASSOC-EQ X A)))))
(DEFTHM EVL2-CONSTRAINT-2
(IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'QUOTE))
(EQUAL (EVL2 X A) (CADR X))))
(DEFTHM EVL2-CONSTRAINT-3
(IMPLIES (AND (CONSP X) (CONSP (CAR X)))
(EQUAL (EVL2 X A)
(EVL2 (CADDAR X)
(PAIRLIS$ (CADAR X)
(EVL2-LIST (CDR X) A))))))
(DEFTHM EVL2-CONSTRAINT-4
(IMPLIES (NOT (CONSP X-LST))
(EQUAL (EVL2-LIST X-LST A) NIL)))
(DEFTHM EVL2-CONSTRAINT-5
(IMPLIES (CONSP X-LST)
(EQUAL (EVL2-LIST X-LST A)
(CONS (EVL2 (CAR X-LST) A)
(EVL2-LIST (CDR X-LST) A)))))
(DEFTHM EVL2-CONSTRAINT-6
(IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'F))
(EQUAL (EVL2 X A) ; changed f to f2 just below
(F2 (EVL2 (CADR X) A)))))
(DEFTHM EVL2-CONSTRAINT-7
(IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'F2))
(EQUAL (EVL2 X A)
(F2 (EVL2 (CADR X) A)))))
(DEFTHM EVL2-CONSTRAINT-8
(IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'G))
(EQUAL (EVL2 X A) (G))))
(DEFTHM EVL2-CONSTRAINT-9
(IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'G2))
(EQUAL (EVL2 X A) (G2)))))
(defthm f2-t
(equal (f2 x) t)
:hints ((\"Goal\" :by (:functional-instance
f-t
(f f2)
(evl evl2)
(evl-list evl2-list)))))
(defthm bug-implies-nil
nil
:hints ((\"Goal\" :use ((:instance f2-t (x t)))))
:rule-classes nil)
Finally, we also require that no function has an attachment (see
[defattach]) that is both ancestral in the evaluator and also
ancestral in the meta or clause-processor functions. (If you don't
use [defattach] then you can ignore this condition.) Without this
restriction, the following events prove nil.
(in-package \"ACL2\")
(defstub f () t)
(defevaluator evl evl-list
((f)))
(defun my-meta-fn (x)
(if (equal x '(f))
(list 'quote (f))
x))
(defthm my-meta-fn-correct
(equal (evl x a)
(evl (my-meta-fn x) a))
:rule-classes ((:meta :trigger-fns (f))))
(defun constant-nil ()
(declare (xargs :guard t))
nil)
(defattach f constant-nil)
(defthm f-is-nil
; proved using my-meta-fn-correct
(equal (f) nil)
:rule-classes nil)
(defthm contradiction
nil
:hints ((\"Goal\" :use ((:functional-instance
f-is-nil
(f (lambda () t))))))
:rule-classes nil)
To see why this restriction is sufficient, see a comment in the ACL2
source code entitled ``; Essay on Correctness of Meta Reasoning.''")
(EVENP
(NUMBERS ACL2-BUILT-INS)
"Test whether an integer is even
(evenp x) is true if and only if the integer x is even. Actually, in
the ACL2 logic (evenp x) is defined to be true when x/2 is an
integer.
The [guard] for evenp requires its argument to be an integer.
Evenp is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <evenp>
(defun evenp (x)
(declare (xargs :guard (integerp x)))
(integerp (* x (/ 2))))")
(EVENTS
(ACL2)
"Functions that extend the logic
Any extension of the syntax of ACL2 (i.e., the definition of a new
constant or macro), the axioms (i.e., the definition of a
function), or the rule database (i.e., the proof of a theorem),
constitutes a logical ``event.'' Events change the ACL2 logical
world (see [world]). Indeed, the only way to change the ACL2
[world] is via the successful evaluation of an event function.
Every time the [world] is changed by an event, a landmark is left
on the [world] and it is thus possible to identify the [world] ``as
of'' the evaluation of a given event. An event may introduce new
logical names. Some events introduce no new names (e.g.,
[verify-guards]), some introduce exactly one (e.g., [defmacro] and
[defthm]), and some may introduce many (e.g., [encapsulate] ).
ACL2 typically completes processing of an event by printing a
summary. Unless proofs are skipped (see [ld-skip-proofsp]) or
summary output is inhibited (see [set-inhibit-output-lst]),
information about the proof attempt (if any) is printed that
includes a list of rules used, a summary of warnings, and the
number of ``prover steps'' (if any; see [with-prover-step-limit]).
A breakdown of the time used is also printed, which by default is
runtime (cpu time), but can be changed to realtime (wall clock
time); see [get-internal-time].
See [embedded-event-form] for a discussion of events permitted in
[books].
Subtopics
[Add-custom-keyword-hint]
Add a new custom keyword hint
[Assert-event]
Assert that a given form returns a non-nil value
[Comp]
Compile some ACL2 functions
[Defabbrev]
A convenient form of macro definition for simple expansions
[Defabsstobj]
Define a new abstract single-threaded object
[Defabsstobj-missing-events]
Obtain the [events] needed to admit a [defabsstobj] event
[Defattach]
Execute constrained functions using corresponding attached functions
[Defaxiom]
Add an axiom
[Defchoose]
Define a Skolem (witnessing) function
[Defcong]
Prove [congruence] rule
[Defconst]
Define a constant
[Defdoc]
Deprecated event (formerly for adding documentation)
[Defequiv]
Prove that a function is an [equivalence] relation
[Defevaluator]
Introduce an evaluator function
[Defexec]
Attach a terminating executable function to a definition
[Define-trusted-clause-processor]
Define a trusted (unverified) goal-level simplifier
[Deflabel]
Build a landmark
[Defmacro]
Define a macro
[Defmacro-last]
Define a macro that returns its last argument, but with side effects
[Defn]
Definition with [guard] t
[Defnd]
[disable]d definition with [guard] t
[Defpkg]
Define a new symbol package
[Defproxy]
Define a non-executable :[program]-mode function for attachment
[Defpun]
Define a tail-recursive function symbol
[Defrec]
Introduce a record structure, like a struct in C.
[Defrefinement]
Prove that equiv1 refines equiv2
[Defstobj]
Define a new single-threaded object
[Defstub]
Stub-out a function symbol
[Deftheory]
Define a theory (to [enable] or [disable] a set of rules)
[Deftheory-static]
Define a `static' theory (to [enable] or [disable] a set of rules)
[Defthm]
Prove and name a theorem
[Defthmd]
Prove and name a theorem and then disable it
[Defttag]
Introduce a trust tag (ttag)
[Defun]
Define a function symbol
[Defun-inline]
Define a potentially inlined function symbol and associated macro
[Defun-notinline]
Define a not-to-be-inlined function symbol and associated macro
[Defun-nx]
Define a non-executable function symbol
[Defun-sk]
Define a function whose body has an outermost quantifier
[Defund]
Define a function symbol and then disable it
[Defund-inline]
Define a potentially disabled, inlined function symbol and
associated macro
[Defund-notinline]
Define a disabled, not-to-be-inlined function symbol and associated
macro
[Embedded-event-form]
Forms that may be embedded in other [events]
[Encapsulate]
Hide some [events] and/or constrain some functions
[Evisc-table]
Support for abbreviated output
[In-arithmetic-theory]
Designate theory for some rewriting done for non-linear arithmetic
[In-theory]
Designate ``current'' theory (enabling its rules)
[Include-book]
Load the [events] in a file
[Local]
Hiding an event in an encapsulation or book
[Logical-name]
A name created by a logical event
[Make-event]
Evaluate (expand) a given form and then evaluate the result
[Memoize]
Turn on memoization for a specified function
[Mutual-recursion]
Define some mutually recursive functions
[Name]
Syntactic rules on logical names
[Profile]
Turn on profiling for one function
[Progn]
Evaluate some [events]
[Progn!]
Evaluate some forms, not necessarily [events]
[Redundant-events]
Allowing a name to be introduced ``twice''
[Regenerate-tau-database]
Regenerate the tau database relative to the current enabled theory
[Remove-custom-keyword-hint]
Remove a custom keyword hint
[Set-body]
Set the definition body
[Skip-proofs]
Skip proofs for a given form --- a quick way to introduce
unsoundness
[Table]
User-managed tables
[Theory-invariant]
User-specified invariants on [theories]
[Unmemoize]
Turn off memoization for the specified function
[Value-triple]
Compute a value, optionally checking that it is not nil
[Verify-guards]
Verify the [guard]s of a function
[Verify-guards+]
Verify the [guard]s of a function
[Verify-termination]
Convert a function from :program mode to :logic mode")
(EVISC-TABLE
(EVENTS)
"Support for abbreviated output
The evisc-table is an ACL2 table (see [table]) whose purpose is to
modify the print representations of specified non-nil objects. When
a key (some object) is associated with a string value, then that
string is printed instead of that key (as an abbreviation). For
example, the following log shows how to abbreviate the key (a b c)
with the token <my-abc-list>.
ACL2 !>(table evisc-table '(a b c) \"<my-abc-list>\")
Summary
Form: ( TABLE EVISC-TABLE ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
EVISC-TABLE
ACL2 !>'(a b c)
<my-abc-list>
ACL2 !>'(4 5 a b c)
(4 5 . <my-abc-list>)
ACL2 !>
Every value in this [table] must be either a string or nil, where nil
eliminates any association of the key with an abbreviation.
Continuing with the log above:
ACL2 !>(table evisc-table '(a b c) nil)
Summary
Form: ( TABLE EVISC-TABLE ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
EVISC-TABLE
ACL2 !>'(a b c)
(A B C)
ACL2 !>'(4 5 a b c)
(4 5 A B C)
ACL2 !>
It can be particularly helpful to use this table to abbreviate a
constant introduced by [defconst] by prefixing the constant name
with \"#,\", as we now describe. Consider first the following
example.
(defconst *abc* '(1 2 3 4 5 6 7 8))
(table evisc-table *abc*
(concatenate 'string \"#,\" (symbol-name '*abc*)))
Then the constant *abc* is printed as follows --- very helpful if its
associated structure is significantly larger than the 8-element
list of numbers shown above!
ACL2 !>*abc*
#,*ABC*
ACL2 !>
What's more, the ACL2 reader will replace #,*C*, where *C* is defined
by [defconst], by its value, regardless of evisc-table; see
[sharp-dot-reader]. Continuing with the example above, we have:
ACL2 !>(cdr (quote #,*ABC*))
(2 3 4 5 6 7 8)
ACL2 !>
Of course, more care needs to be taken if packages are involved (see
[defpkg]), as we now illustrate.
ACL2 !>(defpkg \"FOO\" nil)
Summary
Form: ( DEFPKG \"FOO\" ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
\"FOO\"
ACL2 !>(defconst foo::*a* '(1 2 3))
Summary
Form: ( DEFCONST FOO::*A* ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO::*A*
ACL2 !>(table evisc-table foo::*a* \"#,foo::*a*\")
Summary
Form: ( TABLE EVISC-TABLE ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
EVISC-TABLE
ACL2 !>foo::*a*
#,foo::*a*
ACL2 !>'#,foo::*a*
#,foo::*a*
ACL2 !>(cdr '#,foo::*a*)
(2 3)
ACL2 !>
We conclude by an example showing some extra care that may be
important to consider taking. We start with:
(defconst |*BaR*| '(3 4))
Then the following works just fine; but try it without the extra code
for the may-need-slashes case and you'll see that the sharp-dot
printing is missing. First:
(table evisc-table
|*BaR*|
(let ((x (symbol-name '|*BaR*|)))
(if (may-need-slashes x)
(concatenate 'string \"#.|\" x \"|\")
(concatenate 'string \"#.\" x))))
Then:
ACL2 !>|*BaR*|
#,|*BaR*|
ACL2 !>")
(EVISC-TUPLE
(IO)
"Control suppression of details when printing
ACL2 output is generally printed in full. However, ACL2 can be
directed to abbreviate, or ``eviscerate'', objects before printing
them. To ``eviscerate'' an object we replace certain substructures
within it by strings that are printed in their stead. Such
replacement is made relative to a so-called ``evisc-tuple'', which
has four components: (evisc-tuple print-level print-length alist
hiding-cars) is the same as the value of (list alist print-level
print-length hiding-cars), and the components are used as follows
(with priority order as discussed below). The alist component is
used to replace any substructure occurring as a key by the
corresponding string. The print-level and print-length are
analogous to Common Lisp variables *print-level* and
*print-length*, respectively, and cause replacement of
substructures deeper than print-level by `#' and those longer than
print-length by `...'. Finally, any [consp] x that starts with one
of the symbols in hiding-cars is printed as <hidden>.
The following example illustrates the use of an evisc-tuple that
limits the print-level to 3 --- only three descents into list
structures are permitted before replacing a subexpression by `#'
--- and limits the print-length to 4 --- only the first four
elements of any list structure will be printed before replacing its
tail by `...'.
ACL2 !>(fms \"~x0~%\"
(list (cons #\\0 '((a b ((c d)) e f g) u v w x y)))
*standard-co*
state
(evisc-tuple 3 4 nil nil))
((A B (#) E ...) U V W ...)
<state>
ACL2 !>
Notice that it is impossible to read the printed value back into
ACL2, since there is no way for the ACL2 reader to interpret `#' or
`...'. To solve this problem, see [set-iprint].
In the above example we pass an evisc-tuple explicitly to a printing
function, in this case, [fms] (see [fmt]). But ACL2 also does its
own printing, for example during a proof attempt. There are global
evisc-tuples that control ACL2's printing; see [set-evisc-tuple]
and see [without-evisc].")
(EVISCERATE-HIDE-TERMS
(IO)
"To print (hide ...) as <hidden>
Example:
(assign eviscerate-hide-terms t)
(assign eviscerate-hide-terms nil)
Eviscerate-hide-terms is a [state] global variable whose value is
either t or nil. The variable affects how terms are displayed by
default (but not if you have set the term-evisc-tuple to other than
its default; see [set-evisc-tuple]). If t, terms of the form (hide
...) are printed as <hidden>. Otherwise, they are printed normally.")
(EXAMPLE-INDUCTION-SCHEME-BINARY-TREES
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Induction on binary trees
See [logic-knowledge-taken-for-granted-inductive-proof] for an
explanation of what we mean by the induction suggested by a
recursive function or a term.
Classical Induction on Binary Trees: To prove (p x), for all x, by
classical induction on binary tree structures, prove each of the
following:
Base Case:
(implies (atom x) (p x))
Induction Step:
(implies (and (not (atom x))
(p (car x))
(p (cdr x)))
(p x))
An argument analogous to that given in
[example-induction-scheme-on-lists] should convince you that (p x)
holds for every object.
A function that suggests this induction is:
(defun flatten (x)
(if (atom x)
(list x)
(app (flatten (car x))
(flatten (cdr x))))).")
(EXAMPLE-INDUCTION-SCHEME-DOWN-BY-2
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Induction downwards 2 steps at a time
See [logic-knowledge-taken-for-granted-inductive-proof] for an
explanation of what we mean by the induction suggested by a
recursive function or a term.
Classical Induction on Natural Numbers Preserving Parity: Here is
another way to decompose natural numbers. To prove (p n), for all
n, prove each of the following:
Base Case 1:
(implies (zp n) (p n))
Base Case 2:
(implies (equal n 1) (p n))
Induction Step:
(implies (and (not (zp n))
(not (equal n 1))
(p (- n 2)))
(p n))
Base Case 1 establishes that p holds for 0 (and all objects other
than positive naturals).
Base Case 2 establishes that p holds for 1.
The Induction Step establishes that if n is a natural number greater
than 1, and if p holds for n-2, then p holds for n.
Note that we have thus proved that (p n) holds, for all n. For
example, (p -7), (p 'abc), and (p 0) are all established by Base
Case 1. (p 1) is established by Base Case 2. (p 2) is established
from (p 0) and the Induction Step. Think about it! (p 3) is
established form (p 1) and the Induction Step, etc.
A function that suggests this induction is:
(defun parity (n)
(if (zp n)
'even
(if (equal n 1)
'odd
(parity (- n 2))))).")
(EXAMPLE-INDUCTION-SCHEME-NAT-RECURSION
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Induction on natural numbers
See [logic-knowledge-taken-for-granted-inductive-proof] for an
explanation of what we mean by the induction suggested by a
recursive function or a term.
Classical Induction on Natural Numbers: Induction is familiar in the
arithmetic setting. To prove (p n), for all n, by classical
induction on the construction of the natural numbers, prove each of
the following:
Base Case:
(implies (zp n) (p n))
Induction Step:
(implies (and (not (zp n))
(p (- n 1)))
(p n))
The Base Case establishes that p holds for 0. In fact, because of the
definition of [zp] [{ICON}], it establishes that (p n) holds when n
is 0 and it holds when n is not a natural number.
The Induction Step establishes that if n is a natural number other
than 0, and if p holds for n-1, then p holds for n. The hypothesis
(p (- n 1)) above is called the induction hypothesis.
A function that suggests this induction is
(defun nat-recursion (n)
(if (zp n)
n
(nat-recursion (- n 1))))
Similarly, the term (fact n) suggests this induction if fact is
defined:
(defun fact (k)
(if (zp k)
1
(* k (fact (- k 1))))).
even though the formal parameter of this definition of fact is k, not
n.")
(EXAMPLE-INDUCTION-SCHEME-ON-LISTS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Induction on lists
See [logic-knowledge-taken-for-granted-inductive-proof] for an
explanation of what we mean by the induction suggested by a
recursive function or a term.
Classical Induction on Lists: To prove (p x), for all x, by classical
induction on the linear list structure, prove each of the
following:
Base Case:
(implies (endp x) (p x))
Induction Step:
(implies (and (not (endp x))
(p (cdr x)))
(p x))
An argument analogous to that given for natural numbers,
[example-induction-scheme-nat-recursion], establishes (p x) for
every x. For example, (p -7), (p 'abc), and (p nil) are all
established by the Base Case. (p '(Friday)) follows from (p nil),
given the Induction Step. That sentence bears thinking about! Think
about it! Similarly, (p '(Yellow)) holds for the same reason. (p
'(Thursday Friday)) follows from (p '(Friday)) and the Induction
Step, etc.
A function that suggests this induction is
(defun app (x y)
(if (endp x)
y
(cons (car x)
(app (cdr x) y)))).")
(EXAMPLE-INDUCTION-SCHEME-ON-SEVERAL-VARIABLES
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Induction on several variables
See [logic-knowledge-taken-for-granted-inductive-proof] for an
explanation of what we mean by the induction suggested by a
recursive function or a term.
Induction on Several Variables To (p n x) for all n and all x, prove
each of the following:
Base Case 1:
(implies (endp x)
(p n x))
Base Case 2:
(implies (and (not (endp x))
(zp n))
(p n x))
Induction Step:
(implies (and (not (endp x))
(not (zp n))
(p (- n 1) (cdr x)))
(p n x))
A function that suggests this induction is
(defun nth (n x)
(if (endp x)
nil
(if (zp n)
(car x)
(nth (- n 1) (cdr x))))).")
(EXAMPLE-INDUCTION-SCHEME-UPWARDS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Induction upwards
See [logic-knowledge-taken-for-granted-inductive-proof] for an
explanation of what we mean by the induction suggested by a
recursive function or a term.
Induction Upwards: To (p i max) for all i and all max, prove each of
the following:
Base Case:
(implies (not (and (natp i)
(natp max)
(< i max)))
(p i max))
Induction Step:
(implies (and (natp i)
(natp max)
(< i max)
(p (+ i 1) max))
(p i max))
Note that the induction hypothesis is about an i that is bigger than
the i in in the conclusion. In induction, as in recursion, the
sense of one thing being ``smaller'' than another is determined by
an arbitrary measure of all the variables, not the magnitude or
extent of some particular variable.
A function that suggests this induction is shown below. ACL2 has to
be told the measure, namely the difference between max and i
(coerced to a natural number to insure that the measure is an
ordinal).
(defun count-up (i max)
(declare (xargs :measure (nfix (- max i))))
(if (and (natp i)
(natp max)
(< i max))
(cons i (count-up (+ 1 i) max))
nil)).")
(EXAMPLE-INDUCTION-SCHEME-WITH-ACCUMULATORS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Induction scheme with accumulators
See [logic-knowledge-taken-for-granted-inductive-proof] for an
explanation of what we mean by the induction suggested by a
recursive function or a term.
To prove (p x a) for all x and all a, prove each of the following:
Base Case:
(implies (endp x)
(p x a))
Induction Step:
(implies (and (not (endp x))
(p (cdr x) (cons (car x) a)))
(p x a))
Note that in the induction hypothesis we assume p for a smaller x but
a larger a. In fact, we could include as many induction hypotheses
as we want and use any terms we want in the a position as long as
the x position is occupied by a smaller term.
A function that suggests this particular induction is shown below.
(defun rev1 (x a)
(if (endp x)
a
(rev1 (cdr x) (cons (car x) a)))).
A function that suggests a similar induction in which three induction
hypotheses are provided, one in which the a position is occupied by
(cons (car x) a), another in which the a position is occupied by
some arbitrary term b, and a third in which the a position is
occupied by a, is suggested by the term (rev1-modified x a b) where
(defun rev1-modified (x a b)
(if (endp x)
(list x a b)
(list (rev1-modified (cdr x) (cons (car x) a) b)
(rev1-modified (cdr x) b b)
(rev1-modified (cdr x) a b))))
Remember that the value of this term or function is irrelevant to the
induction suggested. Because ACL2's definitional principle insists
that all the formal parameters play a role in the computation (at
least syntactically), it is common practice when defining functions
for their induction schemes to return the list of all the formals
(to insure all variables are involved) and to combine recursive
calls on a given branch with list (to avoid introducing additional
case analysis as would happen if and or or or other propositional
functions are used).
If you tried to prove (p x a) and suggested the induct hint
(rev1-modified x a (fact k)), as by
(thm (p x a)
:hints ((\"Goal\" :induct (rev1-modified x a (fact k)))))
the inductive argument would be:
Base Case:
(implies (endp x)
(p x a))
Inductive Step:
(implies (and (not (endp x))
(p (cdr x) (cons (car x) a))
(p (cdr x) (fact k))
(p (cdr x) a))
(p x a))")
(EXAMPLE-INDUCTION-SCHEME-WITH-MULTIPLE-INDUCTION-STEPS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Induction scheme with more than one induction step
See [logic-knowledge-taken-for-granted-inductive-proof] for an
explanation of what we mean by the induction suggested by a
recursive function or a term.
Several Induction Steps: To (p x i a) for all x, i, and a, prove each
of the following:
Base Case 1:
(implies (zp i)
(p x i a))
Induction Step 1:
(implies (and (not (zp i))
(equal (parity i) 'even)
(p (* x x)
(floor i 2)
a))
(p x i a))
Induction Step 2:
(implies (and (not (zp i))
(not (equal (parity i) 'even))
(p x
(- i 1)
(* x a)))
(p x i a))
A function that suggests this induction is the binary exponentiation
function for natural numbers.
(defun bexpt (x i a)
(cond ((zp i) a)
((equal (parity i) 'even)
(bexpt (* x x)
(floor i 2)
a))
(t (bexpt x
(- i 1)
(* x a)
)))).
In order to admit this function it is necessary to know that (floor i
2) is smaller than i in the case above. This can be proved if the
community book \"arithmetic-5/top\" has been included from the ACL2
system directory, i.e.,
(include-book \"arithmetic-5/top\" :dir :system)
should be executed before defining bexpt.")
(EXAMPLE-INDUCTIONS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Some examples of induction schemes in ACL2
Here are some pages illustrating various induction schemes suggested
by recursive functions.
Classical Induction on Natural Numbers: see
[example-induction-scheme-nat-recursion].
Induction Preserving Even/Odd Parity or
Induction Downwards by 2 or
Induction with Multiple Base Cases: see
[example-induction-scheme-down-by-2] for an induction in which the
induction hypothesis decreases the induction variable by an amount
other than 1. This illustrates that the induction hypothesis can be
about whatever term or terms are needed to explain how the formula
recurs. The example also illustrates an induction with more than
one Base Case.
Classical Induction on Lists: see [example-induction-scheme-on-lists]
for an induction over linear lists, in which we inductively assume
the conjecture for (cdr x) and prove it for x. It doesn't matter
whether the list is nil-terminated or not; the Base Case addresses
all the possibilities.
Classical Induction on Binary (Cons) Trees: see
[example-induction-scheme-binary-trees] for an induction over the
simplest form of binary tree. Here the Induction Step provides two
hypotheses, one about the left subtree and one about the right
subtree.
Induction on Several Variables: see
[example-induction-scheme-on-several-variables] for an induction in
which several variables participate in the case analysis and
induction hypotheses.
Induction Upwards: see [example-induction-scheme-upwards] for an
induction scheme in which the induction hypothesis is about
something ``bigger than'' the induction conclusion. This
illustrates that the sense in which the hypothesis is about
something ``smaller'' than the conclusion is determined by a
measure of all the variables, not the magnitude or extent of some
single variable.
Induction with Auxiliary Variables or
Induction with Accumulators: see
[example-induction-scheme-with-accumulators] for an induction
scheme in which one variable ``gets smaller'' but another is
completely arbitrary. Such schemes are common when dealing with
tail-recursive functions that accumulate partial results in
auxiliary variables. This example also shows how to provide several
arbitrary terms in a non-inductive variable of a scheme.
Induction with Multiple Induction Steps: see
[example-induction-scheme-with-multiple-induction-steps] for an
induction in which we make different inductive hypotheses depending
on which case we're in. This example also illustrates the handling
of auxiliary variables or accumulators.")
(EXECUTABLE-COUNTERPART
(RULE-CLASSES)
"A rule for computing the value of a function
Examples:
(:executable-counterpart length)
which may be abbreviated in [theories] as
(length)
Every [defun] introduces at least two rules used by the theorem
prover. Suppose fn is the name of a [defun]'d function. Then
(:definition fn) is the rune (see [rune]) naming the rule that
allows the simplifier to replace calls of fn by its instantiated
body. (:executable-counterpart fn) is the [rune] for the rule for
how to evaluate the function on known constants.
When typing [theories] it is convenient to know that (fn) is a runic
designator that denotes (:executable-counterpart fn). See
[theories].
If (:executable-counterpart fn) is [enable]d, then when applications
of fn to known constants are seen by the simplifier they are
computed out by executing the Common Lisp code for fn (with the
appropriate handling of [guard]s). Suppose fact is defined as the
factorial function. If the executable counterpart [rune] of fact,
(:executable-counterpart fact), is [enable]d when the simplifier
encounters (fact 12), then that term will be ``immediately''
expanded to 479001600. Note that even if subroutines of fn have
disabled executable counterparts, fn will call their Lisp code
nonetheless: once an executable counterpart function is applied, no
subsidiary enable checks are made.
Such one-step expansions are sometimes counterproductive because they
prevent the anticipated application of certain lemmas about the
subroutines of the expanded function. Such computed expansions can
be prevented by disabling the executable counterpart [rune] of the
relevant function. For example, if (:executable-counterpart fact)
is [disable]d, (fact 12) will not be expanded by computation. In
this situation, (fact 12) may be rewritten to (* 12 (fact 11)),
using the rule named (:definition fact), provided the system's
heuristics permit the introduction of the term (fact 11). Note that
lemmas about multiplication may then be applicable (while such
lemmas would be inapplicable to 479001600). In many proofs it is
desirable to [disable] the executable counterpart [rune]s of
certain functions to prevent their expansion by computation. See
[executable-counterpart-theory].
Finally: What do we do about functions that are ``constrained''
rather than defined, such as the following? (See [encapsulate].)
(encapsulate (((foo *) => *))
(local (defun foo (x) x)))
Does foo have an executable counterpart? Yes: since the vast majority
of functions have sensible executable counterparts, it was decided
that all functions, even such ``constrained'' ones, have executable
counterparts. We essentially ``trap'' when such calls are
inappropriate. Thus, consider for example:
(defun bar (x)
(if (rationalp x)
(+ x 1)
(foo x)))
If the term (bar '3) is encountered by the ACL2 rewriter during a
proof, and if the :executable-counterpart of bar is [enable]d, then
it will be invoked to reduce this term to '4. However, if the term
(bar 'a) is encountered during a proof, then since 'a is not a
[rationalp] and since the :executable-counterpart of foo is only a
``trap,'' then this call of the :executable-counterpart of bar will
result in a ``trap.'' In that case, the rewriter will return the
term (hide (bar 'a)) so that it never has to go through this
process again. See [hide].")
(EXECUTABLE-COUNTERPART-THEORY
(THEORIES THEORY-FUNCTIONS)
"Executable counterpart rules as of logical name
Examples:
(executable-counterpart-theory :here)
(executable-counterpart-theory 'lemma3)
See [logical-name].
General Form:
(executable-counterpart-theory logical-name)
Returns the theory containing all the :[executable-counterpart]
[rune]s, whether [enable]d or not, that existed immediately after
[logical-name] was introduced. See the documentation for
[theories], [logical-name], [executable-counterpart] and
[function-theory].
You may experience a fencepost problem in deciding which logical name
to use. [Deflabel] can always be used to mark unambiguously for
future reference a particular point in the development of your
theory. The order of [events] in the vicinity of an [encapsulate]
is confusing. See [encapsulate].
This ``function'' is actually a macro that expands to a term
mentioning the single free variable [world]. When theory
expressions are evaluated by [in-theory] or the :[in-theory] hint,
[world] is bound to the current ACL2 [world].")
(EXISTS
(DEFUN-SK)
"Existential quantifier
The symbol exists (in the ACL2 package) represents existential
quantification in the context of a [defun-sk] form. See [defun-sk]
and see [forall].
See [quantifiers] for an example illustrating how the use of
recursion, rather than explicit quantification with [defun-sk], may
be preferable.")
(EXIT (GOOD-BYE)
"Quit entirely out of Lisp
Same as [good-bye].")
(EXIT-BOOT-STRAP-MODE
(HISTORY)
"The end of pre-history
Exit-boot-strap-mode is the last step in creating the ACL2 [world] in
which the user lives. It has [command] number 0. [Command]s before
it are part of the system initialization and extend all the way
back to :[min]. [Command]s after it are those of the user.
Exit-boot-strap-mode is a Common Lisp function but not an ACL2
function. It is called when every [defconst], [defun], etc., in our
source code has been processed under ACL2 and the [world] is all
but complete. exit-boot-strap-mode has only one job: to signal the
completion of the boot-strapping.")
(EXPAND (POINTERS)
"See [hints] for keyword :expand.")
(EXPLODE-ATOM
(CHARACTERS ACL2-BUILT-INS)
"Convert any [atom] into a [character-listp] that contains its printed
representation, rendering numbers in your choice of print base.
(explode-atom x print-base) prints the atom x as a list of
characters, using some [print-base-p] to decide what base to print
numbers in.
Examples:
(explode-atom 15 10) --> (#\\1 #\\5) ; 15 in decimal
(explode-atom 15 16) --> (#\\F) ; 15 in hex
(explode-atom \"foo\" 10) --> (#\\f #\\o #\\o)
(explode-atom 'acl2::foo 10) --> (#\\F #\\O #\\O) ; note: no package
See also [explode-nonnegative-integer], [str::numbers], and
[printing-to-strings].
Function: <explode-atom>
(defun
explode-atom (x print-base)
(declare (xargs :guard (and (or (acl2-numberp x)
(characterp x)
(stringp x)
(symbolp x))
(print-base-p print-base))))
(cond
((rationalp x)
(cond
((integerp x)
(cond ((< x 0)
(cons #\\-
(explode-nonnegative-integer (- x)
print-base nil)))
(t (explode-nonnegative-integer x print-base nil))))
(t
(append (explode-atom (numerator x) print-base)
(cons #\\/
(explode-nonnegative-integer (denominator x)
print-base nil))))))
((complex-rationalp x)
(list*
#\\# #\\C #\\(
(append (explode-atom (realpart x) print-base)
(cons #\\Space
(append (explode-atom (imagpart x) print-base)
'(#\\)))))))
((characterp x) (list x))
((stringp x) (coerce x 'list))
(t (coerce (symbol-name x) 'list))))")
(EXPLODE-NONNEGATIVE-INTEGER
(CHARACTERS NUMBERS ACL2-BUILT-INS)
"The list of [characters] in the radix-r form of a number
Examples:
ACL2 !>(explode-nonnegative-integer 925 10 nil)
(#9 #2 #5)
ACL2 !>(explode-nonnegative-integer 325 16 nil)
(#3 #9 #D)
For a non-negative integer n, (explode-nonnegative-integer n r nil)
is the list of [characters] in the radix-r (base-r) representation
of n.
The [guard] for explode-nonnegative-integer requires the first
argument to be a nonnegative integer and second argument to be a
valid radix for ACL2 (2, 8, 10, or 16).
See also [explode-atom], [str::numbers], and [printing-to-strings].
Function: <explode-nonnegative-integer>
(defun explode-nonnegative-integer
(n print-base ans)
(declare (xargs :guard (and (integerp n)
(>= n 0)
(print-base-p print-base))))
(cond ((or (zp n)
(not (print-base-p print-base)))
(cond ((null ans) '(#\\0)) (t ans)))
(t (explode-nonnegative-integer
(floor n print-base)
print-base
(cons (digit-to-char (mod n print-base))
ans)))))")
(EXPT
(NUMBERS ACL2-BUILT-INS)
"Exponential function
(Expt r i) is the result of raising the number r to the integer power
i.
The [guard] for (expt r i) is that r is a number and i is an integer,
and furthermore, if r is 0 then i is nonnegative. When the type
requirements of the [guard] aren't met, (expt r i) first coerces r
to a number and i to an integer.
Expt is a Common Lisp function. See any Common Lisp documentation for
more information. Note that r can be a complex number; this is
consistent with Common lisp.
Function: <expt>
(defun expt (r i)
(declare (xargs :guard (and (acl2-numberp r)
(integerp i)
(not (and (eql r 0) (< i 0))))))
(cond ((zip i) 1)
((= (fix r) 0) 0)
((> i 0) (* r (expt r (+ i -1))))
(t (* (/ r) (expt r (+ i 1))))))")
(EXTEND-PE-TABLE
(HISTORY)
"Replace [events] displayed by [history] commands
Example Form:
(extend-pe-table all-natp (all-p natp))
General Form:
(extend-pe-table event-name form)
where event-name is the name of an existing event and form is to be
displayed by [history] commands in place of the actual event that
introduced event-name.
We motivate and illustrate this utility with the following example.
Suppose you develop a macro to define the notion that each element
of a list satisfies a given predicate, as follows.
(defmacro all-p (pred)
(declare (xargs :guard (symbolp pred)))
(let ((name (intern$ (concatenate 'string \"ALL-\" (symbol-name pred))
(symbol-package-name pred))))
`(defun ,name (lst)
(if (atom lst)
t
(and (,pred lst)
(,name (cdr lst)))))))
So for example, after evaluating (all-p natp), you see the following.
ACL2 !>:pe all-natp
L 2:x(ALL-P NATP)
>L (DEFUN ALL-NATP (LST)
(IF (ATOM LST)
T
(AND (NATP LST) (ALL-NATP (CDR LST)))))
ACL2 !>
So far so good. But suppose that instead, you introduce this event
within a call of [progn], as follows.
(progn (defun f1 (x) x)
(defun f2 (x) x)
(all-p natp))
Then when we ask to see the event introducing all-natp, we will not
see any use of the macro all-p.
ACL2 !>:pe all-natp
2:x(PROGN (DEFUN F1 # ...)
(DEFUN F2 # ...)
...)
>L (DEFUN ALL-NATP (LST)
(IF (ATOM LST)
T
(AND (NATP LST) (ALL-NATP (CDR LST)))))
ACL2 !>
Perhaps we therefore prefer that [history] commands display the event
for all-natp as (all-p natp), rather than as the generated [defun]
event. Of course, in this simple example that might not be
important; but it is easy to imagine examples where a small macro
invocation generates a large, ugly primitive event that is best not
viewed by any user!
A solution is to associate the name all-natp with the form that
introduced this name, as follows.
(extend-pe-table all-natp (all-p natp))
After evaluating this form, we see the desired call of all-natp. In
essence, :[pe] and other [history] commands consider the defining
event for all-natp to be (all-p natp) rather than the actual defun
form that introduced all-natp.
ACL2 !>:pe all-natp
2 (PROGN (DEFUN F1 # ...)
(DEFUN F2 # ...)
...)
>L (ALL-P NATP)
ACL2 !>
As mentioned above, other [history] commands are sensitive to the
result of evaluating a call of extend-pe-table. For example:
ACL2 !>:pcb all-natp
2 (PROGN (DEFUN F1 # ...)
(DEFUN F2 # ...)
...)
L (DEFUN F1 (X) ...)
L (DEFUN F2 (X) ...)
L (ALL-P NATP)
ACL2 !>
Note that extend-pe-table actually associates the indicated form with
the most recent event introducing the given event name. Consider
the following example (output elided as shown).
ACL2 !>(encapsulate
()
(program)
(all-p alistp))
[[.. elided ..]]
T
ACL2 !>:pe all-alistp
4:x(ENCAPSULATE NIL ...)
>P (DEFUN ALL-ALISTP (LST)
(IF (ATOM LST)
T
(AND (ALISTP LST)
(ALL-ALISTP (CDR LST)))))
ACL2 !>(extend-pe-table all-alistp (all-p alistp))
Summary
Form: ( TABLE PE-TABLE ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
PE-TABLE
ACL2 !>:pe all-alistp
4 (ENCAPSULATE NIL ...)
>P (ALL-P ALISTP)
ACL2 !>(verify-termination all-alistp)
[[.. elided ..]]
ALL-ALISTP
ACL2 !>:pe all-alistp
L 6:x(VERIFY-TERMINATION ALL-ALISTP)
>L (DEFUN ALL-ALISTP (LST)
(IF (ATOM LST)
T
(AND (ALISTP LST)
(ALL-ALISTP (CDR LST)))))
Additional events for the logical name ALL-ALISTP:
4 (ENCAPSULATE NIL ...)
>PL (ALL-P ALISTP)
ACL2 !>(extend-pe-table all-alistp (:termination-verified (all-p alistp)))
Summary
Form: ( TABLE PE-TABLE ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
PE-TABLE
ACL2 !>:pe all-alistp
L 6 (VERIFY-TERMINATION ALL-ALISTP)
>L (:TERMINATION-VERIFIED (ALL-P ALISTP))
Additional events for the logical name ALL-ALISTP:
4 (ENCAPSULATE NIL ...)
>PL (ALL-P ALISTP)
ACL2 !>
Note that by using :[pe!], in place of :[pe], you can avoid using the
information that was provided by extend-pe-table.
ACL2 !>:pe! all-alistp
L 6 (VERIFY-TERMINATION ALL-ALISTP)
>L (DEFUN ALL-ALISTP (LST)
(IF (ATOM LST)
T
(AND (ALISTP LST)
(ALL-ALISTP (CDR LST)))))
Additional events for the logical name ALL-ALISTP:
4 (ENCAPSULATE NIL ...)
>PL (DEFUN ALL-ALISTP (LST)
(IF (ATOM LST)
T
(AND (ALISTP LST)
(ALL-ALISTP (CDR LST)))))
ACL2 !>
In the examples above we invoked extend-pe-table explicitly. It might
have been better, however, to ``bake in'' such calls by way of the
macro itself, as follows.
(defmacro all-p (&whole form pred)
(declare (xargs :guard (symbolp pred)))
(let ((name (intern$ (concatenate 'string \"ALL-\" (symbol-name pred))
(symbol-package-name pred))))
`(progn (defun ,name (lst)
(if (atom lst)
t
(and (,pred lst)
(,name (cdr lst)))))
(extend-pe-table ,name ,form))))
Then in a fresh session, after defining all-p as shown immediately
above, we can obtain the following (edited) log.
ACL2 !>(all-p natp)
[[.. elided ..]]
ACL2 !>:pe all-natp
2:x(ALL-P NATP)
ACL2 !>
We close with two remarks. First, note that the indicated event must
have already been defined at the time extend-pe-table is invoked.
Second --- in case an advanced user wishes to extend directly the
underlying table, pe-table --- we mention that this table
associates each key, an event name, with an association list that
maps so-called absolute event numbers with events to display. So
for example, we can remove all custom printing of events for the
name all-natp as follows.
(table pe-table 'all-natp nil)")
(EXTENDED-METAFUNCTIONS
(META)
"State and context sensitive metafunctions
General Form of an Extended :Meta theorem:
(implies (and (pseudo-termp x) ; this hyp is optional
(alistp a) ; this hyp is optional
(ev (hyp-fn x mfc state) a) ; this hyp is optional
; meta-extract hyps may also be included (see below)
)
(equiv (ev x a)
(ev (fn x mfc state) a)))
where the restrictions are as described in the [documentation] for
[meta] where state is literally the symbol STATE, and x, a, mfc,
and state are distinct variable symbols. A :meta theorem of the
above form installs fn as a metatheoretic simplifier with
hypothesis function hyp-fn, exactly as for vanilla metafunctions.
The only difference is that when the metafunctions are applied,
some contextual information is passed in via the mfc argument and
the ACL2 [state] is made available.
See [meta] for a discussion of vanilla flavored metafunctions. This
documentation assumes you are familiar with the simpler situation,
in particular, how to define a vanilla flavored metafunction, fn,
and its associated hypothesis metafunction, hyp-fn, and how to
state and prove metatheorems installing such functions. Defining
extended metafunctions requires that you also be familiar with many
ACL2 implementation details. This documentation is sketchy on these
details; see the ACL2 source code or email the [ACL2-help] list if
you need more help.
Additional hypotheses are supported, called ``meta-extract
hypotheses'', that allow metafunctions to depend on the validity of
certain terms extracted from the context or the logical [world].
These hypotheses provide an even more advanced form of metatheorem
so we explain them elsewhere; see [meta-extract].
The metafunction context, mfc, is a list containing many different
data structures used by various internal ACL2 functions. We do not
document the form of mfc. Your extended metafunction should just
take mfc as its second formal and pass it into the functions
mentioned below. The ACL2 state is well-documented (see [state]).
Below we present expressions below that can be useful in defining
extended metafunctions. Some of these expressions involve keyword
arguments, :forcep and :ttree, which are optional and in most cases
are fine to omit, and which we explain after we present the useful
expressions.
(mfc-clause mfc): returns the current goal, in clausal form. A clause
is a list of ACL2 terms, implicitly denoting the disjunction of the
listed terms. The clause returned by mfc-clause is the clausal form
of the translation (see [trans]) of the goal or subgoal on which
the rewriter is working. When a metafunction calls mfc-clause, the
term being rewritten by the metafunction either occurs somewhere in
this clause or, perhaps more commonly, is being rewritten on behalf
of some lemma to which the rewriter has backchained while trying to
rewrite a term in the clause.
(mfc-ancestors mfc): returns an alist whose keys are the negations of
the backchaining hypotheses being pursued. In particular, (null
(mfc-ancestors mfc)) will be true exactly when rewriting is on part
of the current goal. Exception: An element of this alist whose key
is of the form (:binding-hyp hyp unify-subst) indicates that hyp
has been encountered as a hypothesis of the form (equal var term)
or (equiv var (double-rewrite-term)), in each case binding variable
var to the result of rewriting term under unify-subst.
(mfc-rdepth mfc): returns the remaining stack depth for calls of the
rewriter (by default, *default-rewrite-stack-limit* at the top
level; see [rewrite-stack-limit]). When this is 0, no further calls
of the rewriter can be made without error.
(mfc-type-alist mfc): returns the type-alist governing the occurrence
of the term, x, being rewritten by the metafunction. A type-alist
is an association list, each element of which is of the form (term
ts . ttree). Such an element means that the term term has the
[type-set] ts; see [type-alist]. The ttree component is probably
irrelevant here. All the terms in the type-alist are in translated
form (see [trans]). The ts are numbers denoting finite Boolean
combinations of ACL2's primitive types (see [type-set]). The
type-alist includes not only information gleaned from the
conditions governing the term being rewritten but also that gleaned
from forward chaining from the (negations of the) other literals in
the clause returned by mfc-clause.
(mfc-unify-subst mfc): returns nil except when evaluating a [syntaxp]
or [bind-free] hypothesis, in which case, returns the unifying
substitution present at the start of that evaluation.
(mfc-world mfc): returns the ACL2 logical [world].
(mfc-ts term mfc state :forcep forcep :ttreep ttreep): returns the
type-set of term in the current context; see [type-set].
(mfc-rw term obj equiv-info mfc state): returns the result of
rewriting term in the current context, mfc, with objective obj and
the equivalence relation described by equiv-info. Obj should be t,
nil, or ?, and describes your objective: try to show that term is
true, false, or anything. Equiv-info is either nil, t, a function
symbol fn naming a known equivalence relation, or a list of
congruence rules. Nil means return a term that is equal to term. T
means return a term that is propositionally equivalent (i.e., in
the iff sense) to term, while fn means return a term fn-equivalent
to term. The final case, which is intended only for advanced users,
allows the specification of generated equivalence relations, as
supplied to the geneqv argument of rewrite. Generally, if you wish
to establish that term is true in the current context, use the
idiom
(equal (mfc-rw term t t mfc state) *t*)
The constant *t* is set to the internal form of the constant term t,
i.e., 't.
(mfc-rw+ term alist obj equiv-info mfc state): if alist is nil then
this is equivalent to (mfc-rw term obj equiv-info mfc state).
However, the former takes an argument, alist, that binds variables
to terms, and returns the result of rewriting term under that
alist, where this rewriting is as described for mfc-rw above. The
function mfc-rw+ can be more efficient than mfc-rw, because the
terms in the binding alist have generally already been rewritten,
and it can be inefficient to rewrite them again. For example,
consider a rewrite rule of the following form.
(implies (and ...
(syntaxp (... (mfc-rw `(bar ,x) ...) ...))
...)
(equal (... x ...) ...))
Here, x is bound in the conclusion to the result of rewriting some
term, say, tm. Then the above call of mfc-rw will rewrite tm, which
is probably unnecessary. So a preferable form of the rule above may
be as follows, so that tm is not further rewritten by mfc-rw+.
(implies (and ...
(syntaxp (... (mfc-rw+ '(bar v) `((v . ,x)) ...) ...))
...)
(equal (... x ...) ...))
However, you may find that the additional rewriting done by mfc-rw is
useful in some cases.
(mfc-ap term mfc state): returns t or nil according to whether linear
arithmetic can determine that term is false. To the cognoscenti:
returns the contradiction flag produced by linearizing term and
adding it to the linear-pot-lst.
(mfc-relieve-hyp hyp alist rune target bkptr mfc state): returns t or
nil according to whether the indicated hypothesis term, hyp, can be
relieved (proved) under the giving variable bindings, alist. Note
that this function returns nil if hyp has free variables (see
[free-variables]). Here, hyp is the hypothesis of the indicated
[rune] at (one-based) position bkptr, and target is an instantiated
term to which rune is being applied. Note that no indication is
returned for whether any assumptions have been generated by [force]
or [case-split]. (If you need such a feature, feel free to request
it of the ACL2 implementors.)
We explain the :forcep and :ttreep keyword arguments provided in some
expressions, as promised above. Their defaults are :same and nil,
respectively. A value of :same for :forcep means that forcing will
be allowed if and only if it is allowed in the current rewriting
environment; see [force]. A value of t or nil for :forcep overrides
this default and allows or disallows forcing, respectively. By
default these functions return a single value, val, but if :ttreep
is t then they return (mv val ttree), where ttree is the tag-tree
(see [ttree]) returned by the indicated operation, with an input
tag-tree of nil).
During the execution of a metafunction by the theorem prover, the
expressions above compute the results specified. Typically, you
should imagine that there are no axioms about the mfc- function
symbols: treat them as uninterpreted function symbols. There is an
advanced feature, meta-extract hypotheses, that can avoid this
logical weakness in some cases when proving :[meta] rules; see
[meta-extract]. But we assume for the rest of the present
[documentation] topic that you do not use meta-extract hypotheses.
Thus, in the proof of the correctness of a metafunction, no
information is available about the results of these functions: you
should use these functions for heuristic purposes only.
For example, your metafunction may use these functions to decide
whether to perform a given transformation, but the transformation
must be sound regardless of the value that your metafunction
returns. We illustrate this below. It is sometimes possible to use
the hypothesis metafunction, hyp-fn, to generate a sufficient
hypothesis to justify the transformation. The generated hypothesis
might have already been ``proved'' internally by your use of mfc-ts
or mfc-rw, but the system will have to prove it ``officially'' by
relieving it. We illustrate this below also.
We conclude with a script that defines, verifies, and uses several
extended metafunctions. This script is based on one provided by
Robert Krug, who was instrumental in the development of this style
of metafunction and whose help we gratefully acknowledge.
; Here is an example. I will define (foo i j) simply to be (+ i j).
; But I will keep its definition disabled so the theorem prover
; doesn't know that. Then I will define an extended metafunction
; that reduces (foo i (- i)) to 0 provided i has integer type and the
; expression (< 10 i) occurs as a hypothesis in the clause.
; Note that (foo i (- i)) is 0 in any case.
(defun foo (i j) (+ i j))
(defevaluator eva eva-lst ((foo i j)
(unary-- i)
; I won't need these two cases until the last example below, but I
; include them now.
(if x y z)
(integerp x)))
(set-state-ok t)
(defun metafn (x mfc state)
(cond
((and (consp x)
(equal (car x) 'foo)
(equal (caddr x) (list 'unary-- (cadr x))))
; So x is of the form (foo i (- i)). Now I want to check some other
; conditions.
(cond ((and (ts-subsetp (mfc-ts (cadr x) mfc state)
*ts-integer*)
(member-equal `(NOT (< '10 ,(cadr x)))
(mfc-clause mfc)))
(quote (quote 0)))
(t x)))
(t x)))
(defthm metafn-correct
(equal (eva x a) (eva (metafn x mfc state) a))
:rule-classes ((:meta :trigger-fns (foo))))
(in-theory (disable foo))
; The following will fail because the metafunction won't fire.
; We don't know enough about i.
(thm (equal (foo i (- i)) 0))
; Same here.
(thm (implies (and (integerp i) (< 0 i)) (equal (foo i (- i)) 0)))
; But this will work.
(thm (implies (and (integerp i) (< 10 i))
(equal (foo i (- i)) 0)))
; This won't, because the metafunction looks for (< 10 i) literally,
; not just something that implies it.
(thm (implies (and (integerp i) (< 11 i))
(equal (foo i (- i)) 0)))
; Now I will undo the defun of metafn and repeat the exercise, but
; this time check the weaker condition that (< 10 i) is provable
; (by rewriting it) rather than explicitly present.
(ubt 'metafn)
(defun metafn (x mfc state)
(cond
((and (consp x)
(equal (car x) 'foo)
(equal (caddr x) (list 'unary-- (cadr x))))
(cond ((and (ts-subsetp (mfc-ts (cadr x) mfc state)
*ts-integer*)
(equal (mfc-rw `(< '10 ,(cadr x)) t t mfc state)
*t*))
; The mfc-rw above rewrites (< 10 i) with objective t and iffp t. The
; objective means the theorem prover will try to establish it. The
; iffp means the theorem prover can rewrite maintaining propositional
; equivalence instead of strict equality.
(quote (quote 0)))
(t x)))
(t x)))
(defthm metafn-correct
(equal (eva x a) (eva (metafn x mfc state) a))
:rule-classes ((:meta :trigger-fns (foo))))
(in-theory (disable foo))
; Now it will prove both:
(thm (implies (and (integerp i) (< 10 i))
(equal (foo i (- i)) 0)))
(thm (implies (and (integerp i) (< 11 i))
(equal (foo i (- i)) 0)))
; Now I undo the defun of metafn and change the problem entirely.
; This time I will rewrite (integerp (foo i j)) to t. Note that
; this is true if i and j are integers. I can check this
; internally, but have to generate a hyp-fn to make it official.
(ubt 'metafn)
(defun metafn (x mfc state)
(cond
((and (consp x)
(equal (car x) 'integerp)
(consp (cadr x))
(equal (car (cadr x)) 'foo))
; So x is (integerp (foo i j)). Now check that i and j are
; ``probably'' integers.
(cond ((and (ts-subsetp (mfc-ts (cadr (cadr x)) mfc state)
*ts-integer*)
(ts-subsetp (mfc-ts (caddr (cadr x)) mfc state)
*ts-integer*))
*t*)
(t x)))
(t x)))
; To justify this transformation, I generate the appropriate hyps.
(defun hyp-fn (x mfc state)
(declare (ignore mfc state))
; The hyp-fn is run only if the metafn produces an answer different
; from its input. Thus, we know at execution time that x is of the
; form (integerp (foo i j)) and we know that metafn rewrote
; (integerp i) and (integerp j) both to t. So we just produce their
; conjunction. Note that we must produce a translated term; we
; cannot use the macro AND and must quote constants! Sometimes you
; must do tests in the hyp-fn to figure out which case the metafn
; produced, but not in this example.
`(if (integerp ,(cadr (cadr x)))
(integerp ,(caddr (cadr x)))
'nil))
(defthm metafn-correct
(implies (eva (hyp-fn x mfc state) a)
(equal (eva x a) (eva (metafn x mfc state) a)))
:rule-classes ((:meta :trigger-fns (integerp))))
(in-theory (disable foo))
; This will not be proved.
(thm (implies (and (rationalp x) (integerp i)) (integerp (foo i j))))
; But this will be.
(thm (implies (and (rationalp x)
(integerp i)
(integerp j))
(integerp (foo i j))))")
(EXTERNAL-FORMAT (POINTERS)
"See [character-encoding].")
(EXTRA-INFO
(GUARD)
"Sources of measure or guard proof obligations
(Extra-info x y) always returns t by definition. See [guard-debug]
and see [measure-debug] for a discussion of this function, which is
useful for debugging failures from attempts to prove measure
conjectures or to verify [guard]s.")
(F-GET-GLOBAL
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Get the value of a global variable in [state]
Examples:
(+ (f-get-global 'y state) 1)
(f-put-global 'a
(aset1 'ascii-map-array
(f-get-global 'a state)
66
'Upper-case-B)
state)
General Form:
(f-get-global 'symbol state)
where symbol is any symbol to which you have [assign]ed a global
value.
The macro [@] is closely related to f-get-global: (@ var)
macroexpands to (f-get-global 'var state).
The macro [f-put-global] makes it convenient to set the value of a
symbol. The :[ubt] operation has no effect on the global-table of
[state]. Thus, you may use these globals to hang onto useful data
structures even though you may undo back past where you computed
and saved them.")
(F-PUT-GLOBAL
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Assign to a global variable in [state]
Examples:
(f-put-global 'x (expt 2 10) state)
(f-put-global 'a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B) state)
General Form:
(f-put-global (quote symbol) term state)
where symbol is any symbol (with certain enforced exclusions to avoid
overwriting ACL2 system ``globals'') and term is any ACL2 term that
could be evaluated at the top-level. F-put-global evaluates the
term, stores the result as the value of the given symbol in the
global-table of [state], and returns the new state. (Note: the
actual implementation of the storage of this value is much more
efficient than this discussion of the logic might suggest.)
The macro [assign] is closely related to f-put-global: (assign var
val) macroexpands to (f-put-global 'var val state).
The macros [@] and [f-get-global] give convenient access to the value
of such globals. The :[ubt] operation has no effect on the
global-table of [state]. Thus, you may use these globals to hang
onto useful data structures even though you may undo back past
where you computed and saved them.")
(FAILED-FORCING
(FORCE DEBUGGING)
"How to deal with a proof [failure] in a forcing round
See [forcing-round] for a background discussion of the notion of
forcing rounds. When a proof fails during a forcing round it means
that the ``gist'' of the proof succeeded but some ``technical
detail'' failed. The first question you must ask yourself is
whether the [force]d goals are indeed theorems. We discuss the
possibilities below.
If you believe the [force]d goals are theorems, you should follow the
usual methodology for ``fixing'' failed ACL2 proofs, e.g., the
identification of key lemmas and their timely and proper use as
rules. See [failure], see [gag-mode], and see [proof-tree].
The rules designed for the goals of forcing rounds are often just
what is needed to prove the [force]d hypothesis at the time it is
[force]d. Thus, you may find that when the system has been
``taught'' how to prove the goals of the forcing round no forcing
round is needed. This is intended as a feature to help structure
the discovery of the necessary rules.
If a hint must be provided to prove a goal in a forcing round, the
appropriate ``goal specifier'' (the string used to identify the
goal to which the hint is to be applied) is just the text printed
on the line above the formula, e.g., \"[1]Subgoal *1/3''\". See
[goal-spec].
If you solve a forcing problem by giving explicit [hints] for the
goals of forcing rounds, you might consider whether you could avoid
forcing the assumption in the first place by giving those [hints]
in the appropriate places of the main proof. This is one reason
that we print out the origins of each [force]d assumption. An
argument against this style, however, is that an assumption might
be [force]d in hundreds of places in the main goal and proved only
once in the forcing round, so that by delaying the proof you
actually save time.
We now turn to the possibility that some goal in the forcing round is
not a theorem.
There are two possibilities to consider. The first is that the
original theorem has insufficient hypotheses to ensure that all the
[force]d hypotheses are in fact always true. The ``fix'' in this
case is to amend the original conjecture so that it has adequate
hypotheses.
A more difficult situation can arise and that is when the conjecture
has sufficient hypotheses but they are not present in the forcing
round goal. This can be caused by what we call ``premature''
forcing.
Because ACL2 rewrites from the inside out, it is possible that it
will [force] hypotheses while the context is insufficient to
establish them. Consider trying to prove (p x (foo x)). We first
rewrite the formula in an empty context, i.e., assuming nothing.
Thus, we rewrite (foo x) in an empty context. If rewriting (foo x)
[force]s anything, that [force]d assumption will have to be proved
in an empty context. This will likely be impossible.
On the other hand, suppose we did not attack (foo x) until after we
had expanded p. We might find that the value of its second
argument, (foo x), is relevant only in some cases and in those
cases we might be able to establish the hypotheses [force]d by (foo
x). Our premature forcing is thus seen to be a consequence of our
``over eager'' rewriting.
Here, just for concreteness, is an example you can try. In this
example, (foo x) rewrites to x but has a [force]d hypothesis of
(rationalp x). P does a case split on that very hypothesis and uses
its second argument only when x is known to be rational. Thus, the
hypothesis for the (foo x) rewrite is satisfied. On the false
branch of its case split, p simplies to (p1 x) which can be proved
under the assumption that x is not rational.
(defun p1 (x) (not (rationalp x)))
(defun p (x y)(if (rationalp x) (equal x y) (p1 x)))
(defun foo (x) x)
(defthm foo-rewrite (implies (force (rationalp x)) (equal (foo x) x)))
(in-theory (disable foo))
The attempt then to do (thm (p x (foo x))) [force]s the unprovable
goal (rationalp x).
Since all ``formulas'' are presented to the theorem prover as single
terms with no hypotheses (e.g., since [implies] is a function),
this problem would occur routinely were it not for the fact that
the theorem prover expands certain ``simple'' definitions
immediately without doing anything that can cause a hypothesis to
be [force]d. See [simple]. This does not solve the problem, since
it is possible to hide the propositional structure arbitrarily
deeply. For example, one could define p, above, recursively so that
the test that x is rational and the subsequent first ``real'' use
of y occurred arbitrarily deeply.
Therefore, the problem remains: what do you do if an impossible goal
is [force]d and yet you know that the original conjecture was
adequately protected by hypotheses?
One alternative is to disable forcing entirely. See
[disable-forcing]. Another is to [disable] the rule that caused the
[force].
A third alternative is to prove that the negation of the main goal
implies the [force]d hypothesis. For example,
(defthm not-p-implies-rationalp
(implies (not (p x (foo x))) (rationalp x))
:rule-classes nil)
Observe that we make no rules from this formula. Instead, we merely
:use it in the subgoal where we must establish (rationalp x).
(thm (p x (foo x))
:hints ((\"Goal\" :use not-p-implies-rationalp)))
When we said, above, that (p x (foo x)) is first rewritten in an
empty context we were misrepresenting the situation slightly. When
we rewrite a literal we know what literal we are rewriting and we
implicitly assume it false. This assumption is ``dangerous'' in
that it can lead us to simplify our goal to nil and give up --- we
have even seen people make the mistake of assuming the negation of
what they wished to prove and then via a very complicated series of
transformations convince themselves that the formula is false.
Because of this ``tail biting'' we make very weak use of the
negation of our goal. But the use we make of it is sufficient to
establish the [force]d hypothesis above.
A fourth alternative is to weaken your desired theorem so as to make
explicit the required hypotheses, e.g., to prove
(defthm rationalp-implies-main
(implies (rationalp x) (p x (foo x)))
:rule-classes nil)
This of course is unsatisfying because it is not what you originally
intended. But all is not lost. You can now prove your main theorem
from this one, letting the [implies] here provide the necessary
case split.
(thm (p x (foo x))
:hints ((\"Goal\" :use rationalp-implies-main)))")
(FAILURE
(DEBUGGING)
"How to deal with a proof failure
When ACL2 gives up it does not mean that the submitted conjecture is
invalid, even if the last formula ACL2 printed in its proof attempt
is manifestly false. Since ACL2 sometimes [generalize]s the goal
being proved, it is possible it adopted an invalid subgoal as a
legitimate (but doomed) strategy for proving a valid goal.
Nevertheless, conjectures submitted to ACL2 are often invalid and
the proof attempt often leads the careful reader to the realization
that a hypothesis has been omitted or that some special case has
been forgotten. It is good practice to ask yourself, when you see a
proof attempt fail, whether the conjecture submitted is actually a
theorem.
If you think the conjecture is a theorem, then you must figure out
from ACL2's output what you know that ACL2 doesn't about the
functions in the conjecture and how to impart that knowledge to
ACL2 in the form of rules. The ``key checkpoint'' information
printed at the end of the summary provides a fine place to start.
See [the-method] for a general discussion of how to prove theorems
with ACL2, and see [introduction-to-the-theorem-prover] for a more
detailed tutorial. Also see [set-gag-mode] for discussion of key
checkpoints and an abbreviated output mode that focuses attention
on them. You may find it most useful to start by focusing on key
checkpoints that are not under a proof by induction, if any, both
because these are more likely to suggest useful lemmas and because
they are more likely to be theorems; for example, generalization
may have occurred before a proof by induction has begun. If you
need more information than is provided by the key checkpoints ---
although this should rarely be necessary --- then you can look at
the full proof, perhaps with the aid of certain utilities: see
[proof-tree], see [set-gag-mode], and see [set-saved-output].
For information on a tool to help debug failures of [encapsulate] and
[progn] events, as well as [certify-book] failures, see
[redo-flat].
Again, see [the-method] for a general discussion of how to prove
theorems with ACL2, and see [introduction-to-the-theorem-prover]
for a more detailed tutorial. See also the book ``Computer-Aided
Reasoning: An Approach'' (Kaufmann, Manolios, Moore), as well as
the discussion of how to read Nqthm proofs and how to use Nqthm
rules in ``A Computational Logic Handbook'' by Boyer and Moore
(Academic Press, 1988).
If the failure occurred during a forcing round, see [failed-forcing].")
(FAKE-RUNE (POINTERS) "See [rune].")
(FANCY-STRING-READER
(READER)
"A friendly syntax for strings literals that have backslashes and
quotes.
Examples:
ACL2 !> #{\"\"\"Hello, World!\"\"\"}
\"Hello, World!\"
ACL2 !> #{\"\"\"<img src=\"hello.png\"/>\"\"\"}
\"<img src=\\\"hello.png\\\"/>\"
ACL2 !> #{\"\"\"C:\\ACL2\\axioms.lisp\"\"\"}
\"C:\\\\ACL2\\\\axioms.lisp\"
String literals in ACL2 and Common Lisp source code files are usually
written as text strings within quote marks. For instance, the
5-character string whose contents are Hello is normally written as
\"Hello\".
Usually this syntax is fine, but things can get tricky when you want
to write a string whose contents include \" marks. For example, if
you wanted to write down a string whose contents were:
<img src=\"hello.png\"/>
then you would need to escape the quote marks within it using
backslash characters, e.g., as follows:
\"<img src=\\\"hello.png\\\"/>\"
But using \\ as a special character means we also need a special way
to write backslashes. For instance, if we want to write a string
literal whose contents are:
C:\\ACL2\\axioms.lisp
Then we would need to write something a string literal such as:
\"C:\\\\ACL2\\\\axioms.lisp\"
In certain cases, such as when writing long [documentation] strings,
the extra escaping can be tedious and error-prone.
To simplify this, ACL2 provides an alternate #{\"\"\"...\"\"\"} syntax for
string literals. This syntax has no special characters, so nothing
needs to be escaped. The end of the string is recognized by the
unusual character sequence \"\"\"}.
Of course, a string that needs to contain the sequence \"\"\"} cannot be
represented using this fancy string literal syntax, but in practice
that's rarely ever a problem.")
(FAST-ALIST (POINTERS)
"See [fast-alists].")
(FAST-ALIST-CLEAN
(FAST-ALISTS ACL2-BUILT-INS)
"(fast-alist-clean alist) can be used to eliminate \"shadowed pairs\"
from a fast alist.
This [documentation] topic assumes familiarity with fast alists; see
[fast-alists]. See [fast-alist-clean!], [fast-alist-fork], and
[fast-alist-fork!] for related utilities.
Logically, (fast-alist-clean alist) is defined as follows:
Function: <fast-alist-clean>
(defun fast-alist-clean (alist)
(declare (xargs :guard t))
(fast-alist-fork alist
(if (consp alist)
(cdr (last alist))
alist)))
The result is thus a corresponding fast alist, with the order
reversed and with atoms and shadowed pairs removed, as per the
definition above; see [fast-alist-fork] for details. Moreover, if
alist is not a fast alist, then (fast-alist-clean alist) is
executed in raw Lisp by calling fast-alist-fork as indicated above.
However, if alist is a fast alist, then a special definition under
the hood provides a different handling of associated hash tables.
After running (fast-alist-clean alist) to obtain a result,
cleaned-alist, the hash table that had been associated with alist
will now be associated with cleaned-alist instead. This saves the
expense of creating a new hash table, but there is still the
expense of copying the alist, as for [fast-alist-fork]. However,
unlike fast-alist-fork, there is no need to free the input alist.
Note that the final cdr is preserved, so that the name is preserved
for use by [fast-alist-summary] (also see [hons-acons]).")
(FAST-ALIST-CLEAN!
(FAST-ALISTS ACL2-BUILT-INS)
"(fast-alist-clean! alist) is an alternative to [fast-alist-clean]
that produces a [normed] result.
Logically this function is just fast-alist-clean; we leave it enabled
and would think it odd to ever prove a theorem about it.
Under the hood, this is the same as fast-alist-clean except that it
uses something like [hons-acons!] instead of [hons-acons]. You
generally should not use this function unless you really know what
you're doing and understand the drawbacks discussed in
[hons-acons!].")
(FAST-ALIST-FORK
(FAST-ALISTS ACL2-BUILT-INS)
"(fast-alist-fork alist ans) can be used to eliminate \"shadowed pairs\"
from an alist or to copy [fast-alists].
This [documentation] topic assumes familiarity with fast alists; see
[fast-alists]. See [fast-alist-fork!], [fast-alist-clean], and
[fast-alist-clean!] for related utilities.
Logically, (fast-alist-fork alist ans) is defined as follows:
Function: <fast-alist-fork>
(defun fast-alist-fork (alist ans)
(declare (xargs :guard t))
(cond ((atom alist) ans)
((atom (car alist))
(fast-alist-fork (cdr alist) ans))
((hons-assoc-equal (car (car alist)) ans)
(fast-alist-fork (cdr alist) ans))
(t (fast-alist-fork (cdr alist)
(cons (car alist) ans)))))
The alist argument need not be a fast alist.
Typically ans is set to nil or some other atom. In this case,
shrinking produces a new, fast alist which is like alist except
that (1) any \"malformed,\" atomic entries have been removed, (2) all
\"shadowed pairs\" have been removed, and (3) incidentally, the
surviving elements have been reversed. This can be useful as a way
to clean up any unnecessary bindings in alist, or as a way to
obtain a \"deep copy\" of a fast alist that can extended
independently from the original while maintaining discipline.
Note that fast-alist-fork is potentially expensive, for the following
two reasons.
* The alist is copied, dropping any shadowed pairs. This process will
require a hash table lookup for each entry in the alist; and it
will require creating a new alist, which uses additional
memory.
* Unless ans is a fast alist that is stolen (see below), a new hash
table is created, which uses additional memory. This hash table
is populated in time that is linear in the number of unique
keys in the alist.
When ans is not an atom, good discipline requires that it is a fast
alist. In this case, fast-alist-fork steals the hash table for ans
and extends it with all of the bindings in alist that are not in
ans. From the perspective of [hons-assoc-equal], you can think of
the resulting alist as being basically similar to (append ans
alist), but in a different order.
Note that when ans is not a fast alist (e.g., ans is an atom) then
such stealing does not take place.
A common idiom is to replace an alist by the result of shrinking it,
in which case it is best to free the input alist, for example as
follows.
(let ((alist (fast-alist-free-on-exit alist
(fast-alist-fork alist nil))))
...)
See [fast-alist-free-on-exit] and see [fast-alist-free].
Subtopics
[Hons-shrink-alist]
Deprecated feature")
(FAST-ALIST-FORK!
(FAST-ALISTS ACL2-BUILT-INS)
"(fast-alist-fork! alist ans) is an alternative to [fast-alist-fork]
that produces a [normed] result.
Logically this function is just fast-alist-fork; we leave it enabled
and would think it odd to ever prove a theorem about it.
Under the hood, this is the same as fast-alist-fork except that it
uses something like [hons-acons!] instead of [hons-acons]. You
generally should not use this function unless you really know what
you're doing and understand the drawbacks discussed in
[hons-acons!].
Subtopics
[Hons-shrink-alist!]
Deprecated feature")
(FAST-ALIST-FREE
(FAST-ALISTS ACL2-BUILT-INS)
"(fast-alist-free alist) throws away the hash table associated with a
fast alist.
Logically, this function is the identity; we leave it enabled and
would think it odd to ever prove a theorem about it.
Under the hood, fast-alist-free removes the hash table associated
with this alist, if one exists. This effectively converts the alist
into an ordinary alist.
Also see [fast-alist-free-on-exit].
Because there is no automatic mechanism for freeing the hash tables
used in fast alists, to avoid memory leaks you should manually free
any alists that will no longer be used. You may find
[fast-alist-summary] useful in tracking down alists that were not
properly freed.
It is safe to call fast-alist-free on any argument, including fast
alists that have already been freed and objects which are not
alists at all.
Function: <fast-alist-free>
(defun fast-alist-free (alist)
(declare (xargs :guard t))
alist)
Subtopics
[Flush-hons-get-hash-table-link]
Deprecated feature")
(FAST-ALIST-FREE-ON-EXIT
(FAST-ALISTS ACL2-BUILT-INS)
"Free a fast alist after the completion of some form.
Logically, (fast-alist-free-on-exit alist form) is the identity and
returns form. Also see [fast-alist-free].
Under the hood, this essentially expands to:
(prog1 form
(fast-alist-free alist))
In other words, alist is not freed immediately, but instead remains a
fast alist until the form completes. This may be useful when you
are writing code that uses a fast alist but has many return points.
See also the macro fast-alists-free-on-exit defined in the community
book \"books/centaur/misc/hons-extra.lisp\", which can be used to
free several alists.
The community book \"books/centaur/misc/hons-extra.lisp\" extends the
[b*] macro with the free-on-exit pattern binder. That is, after
executing (include-book \"centaur/misc/hons-extra.lisp\" :dir
:system), the form
(b* (...
((free-on-exit a b c))
...)
...)
causes a, b, and c to be freed when the b* completes, but they remain
fast alists until then.")
(FAST-ALIST-LEN
(FAST-ALISTS ACL2-BUILT-INS)
"(fast-alist-len alist) counts the number of unique keys in a fast
alist.
Logically this function counts how many elements would remain in the
alist were we to shrink it with [fast-alist-fork].
Good discipline requires that the alist is a fast alist. Under the
hood, when the alist is a fast alist we can simply call the
underlying Common Lisp function hash-table-count on the associated
hash table, which is very fast and doesn't require us to actually
shrink the alist.
Function: <fast-alist-len>
(defun fast-alist-len (alist)
(declare (xargs :guard t))
(len (fast-alist-fork alist nil)))")
(FAST-ALIST-SUMMARY
(FAST-ALISTS ACL2-BUILT-INS)
"(fast-alist-summary) prints some basic statistics about any current
fast alists.
Logically, fast-alist-summary just returns nil; we leave it enabled
and would think it odd to ever prove a theorem about it.
Under the hood, this function gathers and prints some basic
statistics about the current fast alists. It may be useful for
identifying fast alists that should have been freed with
[fast-alist-free].
Function: <fast-alist-summary>
(defun fast-alist-summary
nil (declare (xargs :guard t))
nil)")
(FAST-ALISTS
(ALISTS PROGRAMMING HONS-AND-MEMOIZATION)
"Alists with hidden hash tables for faster execution
The implementation of fast alists is, in many ways, similar to that
of ACL2 arrays. Logically, [hons-acons] is just like acons, and
[hons-get] is similar to [assoc-equal]. But under the hood, hash
tables are associated with these alists, and, when a certain
discipline is followed, these functions execute with hash table
speeds.
What is this discipline? Each hons-acons operation \"steals\" the hash
table associated with the alist that is being extended. Because of
this, one must be very conscious of which object is the most recent
extension of an alist and use that extension exclusively.
The only penalty for a failure to keep track of the most recent
extension is a loss of execution speed, not of correctness, and
perhaps the annoyance of some [slow-alist-warning]s.
Maintaining discipline may require careful passing of a fast alist up
and down through function calls, as with any single threaded object
in an applicative setting, but there is no syntactic enforcement
that insists you only use the most recent extension of an alist as
there is for single threaded objects ([stobj]s). Also, even with
perfectly proper code, discipline can sometimes be lost due to user
interrupts and aborts.
Performance Notes
See [hons-acons] for how the final [cdr] of a fast alist can be used
as a size hint or as a name for reports printed by calling
[fast-alist-summary].
The keys of fast alists are always [normed]. Why? In Common Lisp,
equal-based hashing is relatively slow, so to allow the use of
eql-based hash tables, [hons-acons] and [hons-get] always
[hons-copy] the keys involved.
Since alist keys are frequently atoms, this norming activity may
often be so fast that you do not need to think about it. But if you
are going to use large structures as the keys for your fast alist,
this overhead can be significant, and you may want to ensure that
your keys are normed ahead of time.
There is no automatic mechanism for reclaiming the hash tables that
are associated with alists. Because of this, to avoid memory leaks,
you should call [fast-alist-free] to remove the hash table
associated with alists that will no longer be used.
Subtopics
[Cons-subtrees]
Build a fast alist whose keys are the subtrees of X
[Fast-alist-clean]
([fast-alist-clean] alist) can be used to eliminate \"shadowed pairs\"
from a fast alist.
[Fast-alist-clean!]
([fast-alist-clean!] alist) is an alternative to [fast-alist-clean]
that produces a [normed] result.
[Fast-alist-fork]
([fast-alist-fork] alist ans) can be used to eliminate \"shadowed
pairs\" from an alist or to copy [fast-alists].
[Fast-alist-fork!]
([fast-alist-fork!] alist ans) is an alternative to
[fast-alist-fork] that produces a [normed] result.
[Fast-alist-free]
([fast-alist-free] alist) throws away the hash table associated with
a fast alist.
[Fast-alist-free-on-exit]
Free a fast alist after the completion of some form.
[Fast-alist-len]
([fast-alist-len] alist) counts the number of unique keys in a fast
alist.
[Fast-alist-summary]
([fast-alist-summary]) prints some basic statistics about any
current fast alists.
[Hons-acons]
([hons-acons] key val alist) is the main way to create or extend
[fast-alists].
[Hons-acons!]
([hons-acons!] key val alist) is an alternative to [hons-acons] that
produces [normed], fast alists.
[Hons-assoc-equal]
([hons-assoc-equal] key alist) is not fast; it serves as the logical
definition for [hons-get].
[Hons-get]
([hons-get] key alist) is the efficient lookup operation for
[fast-alists].
[Make-fast-alist]
([make-fast-alist] alist) creates a fast-alist from the input alist,
returning alist itself or, in some cases, a new object equal to
it.
[Slow-alist-warning]
Warnings issued when [fast-alists] are used inefficiently
[With-fast-alist]
([with-fast-alist] name form) causes name to be a fast alist for the
execution of form.")
(FC-REPORT
(FORWARD-CHAINING-REPORTS)
"To report on the forward chaining activity in the most recent proof
Example: (fc-report 15)
General Form: (fc-report k)
where k is the number of some forward chaining report printed in the
most recent event.
See [forward-chaining-reports] for details.")
(FIFTH
(NTH ACL2-BUILT-INS)
"Fifth member of the list
See any Common Lisp documentation for details.")
(FILE-READING-EXAMPLE
(TUTORIAL5-MISCELLANEOUS-EXAMPLES)
"Example of reading files in ACL2
This example illustrates the use of ACL2's [io] primitives to read
the forms in a file. See [io].
This example provides a solution to the following problem. Let's say
that you have a file that contains s-expressions. Suppose that you
want to build a list by starting with nil, and updating it
``appropriately'' upon encountering each successive s-expression in
the file. That is, suppose that you have written a function
update-list such that (update-list obj current-list) returns the
list obtained by ``updating'' current-list with the next object,
obj, encountered in the file. The top-level function for processing
such a file, returning the final list, could be defined as follows.
Notice that because it opens a channel to the given file, this
function modifies [state] and hence must return [state]. Thus it
actually returns two values: the final list and the new [state].
(defun process-file (filename state)
(mv-let
(channel state)
(open-input-channel filename :object state)
(mv-let (result state)
(process-file1 nil channel state) ;see below
(let ((state (close-input-channel channel state)))
(mv result state)))))
The function process-file1 referred to above takes the currently
constructed list (initially, nil), together with a channel to the
file being read and the [state], and returns the final updated
list. Notice that this function is tail recursive. This is
important because many Lisp compilers will remove tail recursion,
thus avoiding the potential for stack overflows when the file
contains a large number of forms.
(defun process-file1 (current-list channel state)
(mv-let (eofp obj state)
(read-object channel state)
(cond
(eofp (mv current-list state))
(t (process-file1 (update-list obj current-list)
channel state)))))
As an exercise, you might want to add [guard]s to the functions above
and verify the guards (see [verify-guards]). See [args] or make a
call of the form (guard 'your-function nil (w state)) to see the
guard of an existing function.")
(FINALIZE-EVENT-USER
(PROVER-OUTPUT)
"User-supplied code to complete [events], e.g., with extra summary
output
This utility is intended for system hackers, not standard ACL2 users.
ACL2 prints summaries at the conclusions of processing [events]
(unless summaries are inhibited; see [set-inhibit-output-lst] and
also see [set-inhibited-summary-types]). You may arrange for
processing to take place just after the summary, by defining a
function with argument list (ctx body state) that returns one
value, namely state. We describe ctx and body at the end below, but
you may simply prefer to ignore these arguments.) Your function
should normally be a [guard]-verified :[logic] mode function with
no guard other than that provided by the input requirement on
[state], that is, (state-p state); but later below we discuss how
to avoid this requirement. You then attach (see [defattach]) your
function to the function finalize-event-user. The following example
illustrates how this all works.
(defun finalize-event-user-test (ctx body state)
(declare (xargs :stobjs state)
(ignore ctx body))
(cond ((and (boundp-global 'abbrev-evisc-tuple state)
(open-output-channel-p *standard-co*
:character
state))
(pprogn
(if (eq (f-get-global 'abbrev-evisc-tuple state) :DEFAULT)
(princ$ \"Abbrev-evisc-tuple has its default value.~%\"
*standard-co*
state)
(princ$ \"Abbrev-evisc-tuple has been modified.~%\"
*standard-co*
state))))
(t state)))
(defattach finalize-event-user finalize-event-user-test)
After admission of the two events above, an event summary will
conclude with extra printout, for example:
Note: Abbrev-evisc-tuple has its default value.
If the attachment function (above, finalize-event-user-test) does not
meet all the requirements stated above, then you can use the
:skip-checks argument of [defattach] to get around the requirement,
as illustrated by the following example.
(defun finalize-event-user-test2 (state)
(declare (xargs :stobjs state
:mode :program)
(ignore ctx body))
(observation
'my-test
\"~|Value of term-evisc-tuple: ~x0~|\"
(f-get-global 'term-evisc-tuple state)))
(defttag t) ; needed for :skip-checks t
(defattach (finalize-event-user finalize-event-user-test2)
:skip-checks t)
So for example:
ACL2 !>(set-term-evisc-tuple (evisc-tuple 2 7 nil nil) state)
(:TERM)
ACL2 !>(defconst *foo6* '(a b c))
Summary
Form: ( DEFCONST *FOO6* ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
ACL2 Observation in MY-TEST:
Value of term-evisc-tuple: (NIL 2 7 NIL)
*FOO6*
ACL2 !>
Note that (as of this writing) the macro [observation] expands to a
call of a :[program]-mode function. Thus, the trick shown above
involving :skip-checks allows the use of :program-mode functions;
for example, you can print with [fmt].
See community book books/misc/defattach-bang.lisp for a variant of
[defattach] that uses [ec-call] to avoid issues of [guard]
verification.
Also see [initialize-event-user], which discusses the handling of
[state] globals by that utility as well as by finalize-event-user.
Finally, as promised above, we briefly describe the arguments ctx and
body. These are the arguments passed to the call of macro
with-ctx-summarized under which finalize-event-user (or
initialize-event-user) was called. Thus, they are unevaluated
expressions. For example, system function defthm-fn1 has a body of
the following form.
(with-ctx-summarized
(if (output-in-infixp state) event-form (cons 'defthm name))
(let ((wrld (w state))
(ens (ens state))
.....
Thus, when initialize-event-user and finalize-event-user are called
on behalf of [defthm], ctx is the s-expression
(if (output-in-infixp state) event-form (cons 'defthm name))
while body is the following s-expression (with most code elided).
(let ((wrld (w state))
(ens (ens state))
.....
You might find it helpful to use [trace$] to get a sense of ctx and
body, for example, (trace$ finalize-event-user).")
(FIND-RULES-OF-RUNE
(RUNE)
"Find the rules named rune
General Form:
(find-rules-of-rune rune wrld)
This function finds all the rules in wrld with :[rune] rune. It
returns a list of rules in their internal form (generally as
described by the corresponding defrec). Decyphering these rules is
difficult since one cannot always look at a rule object and decide
what kind of record it is without exploiting many system invariants
(e.g., that :[rewrite] runes only name rewrite-rules).
At the moment this function returns nil if the rune in question is a
:[refinement] rune, because there is no object representing
:[refinement] rules. (:[refinement] rules cause changes in the
'coarsenings properties.) In addition, if the rune is an
:[equivalence] rune, then congruence rules with that rune will be
returned --- because :[equivalence] lemmas generate some congruence
rules --- but the fact that a certain function is now known to be
an equivalence relation is not represented by any rule object and
so no such rule is returned. (The fact that the function is an
equivalence relation is encoded entirely in its presence as a
'coarsening of [equal].)")
(FINDING-DOCUMENTATION
(DOCUMENTATION)
"Searching the documentation
The :[doc] command will display, at the terminal, [documentation]
topics defined in ACL2 or in [books] that have already been
included. But how can you find documentation for books that are not
included in the current ACL2 session?
The [xdoc] {ACL2+Books Manual |
http://www.cs.utexas.edu/users/moore/acl2/v7-2/combined-manual/index.html}
includes documentation for both the ACL2 system and the
[community-books]. For more information on this manual and how to
view it, see [documentation].")
(FIRST
(NTH ACL2-BUILT-INS)
"First member of the list
See any Common Lisp documentation for details.")
(FIX
(NUMBERS ACL2-BUILT-INS)
"Coerce to a number
Fix simply returns any numeric argument unchanged, returning 0 on a
non-numeric argument. Also see [nfix], see [ifix], and see [rfix]
for analogous functions that coerce to a natural number, an
integer, and a rational number, respectively.
Fix has a [guard] of t.
Function: <fix>
(defun fix (x)
(declare (xargs :guard t))
(if (acl2-numberp x) x 0))")
(FIX-TRUE-LIST
(LISTS ACL2-BUILT-INS)
"Coerce to a true list
Fix-true-list is the identity function on [true-listp] objects. It
converts every list to a true list by dropping the final [cdr], and
it converts every [atom] to nil.
Function: <fix-true-list>
(defun fix-true-list (x)
(declare (xargs :guard t))
(if (consp x)
(cons (car x) (fix-true-list (cdr x)))
nil))")
(FLAWED_INDUCTION_CANDIDATES_IN_APP_EXAMPLE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Flawed Induction Candidates in App Example
Induction on a is unflawed: every occurrence of a in the conjecture
(equal (app (app a b) c)
(app a (app b c)))
is in a position being recursively decomposed!
Now look at the occurrences of b. The first (shown in bold below) is
in a position that is held constant in the recursion of (app a b).
It would be ``bad'' to induct on b here.
(equal (app (app a b) c)
(app a (app b c)))")
(FLET
(BASICS ACL2-BUILT-INS)
"Local binding of function symbols
Example Form:
; The following evaluates to (mv 7 10):
(flet ((f (x)
(+ x 3))
(g (x)
(declare (type integer x))
(* x 2)))
(mv (f 4) (g 5)))
General Forms:
(flet (def1 ... defk) body)
(flet (def1 ... defk) declare-form1 .. declare-formk body)
where body is a term, and each defi is a definition as in [defun] but
with the leading defun symbol omitted. See [defun]. If any
declare-formi are supplied, then each must be of the form (declare
decl1 ... decln), where each decli is of the form (inline g1 ...
gm) or (notinline g1 ... gm), and each gi is defined by some defi.
The only effect of the declarations is to provide advice to the host
Lisp compiler. The declarations are otherwise ignored by ACL2, so
we mainly ignore them in the discussion below.
The innermost flet-binding of a function symbol, f, above a call of
f, is the one that provides the definition of f for that call. Note
that flet does not provide recursion. Consider the following
example.
; Give a global definition of f:
(defun f (x) (+ x 3))
; Evaluate an expression using a local binding of f:
(flet ((f (x) (cons x (f (1+ x)))))
(f 4))
In the above term (cons x (f (1+ x))), f refers to the global
definition of f above the flet expression. However, (f 4) refers to
the flet-binding of f, (f (x) (cons x (f x))). The result of the
flet expression is thus obtained by evaluating (f 4) where (f 4) is
(cons 4 (f (1+ 4))), where the latter call of f refers to the
global definition; thus we have (cons 4 (f 5)), which evaluates to
(4 . 8).
Although flet behaves in ACL2 essentially as it does in Common Lisp,
ACL2 imposes the following restrictions and qualifications.
* Every [declare] form for a local definition (def1 through defk,
above) must be an ignore, ignorable, or type expression.
* Each defi must bind a different function symbol.
* Each defi must bind a symbol that is a legal name for an ACL2
function symbol. In particular, the symbol may not be in the
keyword package or the main Lisp package. Moreover, the symbol
may not be a built-in ACL2 function or macro.
* Every variable occurring in the body of a defi must be a formal
parameter of that defi. (This restriction is not enforced in
Common Lisp.)
* If the flet-binding defi is in the body of a function f, then the
[stobj] inputs for defi are implicitly those of its inputs that
are declared [stobj] inputs of f.
Flet bindings are evaluated in parallel. Consider the following
example.
(defun f (x) x)
(flet ((f (x) (cons x x))
(g (x) (f x)))
(g 3))
The binding of g refers to the global value of f, not the
flet-binding of f. Thus, the flet expression evaluates to 3.
Compare the flet expression above to the following one, which
instead evaluates to (3 . 3).
(defun f (x) x)
(flet ((f (x) (cons x x)))
(flet ((g (x) (f x)))
(g 3)))
Under the hood, ACL2 translates flet bindings to [lambda] expressions
(see [term]), throwing away the inline and notinline declarations
(if any). The following example illustrates this point.
ACL2 !>:trans (flet ((f (x) (cons x x))
(g (x y) (+ x y)))
(declare (inline f))
(f (g 3 4)))
((LAMBDA (X) (CONS X X))
((LAMBDA (X Y) (BINARY-+ X Y)) '3 '4))
=> *
ACL2 !>
Flet is part of Common Lisp. See any Common Lisp documentation for
more information. We conclude by pointing out an important aspect
of flet shared by ACL2 and Common Lisp: The binding is lexical, not
dynamic. That is, the flet binding of a function symbol only
applies to calls of that function symbol in the body of the flet,
not other calls made in the course of evaluation. Consider the
following example. Suppose we define:
(defun f (x) x)
(defun g (x) (f x))
(defun h (x)
(flet ((f (x) (cons x x)))
(g x)))
Then evaluation of (h 3) results in 3, not in the cons pair (3 . 3),
because the flet binding of f only applies to calls of f that
appear in the body of that flet. In this case, only g is called in
the body of that flet.")
(FLOOR
(NUMBERS ACL2-BUILT-INS)
"Division returning an integer by truncating toward negative infinity
Example Forms:
ACL2 !>(floor 14 3)
4
ACL2 !>(floor -14 3)
-5
ACL2 !>(floor 14 -3)
-5
ACL2 !>(floor -14 -3)
4
ACL2 !>(floor -15 -3)
5
(Floor i j) returns the result of taking the quotient of i and j and
returning the greatest integer not exceeding that quotient. For
example, the quotient of -14 by 3 is -4 2/3, and the largest
integer not exceeding that rational number is -5.
The [guard] for (floor i j) requires that i and j are rational
([real], in ACL2(r)) numbers and j is non-zero.
Floor is a Common Lisp function. See any Common Lisp documentation
for more information. However, note that unlike Common Lisp, the
ACL2 floor function returns only a single value,
Function: <floor>
(defun floor (i j)
(declare (xargs :guard (and (real/rationalp i)
(real/rationalp j)
(not (eql j 0)))))
(let* ((q (* i (/ j)))
(n (numerator q))
(d (denominator q)))
(cond ((= d 1) n)
((>= n 0)
(nonnegative-integer-quotient n d))
(t (+ (- (nonnegative-integer-quotient (- n) d))
-1)))))")
(FLUSH-COMPRESS
(ARRAYS ACL2-BUILT-INS)
"Flush the under-the-hood array for the given name
Example Form:
(flush-compress 'my-array)
General Form:
(flush-compress name)
where name is a symbol.
Recall that (compress1 nm alist) associates an under-the-hood raw
Lisp one-dimensional array of name nm with the given association
list, alist, while (compress2 nm alist) is the analogous function
for two-dimensional arrays; see [compress1] and see [compress2].
The only purpose of flush-compress, which always returns nil, is to
remove the association of any under-the-hood array with the given
name, thus eliminating slow array accesses (see
[slow-array-warning]). It is not necessary if the return values of
[compress1] and [compress2] are always used as the ``current'' copy
of the named array, and thus flush-compress should rarely, if ever,
be needed in user applications.
Nevertheless, we provide the following contrived example to show how
flush-compress can be used to good effect. Comments have been added
to this log to provide explanation.
ACL2 !>(assign a (compress1 'demo
'((:header :dimensions (5)
:maximum-length 15
:default uninitialized
:name demo)
(0 . zero)
(1 . one))))
((:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH
15 :DEFAULT UNINITIALIZED :NAME DEMO)
(0 . ZERO)
(1 . ONE))
ACL2 !>(aref1 'demo (@ a) 0)
ZERO
; As expected, the above evaluation did not cause a slow array warning. Now
; we associate a different under-the-hood array with the name 'demo.
ACL2 !>(compress1 'demo
'((:header :dimensions (5)
:maximum-length 15
:default uninitialized
:name demo)
(0 . zero)))
((:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH
15 :DEFAULT UNINITIALIZED :NAME DEMO)
(0 . ZERO))
; The following array access produces a slow array warning because (@ a) is
; no longer associated under-the-hood with the array name 'demo.
ACL2 !>(aref1 'demo (@ a) 0)
**********************************************************
Slow Array Access! A call of AREF1 on an array named
DEMO is being executed slowly. See :DOC slow-array-warning
**********************************************************
ZERO
; Now we associate under-the-hood, with array name 'demo, an alist equal to
; (@ a).
ACL2 !>(compress1 'demo
'((:header :dimensions (5)
:maximum-length 15
:default uninitialized
:name demo)
(0 . zero)
(1 . one)))
((:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH
15 :DEFAULT UNINITIALIZED :NAME DEMO)
(0 . ZERO)
(1 . ONE))
; The following array access is still slow, because the under-the-hood array
; is merely associated with a copy of (@ a), not with the actual object
; (@ a).
ACL2 !>(aref1 'demo (@ a) 0)
**********************************************************
Slow Array Access! A call of AREF1 on an array named
DEMO is being executed slowly. See :DOC slow-array-warning
**********************************************************
ZERO
; So we might try to fix the problem by recompressing. But this doesn't
; work. It would work, by the way, if we re-assign a:
; (assign a (compress1 'demo (@ a))). That is why we usually will not need
; flush-compress.
ACL2 !>(compress1 'demo (@ a))
((:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH
15 :DEFAULT UNINITIALIZED :NAME DEMO)
(0 . ZERO)
(1 . ONE))
ACL2 !>(aref1 'demo (@ a) 0)
**********************************************************
Slow Array Access! A call of AREF1 on an array named
DEMO is being executed slowly. See :DOC slow-array-warning
**********************************************************
ZERO
; Finally, we eliminate the warning by calling flush-compress before we call
; compress1. The call of flush-compress removes any under-the-hood
; association of an array with the name 'demo. Then the subsequent call of
; compress1 associates the object (@ a) with that name. (Technical point:
; compress1 always associates the indicated name with the value that it
; returns. in this case, what compress1 returns is (@ a), because (@ a) is
; already, logically speaking, a compressed array1p (starts with a :header
; and the natural number keys are ordered).
ACL2 !>(flush-compress 'demo)
NIL
ACL2 !>(compress1 'demo (@ a))
((:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH
15 :DEFAULT UNINITIALIZED :NAME DEMO)
(0 . ZERO)
(1 . ONE))
ACL2 !>(aref1 'demo (@ a) 0)
ZERO
ACL2 !>
Function: <flush-compress>
(defun flush-compress (name)
(declare (xargs :guard t))
(declare (ignore name))
nil)")
(FLUSH-HONS-GET-HASH-TABLE-LINK
(FAST-ALIST-FREE ACL2-BUILT-INS)
"Deprecated feature
Deprecated. Alias for [fast-alist-free].")
(FMS
(IO ACL2-BUILT-INS)
"(fms str alist co-channel state evisc) => state
See [fmt] for further explanation, including documentation of the
tilde-directives.")
(FMS!
(IO ACL2-BUILT-INS)
"(fms! str alist co-channel state evisc) => state
This function is nearly identical to fms; see [fms]. The only
difference is that fms may insert backslash (\\) characters when
forced to print past the right margin in order to make the output a
bit clearer in that case. Use fms! instead if you want to be able
to read the forms back in.")
(FMS!-TO-STRING (POINTERS)
"See [printing-to-strings].")
(FMS-TO-STRING (POINTERS)
"See [printing-to-strings].")
(FMT
(IO ACL2-BUILT-INS)
"Formatted printing
ACL2 provides the functions fmt, [fmt1], and [fms] as substitutes for
Common Lisp's format function. Also see [fmt!], see [fmt1!], and
see [fms!] for versions of these functions that write forms to
files in a manner that allows them to be read, by avoiding using
backslash (\\) to break long lines. There are also analogues of
these functions that return a string without taking [state] as an
argument; see [printing-to-strings].
All three print a given string under an alist pairing character
objects with values, interpreting certain ``tilde-directives'' in
the string. Channel must be a character output channel (e.g.,
[*standard-co*]).
General Forms: result
(fms string alist channel state evisc-tuple) ; state
(fmt string alist channel state evisc-tuple) ; (mv col state)
(fmt1 string alist column channel state evisc-tuple) ; (mv col state)
[Fms] and fmt print an initial newline to put channel in column 0;
[Fmt1] requires the current column as input. Columns are numbered
from 0. The current column is the column into which the next
character will be printed. (Thus, the current column number is also
the number of [characters] printed since the last newline.) The col
returned by fmt and [fmt1] is the current column at the conclusion
of the formatting. Evisc-tuple must be either nil (meaning no
abbreviations are used when objects are printed) or an
``evisceration tuple''; see [evisc-tuple].
We list the tilde-directives below. The notation is explained after
the chart.
~xx pretty print vx (maybe after printing a newline)
~yx pretty print vx starting in current column; end with newline
~Xxy like ~xx but use vy as the evisceration tuple
~Yxy like ~yx but use vy as the evisceration tuple
~@x if vx is a string, \"str\", recursively format \"str\"
if vx is (\"str\" . a), recursively format \"str\" under a+
~#x~[...~/...~/ ... ~/...~] cases on vx
^ ^ ... ^ if 0<=vx<=k, choose vxth alternative
0 1 ... k if vx is a list of length 1, case 0; else 1
~*x iterator: vx must be of the form
(\"str0\" \"str1\" \"str2\" \"str3\" lst . a);
if lst is initially empty, format \"str0\" under a+; otherwise,
bind #\\* successively to the elements of lst and then
recursively format \"stri\" under a+, where i=1 if there is one
element left to process, i=2 if there are two left, and i=3
otherwise.
~&x print elements of vx with ~x, separated by commas and a
final ``and''
~vx print elements of vx with ~x, separated by commas and a
final ``or''
~nx if vx is a small positive integer, print it as a word, e.g.,
seven;
if vx is a singleton containing a small positive integer, print
the corresponding ordinal as a word, e.g., seventh
~Nx like ~nx but the word is capitalized, e.g., Seven or Seventh
~tx tab out to column vx; newline first if at or past column vx
~cx vx is (n . w), print integer n right justified in field of
width w
~fx print object vx flat over as many lines as necessary
~Fx same as ~f, except that subsequent lines are indented to
start one character to the right of the first character printed
~sx if vx is a symbol, print vx, breaking on hyphens (unless the
symbol would normally be printed with surrounding vertical bar
characters (|), in which case print as with ~fx); if vx is a
string, print the characters in it, breaking on hyphens; else
vx is a number, to be printed using the current print-base and
print-radix
~ tilde space: print a space
~_x print vx spaces
~
tilde newline: skip following whitespace
~% output a newline
~| output a newline unless already on left margin
~~ print a tilde
~- if close to rightmargin, output a hyphen and newline; else
skip this char
If x is a character, then vx is the value of #\\x under the current
alist. Consider for example the discussion above for ~y, ``~yx
pretty print vx'', applied to the following expression: (fmt \"HELLO
~y7\" (list (cons #\\7 'world)) *standard-co* state nil). Then in
this example: #\\x is 7; and vx is the value of character #\\7 under
the given alist, which is the symbol, WORLD. Thus, ACL2 will print
HELLO WORLD. When we say ``format str under a+'' we mean: process
the given string under an alist obtained by appending a to the
current alist. The following example illustrates how this works.
ACL2 !>(fms \"~@0\"
(list (cons #\\0 (cons \"~x0 ~@1\" (list (cons #\\0 'abc))))
(cons #\\1 \"-- and now: ~x0 again~%\"))
*standard-co* state nil)
ABC -- and now: ABC again
<state>
ACL2 !>
Note: ~p, ~q, ~P, and ~Q are also currently supported, but are
deprecated. These are respectively the same as ~x, ~y, ~X, and ~Y,
except that their arguments are expected to be terms, preferably
untranslated (user-level) terms, that could be printed using infix
notation in certain environments. Infix printing is not currently
supported but may be if there is sufficient need for it.
ACL2's formatting functions print to the indicated channel, keeping
track of which column they are in. [Fmt1] can be used if the caller
knows which column the channel is in (i.e., how many [characters]
have been printed since the last newline). Otherwise, fmt or [fms]
must be used, both of which output a newline so as to establish the
column position at 0. Unlike Common Lisp's format routine, fmt and
its relatives break the output into lines so that, by default, an
attempt is made to avoid printing past column 77 (the value of
constant *fmt-hard-right-margin-default*). See
[set-fmt-hard-right-margin] for a discussion of how linebreaks are
inserted and how to change the relevant default settings.
The formatting functions scan the string from left to right, printing
each successive character unless it is a tilde (~). Upon
encountering tildes the formatters take action determined by the
character or [characters] immediately following the tilde. The
typical tilde-directive is a group of three successive [characters]
from the string being printed. For example, ~x0 is a 3 character
tilde-directive. The first character in a tilde-directive is always
the tilde character itself. The next character is called the
``command'' character. The character after that is usually taken as
the name of a ``format variable'' that is bound in the alist under
which the string is being printed. Format variables are, by
necessity, [characters]. The objects actually printed by a
tilde-directive are the objects obtained by looking up the
command's format variables in the alist. Typical format variable
names are 0, 1, 2, ..., 9, a, b, c, etc., and if a tilde-directive
uses the format variable 0, as in ~x0, then the character #\\0 must
be bound in the alist. Some tilde commands take no arguments and
others take more than one, so some directives are of length two and
others are longer.
It should be noted that this use of [characters] in the string to
denote arguments is another break from Common Lisp's format
routine. In Common Lisp, the directives refer implicitly to the
``next item to be printed.'' But in ACL2 the directives name each
item explicitly with our format variables.
The following text contains examples that can be evaluated. To make
this process easier, we use a macro which is defined as part of
ACL2 just for this [documentation]. The macro is named fmx and it
takes up to eleven arguments, the first of which is a format
string, str, and the others of which are taken as the values of
format variables. The variables used are #\\0 through #\\9. The macro
constructs an appropriate alist, a, and then evaluates (fmt str a
*standard-co* state nil).
Thus,
(fmx \"Here is v0, ~x0, and here is v1, ~x1.\"
(cons 'value 0)
(cons 'value 1))
is just an abbreviation for
(fmt \"Here is v0, ~x0, and here is v1, ~x1.\"
(list (cons #\\0 (cons 'value 0))
(cons #\\1 (cons 'value 1)))
*standard-co*
state
nil)
which returns (mv 53 state) after printing the line
Here is v0, (VALUE . 0), and here is v1, (VALUE . 1).
We now devote special attention to three of the tilde-directives
whose use is non-obvious.
The Case Statement
~#x is essentially a ``case statement'' in the language of fmt. The
proper form of the statement is
~#x~[case-0~/case-1~/ ... ~/case-k~],
where each of the case-i is a format string. In the most common use,
the variable x has an integer value, vx, between 0 and k,
inclusive. The effect of formatting the directive is to format
case-vx.
For example
(fmx \"Go ~#0~[North~/East~/South~/West~].~%\" 1)
will print ``Go East.'' followed by a newline and will return
(mv 0 state), while if you change the 1 above to 3 (the maximum legal
value), it will print ``Go West.''
In order to make it easier to print such phrases as ``there are seven
cases'' requiring agreement between subject and verb based on the
number of elements of a list, the case statement allows its
variable to take a list as its value and selects case-0 if the list
has length 1 and case-1 otherwise.
(let ((cases '(a b c)))
(fmx \"There ~#0~[is ~n1 case~/are ~n1 cases~].\"
cases
(length cases)))
will print ``There are three cases.'' but if you change the
'(a b c) above simply to '(a) it will print ``There is one case.''
and if you change it to nil it will print ``There are zero cases.''
Indirection
Roughly speaking, ~@ will act as though the value of its argument is
a format string and splice it into the current string at the
current position. It is often used when the phrase to be printed
must be computed. For example,
(let ((ev 'DEFUN))
(fmx \"~x0 is an event~@1.\"
'foo
(if (member-eq ev '(defun defstub encapsulate))
\" that may introduce a function symbol\"
\"\")))
will print ``foo is an event that may introduce a function symbol,''
but if the value of ev is changed from '[defun] to '[defthm], it
prints ``foo is an event.'' The ~@ directive ``splices'' in the
computed phrase (which might be empty). Of course, this particular
example could be done with the case statement
~#1~[~/ that may introduce a function symbol~]
where the value of #\\1 is appropriately computed to be 0 or 1.
If the argument to ~@ is a pair, it is taken to be a format string
[cons]ed onto an alist, i.e., (\"str\" . a), and the alist, a, is
used to extend the current one before \"str\" is recursively
processed. This feature of fmt can be used to pass around
``phrases'' that contain computed contextual information in a. The
most typical use is as ``error messages.'' For example, suppose you
are writing a function which does not have access to [state] and so
cannot print an error message. It may nevertheless be necessary for
it to signal an error to its caller, say by returning two results,
the first of which is interpreted as an error message if non-nil.
Our convention is to use a ~@ pair to represent such messages. For
example, the error value might be produced by the code:
(cons
\"Error: The instruction ~x0 is illegal when the stack is ~x1.~%\"
(list (cons #\\0 (current-instruction st))
(cons #\\1 (i-stack st))))
If the current-instruction and i-stack (whatever they are) are '(popi
3) and '(a b) when the [cons] above is evaluated, then it produces
'(\"Error: The instruction ~x0 is illegal when the stack is ~x1.~%\"
(#\\0 POPI 3)
(#\\1 A B))
and if this pair is made the value of the fmt variable 0, then ~@0
will print
Error: The instruction (POPI 3) is illegal when the stack is (A B).
For example, evaluate
(let
((pair
'(\"Error: The instruction ~x0 is illegal when the stack is ~x1.~%\"
(#\\0 POPI 3)
(#\\1 A B))))
(fmx \"~@0\" pair)).
Thus, even though the function that produced the ``error'' could not
print it, it could specify exactly what error message and data are
to be printed.
This example raises another issue. Sometimes it is desirable to break
lines in your format strings so as to make your source code more
attractive. That is the purpose of the tilde-newline directive. The
following code produces exactly the same output as described above.
(let ((pair '(\"Error: The instruction ~x0 ~
is illegal when the stack is ~
~x1.~%\"
(#\\0 POPI 3)
(#\\1 A B))))
(fmx \"~@0\" pair)).
Finally, observe that when ~@0 extends the current alist, alist, with
the one, a, in its argument, the bindings from a are added to the
front of alist, overriding the current values of any shared
variables. This ensures that the variable values seen by the
recursively processed string, \"str\", are those from a, but if \"str\"
uses variables not bound in a, their values are as specified in the
original alist. Intuitively, variables bound in a are local to the
processing of (\"str\" . a) but \"str\" may use ``global variables.''
The example above illustrates this because when the ~@0 is
processed, #\\0 is bound to the error message pair. But when the ~x0
in the error string is processed, #\\0 is bound to the illegal
instruction.
Iteration
The ~* directive is used to process each element of a list. For
example,
(let ((lst '(a b c d e f g h))) ; a true-list whose elements we exhibit
(fmx \"~*0\"
`(\"Whoa!\" ; what to print if there's nothing to print
\"~x*!\" ; how to print the last element
\"~x* and \" ; how to print the 2nd to last element
\"~x*, \" ; how to print all other elements
,lst))) ; the list of elements to print
will print ``A, B, C, D, E, F, G and H!''. Try this example with
other true list values of lst, such as '(a b), '(a), and nil. The
tilde-directives ~&0 and ~v0, which take a true list argument and
display its elements separated by commas and a final ``and'' or
``or,'' are implemented in terms of the more general ~*.
The ~* directive allows the 5-tuple to specify in its final [cdr] an
alist with which to extend the current one before processing the
individual elements.
We often use ~* to print a series of phrases, separated by suitable
punctuation, whitespace and noise words. In such use, the ~*
handles the separation of the phrases and each phrase is generally
printed by ~@.
Here is a complex example. In the [let*], below, we bind phrases to a
list of ~@ pairs and then we create a ~* 5-tuple to print out the
conjunction of the phrases with a parenthetical ``finally!'' if the
series is longer than 3.
(let* ((phrases
(list (list \"simplifying with the replacement rules ~&0\"
(cons #\\0 '(rewrite-rule1
rewrite-rule2
rewrite-rule3)))
(list \"destructor elimination using ~x0\"
(cons #\\0 'elim-rule))
(list \"generalizing the terms ~&0\"
(cons #\\0 '((rev x) (app u v))))
(list \"inducting on ~x0\"
(cons #\\0 'I))))
(5-tuple
(list
\"magic\" ; no phrases
\"~@*\" ; last phrase
\"~@*, and~#f~[~/ (finally!)~] \" ; second to last phrase
\"~@*, \" ; other phrases
phrases ; the phrases themselves
(cons #\\f
(if (>(length phrases) 3) 1 0))))) ;print ``finally''?
(fmx \"We did it by ~*0.\" 5-tuple))
This [let*] prints
We did it by simplifying with the replacement rules REWRITE-RULE1,
REWRITE-RULE2 and REWRITE-RULE3, destructor elimination using ELIM-
RULE, generalizing the terms (REV X) and (APP U V), and (finally!)
inducting on I.
You might wish to try evaluating the [let*] after removing elements
of phrases.
Most of the output produced by ACL2 is produced via fmt statements.
Thus, inspection of the source code will yield many examples. A
complicated example is the code that explains the simplifier's
work. See :[pc] simplify-clause-msg1. An ad hoc example is provided
by the function fmt-doc-example, which takes two arguments: an
arbitrary true list and [state]. To see how fmt-doc-example works,
:[pe] fmt-doc-example.
(fmt-doc-example '(a b c d e f g h i j k l m n o p) state)
will produce the output
Here is a true list: (A B C D E F G H I J K L M N O P). It has 16
elements, the third of which is C.
We could print each element in square brackets:
([A], [B], [C], [D], [E], [F], [G], [H], [I], [J], [K], [L], [M], [N],
[almost there: O], [the end: P]). And if we wished to itemize them
into column 15 we could do it like this
0123456789012345
0 (zeroth) A
1 (first) B
2 (second) C
3 (third) D
4 (fourth) E
5 (fifth) F
6 (sixth) G
7 (seventh)
H
8 (eighth) I
9 (ninth) J
10 (tenth) K
11 (eleventh)
L
12 (twelfth)
M
13 (thirteenth)
N
14 (14th) O
15 (15th) P
End of example.
and return (mv 15 state).
Finally, we should remind the reader that fmt and its subfunctions,
most importantly fmt0, are written entirely in ACL2. We make this
comment for two reasons. First, it illustrates the fact that quite
low level code can be efficiently written in the language. Second,
it means that as a last resort for documentation purposes you can
read the source code without changing languages.")
(FMT!
(IO ACL2-BUILT-INS)
"(fmt! str alist co-channel state evisc) => state
This function is nearly identical to fmt; see [fmt]. The only
difference is that fmt may insert backslash (\\) characters when
forced to print past the right margin in order to make the output a
bit clearer in that case. Use fmt! instead if you want to be able
to read the forms back in.")
(FMT!-TO-STRING (POINTERS)
"See [printing-to-strings].")
(FMT-TO-COMMENT-WINDOW
(IO ACL2-BUILT-INS)
"Print to the comment window
See [cw] for an introduction to the comment window and the usual way
to print it.
Function fmt-to-comment-window is identical to fmt1 (see [fmt]),
except that the channel is [*standard-co*] and the ACL2 [state] is
neither an input nor an output. An analogous function,
fmt-to-comment-window!, prints with [fmt!] instead of [fmt], in
order to avoid insertion of backslash (\\) characters for margins;
also see [cw!]. Note that even if you change the value of [ld]
special standard-co (see [standard-co]), fmt-to-comment-window will
print to [*standard-co*], which is the original value of
[standard-co].
General Form:
(fmt-to-comment-window fmt-string alist col evisc-tuple)
where these arguments are as desribed for [fmt1]; see [fmt].")
(FMT-TO-STRING (POINTERS)
"See [printing-to-strings].")
(FMT1
(IO ACL2-BUILT-INS)
"(fmt1 str alist col co-channel state evisc) => (mv col state)
See [fmt] for further explanation, including documentation of the
tilde-directives.")
(FMT1!
(IO ACL2-BUILT-INS)
"(fmt1! str alist col channel state evisc) => (mv col state)
This function is nearly identical to fmt1; see [fmt1]. The only
difference is that fmt1 may insert backslash (\\) characters when
forced to print past the right margin in order to make the output a
bit clearer in that case. Use fmt1! instead if you want to be able
to read the forms back in.")
(FMT1!-TO-STRING (POINTERS)
"See [printing-to-strings].")
(FMT1-TO-STRING (POINTERS)
"See [printing-to-strings].")
(FNCALL-TERM (POINTERS)
"See [meta-extract].")
(FORALL
(DEFUN-SK)
"Universal quantifier
The symbol forall (in the ACL2 package) represents universal
quantification in the context of a [defun-sk] form. See [defun-sk]
and see [exists].
See [quantifiers] for an example illustrating how the use of
recursion, rather than explicit quantification with [defun-sk], may
be preferable.")
(FORCE
(REWRITE LINEAR
TYPE-PRESCRIPTION DEFINITION META)
"Identity function used to force a hypothesis
Force is the identity function: (force x) is equal to x. However, for
rules of many classes (see [rule-classes]), a hypothesis of the
form (force term) is given special treatment, as described below.
This treatment takes place for rule classes :[rewrite], :[linear],
:[type-prescription], :[definition], :[meta] (actually in that
case, the result of evaluating the hypothesis metafunction call),
and :[forward-chaining].
When a hypothesis of a conditional rule (of one of the classes listed
above) has the form (force hyp), it is logically equivalent to hyp
but has a pragmatic effect. In particular, when the rule is
considered, the needed instance of the hypothesis, hyp', may be
assumed if the usual process fails to prove it or its negation. In
that situation, if the rule is eventually applied, then a special
case is generated, requiring the system to prove that hyp' is true
in the current context. The proofs of all such ``forced
assumptions'' are, by default, delayed until the successful
completion of the main goal. See [forcing-round] and see
[immediate-force-modep].
Note that the only time that ACL2 gives special treatment to calls of
force is when it is considering the hypotheses of a conditional
rule, as discussed above. In particular, when the rewriter
encounters a subterm of the goal currently being simplified, a call
of force is not treated specially. For example, if you provide a
:use hint (see [hints]) that replaces a goal G by the goal
(implies (implies (and ... (force HYP) ...)
concl)
G)
then the rewriter will not give any special treatment to (force HYP).
Instead, it will first rewrite HYP to, say, HYP'; and then, using
the fact that force is the identity function, the rewriter will
return HYP' as the rewritten value for (force HYP).
Forcing is generally used on hypotheses that are always expected to
be true, as is commonly the case for [guard]s of functions. All the
power of the theorem prover is brought to bear on a forced
hypothesis and no backtracking is possible. Forced goals can be
attacked immediately (see [immediate-force-modep]) or in a
subsequent forcing round (see [forcing-round]). Also see
[case-split] for a related utility. If the
:[executable-counterpart] of the function force is [disable]d, then
no hypothesis is forced. For more on enabling and disabling
forcing, see [enable-forcing] and see [disable-forcing].
It sometimes happens that a conditional rule is not applied because
some hypothesis, hyp, could not be relieved, even though the
required instance of hyp, hyp', can be shown true in the context.
This happens when insufficient resources are brought to bear on
hyp' at the time we try to relieve it. A sometimes desirable
alternative behavior is for the system to assume hyp', apply the
rule, and to generate explicitly a special case to show that hyp'
is true in the context. This is called ``forcing'' hyp. It can be
arranged by restating the rule so that the offending hypothesis,
hyp, is embedded in a call of force, as in (force hyp). By using
the :[corollary] field of the [rule-classes] entry, a hypothesis
can be forced without changing the statement of the theorem from
which the rule is derived.
Technically, force is just a function of one argument that returns
that argument. It is generally [enable]d and hence evaporates
during simplification. But its presence among the hypotheses of a
conditional rule causes case splitting to occur if the hypothesis
cannot be conventionally relieved.
Since a forced hypothesis must be provable whenever the rule is
otherwise applicable, forcing should be used only on hypotheses
that are expected always to be true.
A particularly common situation in which some hypotheses should be
forced is in ``most general'' [type-prescription] lemmas. If a
single lemma describes the ``expected'' type of a function, for all
``expected'' arguments, then it is probably a good idea to force
the hypotheses of the lemma. Thus, every time a term involving the
function arises, the term will be given the expected type and its
arguments will be required to be of the expected type. In applying
this advice it might be wise to avoid forcing those hypotheses that
are in fact just type predicates on the arguments, since the
routine that applies [type-prescription] lemmas has fairly thorough
knowledge of the types of all terms.
Force can have the additional benefit of causing the ACL2 typing
mechanism to interact with the ACL2 rewriter to establish the
hypotheses of [type-prescription] rules. To understand this remark,
think of the ACL2 type reasoning system as a rather primitive
rule-based theorem prover for questions about Common Lisp types,
e.g., ``does this expression produce a [consp]?'' ``does this
expression produce some kind of ACL2 number, e.g., an [integerp], a
[rationalp], or a [complex-rationalp]?'' etc. It is driven by
[type-prescription] rules. To relieve the hypotheses of such rules,
the type system recursively invokes itself. This can be done for
any hypothesis, whether it is ``type-like'' or not, since any
proposition, p, can be phrased as the type-like question ``does p
produce an object of type nil?'' However, as you might expect, the
type system is not very good at establishing hypotheses that are
not type-like, unless they happen to be assumed explicitly in the
context in which the question is posed, e.g., ``If p produces a
[consp] then does p produce nil?'' If type reasoning alone is
insufficient to prove some instance of a hypothesis, then the
instance will not be proved by the type system and a
[type-prescription] rule with that hypothesis will be inapplicable
in that case. But by embedding such hypotheses in force expressions
you can effectively cause the type system to ``punt'' them to the
rest of the theorem prover. Of course, as already noted, this
should only be done on hypotheses that are ``always true.'' In
particular, if rewriting is required to establish some hypothesis
of a [type-prescription] rule, then the rule will be found
inapplicable because the hypothesis will not be established by type
reasoning alone.
The ACL2 rewriter uses the type reasoning system as a subsystem. It
is therefore possible that the type system will force a hypothesis
that the rewriter could establish. Before a forced hypothesis is
reported out of the rewriter, we try to establish it by rewriting.
This makes the following surprising behavior possible: A
[type-prescription] rule fails to apply because some true
hypothesis is not being relieved. The user changes the rule so as
to force the hypothesis. The system then applies the rule but
reports no forcing. How can this happen? The type system ``punted''
the forced hypothesis to the rewriter, which established it.
Finally, we should mention that the rewriter is never willing to
force when there is an [if] term present in the goal being
simplified. Since [and] terms and [or] terms are merely
abbreviations for [if] terms, they also prevent forcing. Note that
[if] terms are ultimately eliminated using the ordinary flow of the
proof (but see [set-case-split-limitations]), allowing force
ultimately to function as intended. Moreover, forcing can be
disabled, as described above; also see [disable-forcing].
Function: <force>
(defun force (x)
(declare (xargs :guard t))
x)
Subtopics
[Disable-forcing]
To disallow forced case-splits
[Disable-immediate-force-modep]
[force]d hypotheses are not attacked immediately
[Enable-forcing]
To allow forced case splits
[Enable-immediate-force-modep]
[force]d hypotheses are attacked immediately
[Failed-forcing]
How to deal with a proof [failure] in a forcing round
[Forcing-round]
A section of a proof dealing with [force]d assumptions
[Immediate-force-modep]
When executable counterpart is [enable]d, [force]d hypotheses are
attacked immediately")
(FORCED (POINTERS) "See [force].")
(FORCING-ROUND
(FORCE)
"A section of a proof dealing with [force]d assumptions
If ACL2 ``[force]s'' some hypothesis of some rule to be true, it is
obliged later to prove the hypothesis. See [force]. ACL2 delays the
consideration of [force]d hypotheses until the main goal has been
proved. It then undertakes a new round of proofs in which the main
goal is essentially the conjunction of all hypotheses [force]d in
the preceding proof. Call this round of proofs the ``Forcing
Round.'' Additional hypotheses may be [force]d by the proofs in the
Forcing Round. The attempt to prove these hypotheses is delayed
until the Forcing Round has been successfully completed. Then a new
Forcing Round is undertaken to prove the recently [force]d
hypotheses and this continues until no hypotheses are [force]d.
Thus, there is a succession of Forcing Rounds.
The Forcing Rounds are enumerated starting from 1. The Goals and
Subgoals of a Forcing Round are printed with the round's number
displayed in square brackets. Thus, \"[1]Subgoal 1.3\" means that the
goal in question is Subgoal 1.3 of the 1st forcing round. To supply
a hint for use in the proof of that subgoal, you should use the
goal specifier \"[1]Subgoal 1.3\". See [goal-spec].
When a round is successfully completed --- and for these purposes you
may think of the proof of the main goal as being the 0th forcing
round --- the system collects all of the assumptions [force]d by
the just-completed round. Here, an assumption should be thought of
as an implication, (implies context hyp), where context describes
the context in which hyp was assumed true. Before undertaking the
proofs of these assumptions, we try to ``clean them up'' in an
effort to reduce the amount of work required. This is often
possible because the [force]d assumptions are generated by the same
rule being applied repeatedly in a given context.
By delaying and collecting the forced assumptions until the
completion of the ``main goal'' we gain two advantages. First, the
user gets confirmation that the ``gist'' of the proof is complete
and that all that remains are ``technical details.'' Second, by
delaying the proofs of the [force]d assumptions ACL2 can undertake
the proof of each assumption only once, no matter how many times it
was [force]d in the main goal.
In order to indicate which proof steps of the previous round were
responsible for which [force]d assumptions, we print a sentence
explaining the origins of each newly [force]d goal. For example,
[1]Subgoal 1, below, will focus on
(GOOD-INPUTP (XTRANS I)),
which was forced in
Subgoal 14, above,
by applying (:REWRITE PRED-CRUNCHER) to
(PRED (XTRANS I) I),
and
Subgoal 28, above,
by applying (:REWRITE PRED-CRUNCHER) to
(PRED (XTRANS I) I).
In this entry, ``[1]Subgoal 1'' is the name of a goal which will be
proved in the next forcing round. On the next line we display the
[force]d hypothesis, call it x, which is (good-inputp (xtrans i))
in this example. This term will be the conclusion of the new
subgoal. Since the new subgoal will be printed in its entirety when
its proof is undertaken, we do not here exhibit the context in
which x was [force]d. The sentence then lists (possibly a
succession of) a goal name from the just-completed round and some
step in the proof of that goal that [force]d x. In the example
above we see that Subgoals 14 and 28 of the just-completed proof
[force]d (good-inputp (xtrans i)) by applying (:rewrite
pred-cruncher) to the term (pred (xtrans i) i).
If one were to inspect the theorem prover's description of the proof
steps applied to Subgoals 14 and 28 one would find the word
``[force]d'' (or sometimes ``forcibly'') occurring in the
commentary. Whenever you see that word in the output, you know you
will get a subsequent forcing round to deal with the hypotheses
[force]d. Similarly, if at the beginning of a forcing round a
[rune] is blamed for causing a [force] in some subgoal, inspection
of the commentary for that subgoal will reveal the word
``[force]d'' after the rule name blamed.
Most [force]d hypotheses come from within the prover's simplifier.
When the simplifier encounters a hypothesis of the form (force hyp)
it first attempts to establish it by rewriting hyp to, say, hyp'.
If the truth or falsity of hyp' is known, forcing is not required.
Otherwise, the simplifier actually [force]s hyp'. That is, the x
mentioned above is hyp', not hyp, when the [force]d subgoal was
generated by the simplifier.
Once the system has printed out the origins of the newly [force]d
goals, it proceeds to the next forcing round, where those goals are
individually displayed and attacked.
At the beginning of a forcing round, the [enable]d structure defaults
to the global [enable]d structure. For example, suppose some
[rune], rune, is globally [enable]d. Suppose in some event you
[disable] the [rune] at \"Goal\" and successfully prove the goal but
[force] \"[1]Goal\". Then during the proof of \"[1]Goal\", [rune] is
[enable]d ``again.'' The right way to think about this is that the
[rune] is ``still'' [enable]d. That is, it is [enable]d globally
and each forcing round resumes with the global [enable]d structure.")
(FORMULA
(HISTORY WORLD ACL2-BUILT-INS)
"The formula of a name or [rune]
The ACL2 system function, formula, returns the [term] associated with
a given [rune] or symbolic name, returning nil if there is no such
term. Note that a non-nil result will be an ACL2 ``translated''
term (see [term]). Most ACL2 users probably will have no reason to
know about this function. But here we document this function for
those who write system-level tools, since they might find this
interface to the ACL2 logical [world] to be useful.
When ACL2 is given a :use or :by hint, it looks for the [term] stored
in the ACL2 logical [world] that is associated with the name given
in the hint, which is a symbol or a [rune]. (See (@see
lemma-instance).) The utility used to find that term is formula,
which ACL2 invokes as follows.
(formula x t wrld) ; for :use hints
(formula x nil wrld) ; for :by hints
The second argument can affect whether or not to use a ``normalized''
version of the term associated with x. The value is t for :use
[hints] because normalizing a term simplifies it, which is often
desirable. But for a :by hint, the non-normalized version of the
term is used in order to increase the chance that the necessary
subsumption test will succeed. Even if the second argument is t,
normalization might not take place. In the unlikely case that you
really need to know the effect of supplying t, see the source code
for formula.
Here are some examples. Note that (w state) returns the current ACL2
logical [world]. First let us submit a few [events].
(defun f1 (x) (cons 3 x))
(defun f2 (x y) (implies x y))
(defthm one-rule
(and (equal (* 2 y) (+ y y))
(equal (* 3 y) (+ y y y))))
(defthm two-rules
t
:rule-classes ((:rewrite :corollary (equal (* 2 y) (+ y y)))
(:rewrite :corollary (equal (* 3 y) (+ y y y)))))
Then:
ACL2 !>(formula 'f1 nil (w state))
(EQUAL (F1 X) (CONS '3 X))
ACL2 !>(formula 'f1 t (w state))
(EQUAL (F1 X) (CONS '3 X))
ACL2 !>(formula 'f2 nil (w state))
(EQUAL (F2 X Y) (IMPLIES X Y))
ACL2 !>(formula 'f2 t (w state))
(EQUAL (F2 X Y)
(IF X (IF Y 'T 'NIL) 'T))
ACL2 !>(formula 'one-rule nil (w state))
(IF (EQUAL (BINARY-* '2 Y) (BINARY-+ Y Y))
(EQUAL (BINARY-* '3 Y)
(BINARY-+ Y (BINARY-+ Y Y)))
'NIL)
ACL2 !>(equal (formula 'one-rule nil (w state)) (formula 'one-rule t (w state)))
T
ACL2 !>(formula 'two-rules nil (w state))
'T
ACL2 !>(formula 'two-rules t (w state))
'T
ACL2 !>(formula '(:rewrite two-rules . 1) nil (w state))
(EQUAL (BINARY-* '2 Y) (BINARY-+ Y Y))
ACL2 !>(formula '(:rewrite two-rules . 2) nil (w state))
(EQUAL (BINARY-* '3 Y)
(BINARY-+ Y (BINARY-+ Y Y)))
ACL2 !>(formula 'no-such-rule nil (w state))
NIL
ACL2 !>")
(FORWARD-CHAINING
(RULE-CLASSES)
"Make a rule to forward chain when a certain trigger arises
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Examples:
(defthm p-and-r-forward ; When (p a) appears in a formula to be
(implies (and (p x) (r x)) ; simplified, try to establish (p a) and
(q (f x))) ; (r a) and, if successful, add (q (f a))
:rule-classes :forward-chaining) ; to the known assumptions.
(defthm p-and-r-forward ; as above with most defaults filled in
(implies (and (p x) (r x))
(q (f x)))
:rule-classes ((:forward-chaining :trigger-terms ((p x))
:corollary (implies (and (p x) (r x))
(q (f x)))
:match-free :all)))
To specify the triggering terms provide a non-empty list of terms as
the value of the :trigger-terms field of the rule class object.
General Form:
Any theorem, provided an acceptable triggering term exists.
The structure of this documentation is as follows. First we give a
brief overview of forward chaining and contrast it to backchaining
(rewriting). Then we lay out the syntactic restrictions on
:forward-chaining rules. Then we give more details about the
process and point to a tool to assist you in debugging your
:forward-chaining rules.
Overview and When to Use Forward Chaining
Forward chaining is performed as part of the simplification process:
before the goal is rewritten a context is established. The context
tells the theorem prover what may be assumed during rewriting, in
particular, to establish hypotheses of rewrite rules. Forward
chaining is used to extend the context before rewriting begins. For
example, the :forward-chaining rule (implies (p x) (p1 x)) would
add (p1 A) to the context, where A is some term, if (p A) is
already in the context.
Forward chaining and backchaining are duals. If a rewrite rule
requires that (p1 A) be established and (p A) is known, it could be
done either by making (implies (p x) (p1 x)) a :forward-chaining
rule or a :rewrite rule. Which should you choose?
As a rule of thumb, if a conclusion like (p1 A) is expected to be
widely needed, it is better to derive it via forward chaining
because then it is available ``for free'' during the rewriting
after paying the one-time cost of forward chaining. Alternatively,
if (p1 A) is a rather special hypothesis of key importance to only
a few rewrite rules, it is best to derive it only when needed. Thus
forward chaining is pro-active and backward chaining (rewriting) is
reactive.
Syntactic Restrictions
Forward chaining rules are generated from the corollary term (see
[rule-classes]) as follows. First, every [let] expression is
expanded away (hence, so is every [let*] and [lambda] expression),
and trivial ``guard holders'' are removed; see [guard-holders]. If
the resulting term has the form (implies hyp concl), then concl is
treated as a conjunction, with one forward chaining rule with
hypothesis hyp created for each conjunct. In the other case, where
the corollary term is not an [implies], we process it as we process
the conclusion in the first case.
Note that unlike rewrite rules, a nested implication is not folded
into a single implication. Consider for example the following term.
(implies (p1 x)
(implies (p2 x)
(p3 x)))
Although this term is parsed for a rewrite rule as (implies (and (p1
x) (p2 x)) (p3 x)), that is not the case when this term is parsed
for a forward-chaining rule, in which case (p1 x) is treated as the
hypothesis and (implies (p2 x) (p3 x)) is treated as the
conclusion.
The :trigger-terms field of a :forward-chaining rule class object
should be a non-empty list of terms, if provided, and should have
certain properties described below. If the :trigger-terms field is
not provided, it defaults to the singleton list containing the
``atom'' of the first hypothesis of the formula. (The atom of (not
x) is x; the atom of any other term is the term itself.) If there
are no hypotheses and no :trigger-terms were provided, an error is
caused.
A triggering term is acceptable if it is not a variable, a quoted
constant, a lambda application, a [let]- (or [let*]-) expression,
or a [not]-expression, and every variable symbol in the conclusion
of the theorem either occurs in the hypotheses or occurs in the
trigger.
More Details about Forward Chaining
:Forward-chaining rules are used by the simplifier before it begins
to rewrite the literals of the goal. (Forward chaining is thus
carried out from scratch for each goal.) If any term in the goal is
an instance of a trigger of some forward chaining rule, we try to
establish the hypotheses of that forward chaining theorem (from the
negation of the goal). To relieve a hypothesis we only use type
reasoning, evaluation of ground terms, and presence among our known
assumptions. We do not use rewriting. So-called free variables in
hypotheses are treated specially; see [free-variables]. If all
hypotheses are relieved, and certain heuristics approve of the
newly derived conclusion, we add the instantiated conclusion to our
known assumptions. Since this might introduce new terms into the
assumptions, forward chaining is repeated. Heuristic approval of
each new addition is necessary to avoid infinite looping as would
happen with the rule (implies (p x) (p (f x))), which might
otherwise forward chain from (p A) to (p (f A)) to (p (f (f A))),
etc.
Caution. Forward chaining does not actually add terms to the goals
displayed during proof attempts. Instead, it extends an associated
context, called ``assumptions'' in the preceding paragraph, that
ACL2 builds from the goal currently being proved. (For insiders:
forward chaining extends the [type-alist].) The context starts out
with ``obvious'' consequences of the negation of the goal. For
example, if the goal is
(implies (and (p A) (q (f A)))
(c A))
then the context notes that (p A) and (q (f A)) are non-nil and (c A)
is nil. Forward chaining is then used to expand the context. For
example, if a forward chaining rule has (f x) as a trigger term and
has body (implies (p x) (r (f x))), then the context is extended by
binding (r (f A)) to non-nil, provided the heuristics approve of
this extension. Note however that since (r (f A)) is put into the
context, not the goal, you will not see it in the goal formula.
Furthermore, the assumption added to the context is just the
instantiation of the conclusion of the rule, with no simplification
or rewriting applied. Thus, for example, if it contains an enabled
non-recursive function symbol it is unlikely ever to match a
(rewritten) term arising during subsequent simplification of the
goal.
However, forward-chaining does support the linear arithmetic
reasoning package. For example, suppose that forward-chaining puts
(< (f x) (g x)) into the context. Then this inequality also goes
into the linear arithmetic database, together with suitable
instances of linear lemmas whose trigger term is a call of g. See
[linear].
Debugging :forward-chaining rules can be difficult since their
effects are not directly visible on the goal being simplified.
Tools are available to help you discover what forward chaining has
occurred see [forward-chaining-reports].
Subtopics
[Case-split]
Like force but immediately splits the top-level goal on the
hypothesis
[Forward-chaining-reports]
To see reports about the forward chaining process")
(FORWARD-CHAINING-REPORTS
(FORWARD-CHAINING DEBUGGING)
"To see reports about the forward chaining process
Debugging forward-chaining rules can be hard because their effects
are not directly visible on the goal. In this documentation we tell
you how to get reports on the forward chaining activity occurring
in your proof attempts. This documentation is written in several
parts. The first part is an introduction for the first-time user of
forward chaining reports. The next two parts describe how to read
reports. The last part describes how to monitor forward chaining
activity only for selected runes, etc. We recommend the new user of
these reports read everything!
A Quick Introduction to Forward Chaining Reports
Caution: The reporting mechanism maintains some state, and if you
have already used forward chaining reporting in a session, the
directions below may not work as advertised! To return to the
default forward chaining reporting state, execute this form at the
top level:
(reset-fc-reporting)
You can get a report about all forward chaining activity in
subsequent proofs by doing:
(set-fc-criteria t)
Options will be discussed later that allow you to monitor the
activity caused by particular :forward-chaining rules or terms.
Then do a proof that is expected to cause some forward chaining. In
the proof output you will see lines like this:
(Forward Chaining on behalf of PREPROCESS-CLAUSE: (FC-Report 1))
This is the only difference you should see in the proof output.
After the proof attempt has terminated, you can execute:
(fc-report k)
for any k printed during the immediately preceding proof attempt.
That will print a much longer report describing the activity that
occurred during the kth use of forward chaining in that proof
attempt.
If you want to see these reports in real time (embedded in the proof
output), do this before invoking the prover:
(set-fc-report-on-the-fly t)
Collecting the data used to generate these reports slows down the
prover. If you no longer wish to see such reports, do
(set-fc-criteria nil)
How To Read FC Reports
The report printed by (fc-report k) is of the form:
Forward Chaining Report k:
Caller: token
Clause: (lit1 lit2 ... litn)
Number of Rounds: m
Contradictionp: bool
Activations: (act1 act2 ...)
This report means that the kth use of forward chaining in the most
recent proof attempt was done on behalf of token (see below). The
initial context (set of assumptions) consisted of the negations of
the literals listed in the clause shown and the initial candidate
trigger terms are all those appearing in that clause. This
invocation of forward chaining proceeded to do m rounds of
successive extensions of the initial context and ultimately either
reached a contradiction (bool = T) or returned an extended context
(bool = NIL). Note that reaching a contradiction from the negations
of all the literals in a clause is ``good'' because it means the
clause is true. The report concludes with the final status of all
the forward chaining rules fired during the process. We explain how
to read one of these activation reports in the next section.
Forward chaining is done on behalf of many proof techniques in the
system. Each is associated with a token. The main proof technique
that uses forward chaining is SIMPLIFY-CLAUSE. This is the call of
forward chaining that sets up the context used by the rewriter to
relieve hypotheses during backchaining. Another common caller of
forward chaining is PREPROCESS-CLAUSE, the first process in the
ACL2 waterfall (see [hints-and-the-waterfall]). Forward chaining
often proves ``near propositional'' goals (those depending just on
boolean implications between basic predicates). Other tokens you
may see include INDUCT, which uses forward chaining to set up a
context for applying :[induction] rules, and the definitional
principle (and related utilities such as [verify-termination] and
[verify-guards]) which uses forward chaining during the
construction of both measure conjectures and guard conjectures.
When used this way, the token is defun-or-guard-verification.
How to Read Activation Reports
The forward chaining report concludes with a list of activation
reports.
Activations: (act1 act2 ...)
Each acti is of the form:
(rune
(:TRIGGER inst-trig)
((:UNIFY-SUBST subst)
(:DISPOSITION outcome-part1 outcome-part2 inst-term))
...)
where the ... indicates that the rest of the report consists of more
of those tuples listing a :UNIFY-SUBST and :DISPOSITION. We call
each tuple a disposition of the activation and each disposition
describes a substitution subst identifying the final instantiation
of the rule and how the activation fared. Suppose there are n
dispositions. (If the rule in question contains no free variables,
n will be 1.)
This activation report means that during the forward chaining process
in question, the :[forward-chaining] [rune] rune was fired due to
the presence in the evolving context of the trigger term inst-trig.
(Note that inst-trig is an instantiation of the trigger term of the
named rule. That is, the variable symbols you see in inst-trig are
those of the clause printed in the forward chaining report.) The
activation of rune by inst-trig proceeded to split n ways as
different choices were made for the [free-variables] occuring among
the hypotheses. Each of those n choices gave rise to a different
substitution subst, and each succeeded or failed as described by
the corresponding :DISPOSITION.
The :DISPOSITION of an activation is described in three parts,
outcome-part1, outcome-part2, and inst-term. Outcome-part1 is
either SUCCESS or BLOCKED, meaning that the instance given by subst
either succeeded in the sense that all of its instantiated
hypotheses were found in the context, or failed because some
instantiated hypothesis was not found.
If outcome-part1 is SUCCESS then inst-term is the instantiated
conclusion produced by the rule. Outcome-part2 is APPROVED if the
instantiated conclusion was acceptable to our heuristics designed
to prevent looping and not already known in the evolving context.
Outcome-part2 is REJECTED if the instantiated conclusion was not
approved by our heuristics. Outcome-part2 is REDUNDANT if the
instantiated conclusion was approved by the heuristics but already
known true in the current evolving context. If APPROVED, the truth
of the instantiated conclusion is added to the evolving context.
Otherwise, it is not.
If outcome-part1 is BLOCKED then outcome-part2 is one of three
possible things: FALSE, in which case inst-term is an instantiated
hypothesis of the rule that is assumed false in the current
context, UNRELIEVED-HYP, in which case inst-term is an instantiated
hypothesis whose truthvalue is not determined by the context, or
UNRELIEVED-HYP-FREE, in which case inst-term is an oddly
instantiated hypothesis whose truthvalue is not determined by the
context and which also contains free variables. In the last case,
the ``odd'' instantiation was by the substitution subst but
extended so that free variables in the hypothesis are renamed to
start with the prefix UNBOUND-FREE- to draw your attention to them.
Note: All of the terms printed in the report are instantiated with
the relevant unifying substitution (possibly extended to bind free
variables).
Specifying the Tracking Criteria
During a proof attempt, the forward chaining module stores
information about the activations satisfying certain criteria. The
criteria is a list of triples. Each triple consists of a forward
chaining rune, an instantiated trigger term, and an instantiated
conclusion to watch for. However, any or all of the components of
such a triple may be t and that is given special significance.
An activation satisfies a criteria if it satisfies at least one of
the triples. An activation satisfies a triple if it satisfies all
three of the components. Every activation satisfies the component
t. An activation satisfies a rune if the activation describes a
firing of the named rule. An activation satisfies an instantiated
trigger term if the activation was created by that trigger being
present in the context. An activation satisfies an instantiated
conclusion if the activation could produce the instantiated
conclusion (with the right choice of any free variables).
Thus, the criteria is interpreted as a disjunction of conjunctions,
making it possible to track a specific set of runes, triggers, and
conclusions.
For example, here is a triple that might appear in the criteria:
((:FORWARD-CHAINING ALISTP-FORWARD-TO-TRUE-LISTP)
t
t).
This triple would cause every activation of the given rule to be
tracked. However, the triple
((:FORWARD-CHAINING ALISTP-FORWARD-TO-TRUE-LISTP)
(ALISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S))))
t)
would only track activations of that rule fired by the specific term
shown as the second element of the triple. Futhermore
(t
(ALISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S))))
t)
would track any forward chaining rule triggered by that term, and
(t
t
(TRUE-LISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S)))))
would track any rule fired by any trigger that might lead to the
specific term given as the third component above.
Note: The condition on how an activation satisfies an instantiated
conclusion is a little subtle. Consider the activation of the
forward chaining rule
(implies (and (symbol-listp x)
(equal (len x) (len y)))
(true-listp (make-bindings x y)))
triggered by (SYMBOL-LISTP VARS) arising in the current context. This
activation could produce the specific conclusion shown in the last
triple above, if it just happened that (TOP-N (OP1 INST) (STACK S))
were chosen as the binding of the free variable y. Thus, the
activation of this rule triggered by (SYMBOL-LISTP VARS) satisfies
the last triple above.
Observe that the triple
(t t t)
is satisfied by every activation of any rule by any trigger term
producing any conclusion.
The function set-fc-criteria sets the criteria describing which
activations are to be tracked. For example, if you execute:
(set-fc-criteria ((:FORWARD-CHAINING LEMMA1)
t t)
((:FORWARD-CHAINING LEMMA2)
(ALISTP (BASIC-MAPPER A B))
t)
(t t (TRUE-LISTP (DLT D)))),
the system would track all activations of the forward-chaining rule
LEMMA1, plus those activations of forward-chaining rule LEMMA2
triggered by the term given in the second triple, plus any
activation of any rule that might derive (TRUE-LISTP (DLT D)).
Because criteria generally mention variable symbols used in a
specific conjecture, it is probably best to reconsider your
criteria every time you want to track forward chaining.
If the criteria is nil, then nothing is tracked. Setting the criteria
to nil is the way you turn off tracking and reporting of forward
chaining activity. You may do this either by (set-fc-criteria) or
by (set-fc-criteria nil). (Technically the second form is an odd
use of set-fc-criteria, which expects any supplied arguments to be
triples; if the ``triple'' nil is the only one supplied, we take it
to mean that the entire criteria should be nil.)
To track every forward chaining activation you may set the criteria
with either (set-fc-criteria (t t t)) or use the abbreviation
(set-fc-criteria t).
If, when you read a forward chaining report, you see no mention of an
activation you have in mind, e.g., of a certain rune or deriving a
certain conclusion, and you have set the criteria correctly, then
the activation never happened. (This is akin to using :[brr] and
:[monitor] to monitor the application of a rewrite rule and then
seeing no interactive break.)
For some relevant functions to help you manage criteria and when the
full reports are printed see [fc-report], [show-fc-criteria],
[set-fc-criteria], [reset-fc-reporting], and
[set-fc-report-on-the-fly].
Subtopics
[Fc-report]
To report on the forward chaining activity in the most recent proof
[Reset-fc-reporting]
Reset the forward-chaining tracking state to its initial
configuration
[Set-fc-criteria]
To set the tracking criteria for forward chaining reports
[Set-fc-report-on-the-fly]
To determine when forward-chaining reports are printed
[Show-fc-criteria]
Print the forward-chaining tracking criteria")
(FOURTH
(NTH ACL2-BUILT-INS)
"Fourth member of the list
See any Common Lisp documentation for details.")
(FREE-VARIABLES
(RULE-CLASSES REWRITE)
"Free variables in rules
As described elsewhere (see [rule-classes]), ACL2 rules are treated
as implications for which there are zero or more hypotheses hj to
prove. In particular, rules of class :[rewrite] may look like this:
(implies (and h1 ... hn)
(fn lhs rhs))
Variables of hi are said to occur free in the above :rewrite rule if
they do not occur in lhs or in any hj with j<i. (To be precise,
here we are only discussing those variables that are not in the
scope of a [let]/[let*]/lambda that binds them.) We also refer to
these as the free variables of the rule. ACL2 may issue a warning
or error when there are free variables in a rule, as described
below. (Variables of rhs may be considered free if they do not
occur in lhs or in any hj. But we do not consider those in this
discussion.)
In general, the free variables of rules are those variables occurring
in their hypotheses (not [let]/[let*]/lambda-bound) that are not
bound when the rule is applied. For rules of class :[linear] and
:[forward-chaining], variables are bound by a trigger term. (See
[rule-classes] for a discussion of the :trigger-terms field). For
rules of class :[type-prescription], variables are bound by the
:typed-term field.
Let us discuss the method for relieving hypotheses of [rewrite] rules
with free variables. Similar considerations apply to [linear] and
[forward-chaining] rules, and [type-prescription] rules.
See [free-variables-examples] for more examples of how this all
works, including illustration of how the user can exercise some
control over it. In particular, see
[free-variables-examples-rewrite] for an explanation of output from
the [break-rewrite] facility in the presence of rewriting failures
involving free variables, as well as an example exploring ``binding
hypotheses'' as described below.
Note that the :match-free mechanism discussed below does not apply to
[type-prescription] rules. See [free-variables-type-prescription]
for a discussion of how to control free-variable matching for
[type-prescription] rules.
We begin with an example. Does the proof of the [thm] below succeed?
(defstub p2 (x y) t)
(defaxiom p2-trans
(implies (and (p2 x y)
(p2 y z))
(equal (p2 x z) t))
:rule-classes ((:rewrite :match-free :all)))
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
Consider what happens when the proof of the thm is attempted. The
ACL2 rewriter attempts to apply rule p2-trans to the conclusion,
(p2 a d). So, it binds variables x and z from the left-hand side of
the conclusion of p2-trans to terms a and d, respectively, and then
attempts to relieve the hypotheses of p2-trans. The first
hypothesis of p2-trans, (p2 x y), is considered first. Variable y
is free in that hypothesis, i.e., it has not yet been bound. Since
x is bound to a, the rewriter looks through the context for a
binding of y such that (p2 a y) is true, and it so happens that it
first finds the term (p2 a b), thus binding y to b. Now it goes on
to the next hypothesis, (p2 y z). At this point y and z have
already been bound to b and d; but (p2 b d) cannot be proved.
So, in order for the proof of the [thm] to succeed, the rewriter
needs to backtrack and look for another way to instantiate the
first hypothesis of p2-trans. Because :match-free :all has been
specified, backtracking does take place. This time y is bound to c,
and the subsequent instantiated hypothesis becomes (p2 c d), which
is true. The application of rule (p2-trans) succeeds and the
theorem is proved.
If instead :match-free :all had been replaced by :match-free :once in
rule p2-trans, then backtracking would not occur, and the proof of
the [thm] would fail.
Next we describe in detail the steps used by the rewriter in dealing
with free variables.
ACL2 uses the following sequence of steps to relieve a hypothesis
with free variables, except that steps (1) and (3) are skipped for
:forward-chaining rules and step (3) is skipped for
:type-prescription rules. First, if the hypothesis is of the form
(force hyp0) or (case-split hyp0), then replace it with hyp0.
(1) Suppose the hypothesis has the form (equiv var term) where var is
free and no variable of term is free, and either equiv is
[equal] or else equiv is a known [equivalence] relation and
term is a call of [double-rewrite]. We call this a ``binding
hypothesis.'' Then bind var to the result of rewriting term in
the current context.
(2) Look for a binding of the free variables of the hypothesis so
that the corresponding instance of the hypothesis is known to
be true in the current context.
(3) Search all [enable]d, hypothesis-free rewrite rules of the form
(equiv lhs rhs), where lhs has no variables (other than those
bound by [let], [let*], or lambda), rhs is known to be true in
the current context, and equiv is typically equal but can be
any equivalence relation appropriate for the current context
(see [congruence]); then attempt to bind the free variables so
that the instantiated hypothesis is lhs.
For cases (2) and (3), the first instance found may ultimately fail
because the remaining hypotheses are not all relieved under the
extended bindings. In that case, should the attempt to relieve
hypotheses fail, or should the search continue to find other
instances for (2) or (3)? The answer depends on which of two
options is in force for the so-called ``match-free'' of the rule.
Below we discuss how to specify these two options as ``:once'' or
``:all'' (the default), respectively.
Suppose that the original hypothesis is a call of [force] or
[case-split], where forcing is enabled (see [enable-forcing]) .
Also suppose that one of the following two cases applies: no
instances are found for (2) and also none for (3), or else the
``match-free'' option for the rule is :all (as discussed below) and
all attempts ultimately fail for (2) and (3) (because the remaining
hypotheses are not all relieved). Then the current hypothesis is
relieved but in the resulting split-off goals, all free variables
are bound to unusual names that call attention to this odd
situation.
Is it better to specify :once or :all? We believe that :all is
generally the better choice because of its greater power, provided
the user does not introduce a large number of rules with free
variables, which has been known to slow down the prover due to
combinatorial explosion in the search (Steps (2) and (3) above).
Either way, it is good practice to put the ``more substantial''
hypotheses first, so that the most likely bindings of free
variables will be found first (in the case of :all) or found at all
(in the case of :once). For example, a rewrite rule like
(implies (and (p1 x y)
(p2 x y))
(equal (bar x) (bar-prime x)))
may never succeed if p1 is nonrecursive and enabled, since we may
well not find calls of p1 in the current context. If however p2 is
disabled or recursive, then the above rule may apply if the two
hypotheses are switched. For in that case, we can hope for a match
of (p2 x y) in the current context that therefore binds x and y;
then the rewriter's full power may be brought to bear to prove (p1
x y) for that x and y.
Moreover, the ordering of hypotheses can affect the efficiency of the
rewriter. For example, the rule
(implies (and (rationalp y)
(foo x y))
(equal (bar x) (bar-prime x)))
may well be sub-optimal. Presumably the intention is to rewrite (bar
x) to (bar-prime x) in a context where (foo x y) is explicitly
known to be true for some rational number y. But y will be bound
first to the first term found in the current context that is known
to represent a rational number. If the 100th such y that is found
is the first one for which (foo x y) is known to be true, then
wasted work will have been done on behalf of the first 99 such
terms y --- unless :once has been specified, in which case the rule
will simply fail after the first binding of y for which (rationalp
y) is known to be true. Thus, a better form of the above rule is
almost certainly the following.
(implies (and (foo x y)
(rationalp y))
(equal (bar x) (bar-prime x)))
Specifying `once' or `all'.
As noted above, the following discussion applies only to [rewrite],
[linear], and [forward-chaining] rules. See
[free-variables-type-prescription] for a discussion of analogous
considerations for [type-prescription] rules.
One method for specifying :once or :all for free-variable matching is
to provide the :match-free field of the :rule-classes of the rule,
for example, (:rewrite :match-free :all). See [rule-classes].
However, there are global events that can be used to specify :once
or :all; see [set-match-free-default] and see
[add-match-free-override]. Here are some examples.
(set-match-free-default :once) ; future rules without a :match-free field
; are stored as :match-free :once (but this
; behavior is local to a book)
(add-match-free-override :once t) ; existing rules are treated as
; :match-free :once regardless of their
; original :match-free fields
(add-match-free-override :once (:rewrite foo) (:rewrite bar . 2))
; the two indicated rules are treated as
; :match-free :once regardless of their
; original :match-free fields
Some history. Before Version 2.7 the ACL2 rewriter performed Step (2)
above first. More significantly, it always acted as though :once
had been specified. That is, if Step (2) did not apply, then the
rewriter took the first binding it found using either Steps (1) or
(3), in that order, and proceeded to relieve the remaining
hypotheses without trying any other bindings of the free variables
of that hypothesis.
Subtopics
[Add-match-free-override]
Set :match-free value to :once or :all in existing rules
[Free-variables-examples]
Examples pertaining to free variables in rules
[Free-variables-type-prescription]
Matching for free variable in [type-prescription] rules
[Set-match-free-default]
Provide default for :match-free in future rules
[Set-match-free-error]
Control error vs. warning when :match-free is missing")
(FREE-VARIABLES-EXAMPLES
(FREE-VARIABLES)
"Examples pertaining to free variables in rules
The examples in the two sub-topics of this topic illustrate the
handling of free variables in rules of class :[rewrite] (see
[free-variables-examples-rewrite]) and of class :[forward-chaining]
(see [free-variables-examples-forward-chaining]), respectively.
These implicitly illustrate [free-variables] handling in rules of
class :[linear] as well. Also see [free-variables] and see
[rule-classes].
Subtopics
[Free-variables-examples-forward-chaining]
Examples pertaining to free variables in [forward-chaining] rules
[Free-variables-examples-rewrite]
Examples pertaining to free variables in [rewrite] rules")
(FREE-VARIABLES-EXAMPLES-FORWARD-CHAINING
(FREE-VARIABLES-EXAMPLES)
"Examples pertaining to free variables in [forward-chaining] rules
The following examples illustrate ACL2's handling of free variables
in [forward-chaining] rules, as well as user control over how such
free variables are handled. See [free-variables] for a background
discussion.
; First let us introduce a transitive operation, op, and prove a
; forward-chaining rule stating the transitivity of op.
(encapsulate
(((op * *) => *))
(local (defun op (x y) (< x y)))
(defthm transitivity-of-op
(implies (and (op x y) (op y z)) (op x z))
:rule-classes :forward-chaining))
; The following theorem is proved by forward chaining, using the above rule.
(thm
(implies (and (op u v) (op v w) (op v a))
(op u w)))
; The proof of the theorem just above succeeds because the term (op u v)
; triggers the application of forward-chaining rule transitivity-of-op,
; binding x to u and y to v. Free variable z of that rule is bound to both w
; and to a, resulting in the addition of both (op u w) and (op u a) to the
; context. However, (op v a) happens to be at the front of the context, so
; if only one free-variable binding had been allowed, then z would have only
; been bound to a, not to w, as we now illustrate.
(add-match-free-override :once (:forward-chaining transitivity-of-op))
(thm ; FAILS!
(implies (and (op u v) (op v w) (op v a))
(op u w)))
:ubt! 1
; Starting over, this time we prove transitivity-of-op as a :match-free :once
; forward-chaining rule. Note that the presence of :match-free eliminates
; the free-variables warning that we got the first time.
(encapsulate
(((op * *) => *))
(local (defun op (x y) (< x y)))
(defthm transitivity-of-op
(implies (and (op x y) (op y z)) (op x z))
:rule-classes ((:forward-chaining :match-free :once))))
(thm ; FAILS!
(implies (and (op u v) (op v w) (op v a))
(op u w)))
; Notice that if we swap the order of the last two hypotheses the theorem
; goes through, because this time (op v w) is first in the context.
(thm ; SUCCEEDS!
(implies (and (op u v) (op v a) (op v w))
(op u w)))
:u
; Now let's try setting the default to :once.
(set-match-free-default :once)
; We still get a free-variables warning when we admit this forward-chaining rule.
(encapsulate
(((op * *) => *))
(local (defun op (x y) (< x y)))
(defthm transitivity-of-op
(implies (and (op x y) (op y z)) (op x z))
:rule-classes ((:forward-chaining))))
; This theorem fails--as it should.
(thm ; FAILS!
(implies (and (op u v) (op v w) (op v a))
(op u w)))
; But if we convert this rule (or here, all possible rules) to :all rules,
; then the proof succeeds.
(add-match-free-override :all t)
(thm ; SUCCEEDS!
(implies (and (op u v) (op v w) (op v a))
(op u w)))
; Now let's test a relatively slow :all case (the next thm below).
:ubt! 1
(encapsulate
(((op1 *) => *)
((op3 * * *) => *))
(local (defun op1 (x) (declare (ignore x)) t))
(local (defun op3 (x0 x1 x2)
(declare (ignore x0 x1 x2))
t))
(defthm op1-op3-property
(implies (and (op1 x0) (op1 x1) (op1 x2))
(op3 x0 x1 x2))
:rule-classes ((:forward-chaining :match-free :all))))
; The following succeeds, but takes a little time (about a second in one run).
(thm (implies
(and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
(op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
(op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
(op1 a17) (op1 a18) (op1 a19) (op1 a20))
(op3 a5 a6 a0)))
(add-match-free-override :once t)
; The same theorem now fails because of the add-match-free-override, but is
; more than an order of magnitude faster.
(thm (implies
(and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
(op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
(op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
(op1 a17) (op1 a18) (op1 a19) (op1 a20))
(op3 a5 a6 a0)))
; A slight variant succeeds in a negligible amount of time (still with the
; :once override above).
(thm (implies
(and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
(op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
(op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
(op1 a17) (op1 a18) (op1 a19) (op1 a20))
(op3 a5 a20 a20)))
; Reality check: This shouldn't give a free-variables warning, and everything
; should work great since there are no free variables with this trigger term.
:ubt! 1
(encapsulate
(((op1 *) => *)
((op7 * * * * * * *) => *))
(local (defun op1 (x)
(declare (ignore x))
t))
(local (defun op7 (x0 x1 x2 x3 x4 x5 x6)
(declare (ignore x0 x1 x2 x3 x4 x5 x6))
t))
(defthm op1-op7-property
(implies (and (op1 x0) (op1 x1) (op1 x2)
(op1 x3) (op1 x4) (op1 x5) (op1 x6))
(op7 x0 x1 x2 x3 x4 x5 x6))
:rule-classes ((:forward-chaining
:trigger-terms ((op7 x0 x1 x2 x3 x4 x5 x6))))))
; The following then succeeds, and very quickly.
(thm (implies (and (op1 a0) (op1 a1) (op1 a2)
(op1 a3) (op1 a4) (op1 a5) (op1 a6))
(op7 a4 a6 a5 a6 a6 a6 a6)))")
(FREE-VARIABLES-EXAMPLES-REWRITE
(FREE-VARIABLES-EXAMPLES)
"Examples pertaining to free variables in [rewrite] rules
The following examples illustrate ACL2's handling of free variables
in [rewrite] rules, as well as user control over how such free
variables are handled. See [free-variables] for a background
discussion.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Example 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defstub p2 (x y) t) ; introduce unconstrained function
; Get warning because of free variable. This would be an error if you had
; first executed (set-match-free-error t) in order to force yourself to
; specify :match-free (illustrated later, below).
(defaxiom p2-trans
(implies (and (p2 x y)
(p2 y z))
(p2 x z)))
; Succeeds.
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
; The following causes an error because p2-trans is not a rune.
(add-match-free-override :once p2-trans)
; After the following, the rewrite rule p2-trans will only allow one
; attempt per hypothesis to bind free variables.
(add-match-free-override :once (:rewrite p2-trans))
; Now this same theorem fails to be proved. Here's why. The
; context for proving (p2 a d) happens to include the hypotheses in
; reverse order. So when the first hypothesis of p2-trans, namely
; (p2 x y), is relieved, where x is bound to a (as we are attempting
; to rewrite the current literal (p2 a d)), we find (p2 a b) in the
; context before (p2 a c) and hence y is bound to b. The
; instantiated second hypothesis of p2-trans is thus (p2 b d), and
; the proof fails. Before the add-match-free-override form above,
; the proof succeeded because the rewriter was allowed to backtrack
; and find the other binding for the first hypothesis of p2-trans,
; namely, y bound to c. Then the instantiated second hypothesis of
; p2-trans is (p2 c d), which is known to be true in the current
; context.
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
; Return to original behavior for binding free variables.
(add-match-free-override :all t)
; Succeeds once again.
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
(u) ; undo (add-match-free-override :all t)
; This is an error, since no further arguments should appear after
; :clear.
(add-match-free-override :clear t)
; Return all rules to original behavior for binding free variables,
; regardless of which previous add-match-free-override forms have
; been executed.
(add-match-free-override :clear)
; This succeeds just as it did originally.
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
(ubt! 'p2-trans) ; back to the start, except retain the defstub
; Require that :match-free be specified for :linear and :rewrite rules with
; free variables.
(set-match-free-error t)
; Fails because :match-free is missing.
(defaxiom p2-trans
(implies (and (p2 x y)
(p2 y z))
(p2 x z)))
; Fails because :match-free must be followed by :once or :all.
(defaxiom p2-trans
(implies (and (p2 x y)
(p2 y z))
(p2 x z))
:rule-classes ((:rewrite :match-free nil)))
; Succeeds, this time with no warning at all.
(defaxiom p2-trans
(implies (and (p2 x y)
(p2 y z))
(p2 x z))
:rule-classes ((:rewrite :match-free :once)))
; Fails because we only bind once (see earlier long comment).
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
; Treat p2-trans as though `:match-free :all' had been specified.
(add-match-free-override :all (:rewrite p2-trans))
; Succeeds since more than one binding is allowed for p2-trans.
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
(u)
(u)
; Specify that future :linear and :rewrite rules with free variables
; that do not have :match-free specified are treated as though
; `:match-free :once' were specified.
(set-match-free-default :once)
; Succeeds without error since `:match-free' is specified, as described
; above. But there is a warning, since :match-free is not specified for this
; :rewrite rule.
(defaxiom p2-trans
(implies (and (p2 x y)
(p2 y z))
(p2 x z)))
; Fails since only single bindings are allowed for p2-trans.
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
; Treat p2-trans as though `:match-free :all' had been specified.
(add-match-free-override :all t)
; Succeeds.
(thm (implies (and (p2 a c)
(p2 a b)
(p2 c d))
(p2 a d)))
; Test searching of ground units, i.e. rewrite rules without variables on the
; left side of the conclusion, for use in relieving hypotheses with free
; variables. This is a very contrived example.
(ubt! 1) ; back to the start
(encapsulate
(((p1 *) => *)
((p2 * *) => *)
((p3 *) => *)
((a) => *)
((b) => *))
(local (defun p1 (x) x))
(local (defun p2 (x y) (list x y)))
(local (defun p3 (x) x))
(local (defun a () 0))
(local (defun b () 0)))
; Allow default of :match-free :all (form may be omitted).
(set-match-free-error nil)
(defaxiom ax1
(implies (and (p2 x y)
(p1 y))
(p3 x)))
(defaxiom p2-a-b
(p2 (a) (b)))
(defaxiom p2-a-a
(p2 (a) (a)))
(defaxiom p1-b
(p1 (b)))
; Succeeds; see long comment below on next attempt to prove this
; theorem.
(thm (implies (p2 (a) y)
(p3 (a))))
; Now ax1 will only relieve hypothesis (p2 x y) for one binding of y:
(add-match-free-override :once t)
; Fails when ax1 attempts to rewrite the conclusion to true, because
; the most recent ground unit for hypothesis (p2 x y) with x bound
; to (a) is rule p2-a-a, which binds y to (a). If more than one ground
; unit could be used then we would backtrack and apply rule p2-a-b,
; which binds y to (b) and hence hypothesis (p1 y) of ax1 is
; relieved by rule p1-b.
(thm (implies (p2 (a) y)
(p3 (a))))
; Return rules to original :match-free behavior.
(add-match-free-override :clear)
; Succeeds once again.
(thm (implies (p2 (a) y)
(p3 (a))))
; Just for kicks, change the behavior of a built-in rule irrelevant
; to the proof at hand.
(add-match-free-override :once (:rewrite string<-l-trichotomy))
; Still succeeds.
(thm (implies (p2 (a) y)
(p3 (a))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Example 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
The next example illustrates the use of the [break-rewrite] facility
to get information about handling of free variables by the
rewriter. Explanation is given after this (edited) transcript.
Input begins on lines with a prompt (search for ``ACL2''); the rest
is output.
ACL2 !>(encapsulate
((p1 (u x) t)
(bad (x) t)
(p2 (x y z) t)
(bar (x y) t)
(foo (x y) t)
(poo (x y) t)
(prop (u) t))
(local (defun p1 (u x) (declare (ignore u x)) nil))
(local (defun bad (x) (declare (ignore x)) nil))
(local (defun p2 (x y z) (declare (ignore x y z)) nil))
(local (defun bar (x y) (declare (ignore x y)) nil))
(local (defun foo (x y) (declare (ignore x y)) nil))
(local (defun poo (x y) (declare (ignore x y)) nil))
(local (defun prop (u) (declare (ignore u)) t))
(defthm foo-poo
(implies (syntaxp (equal y 'y3))
(equal (foo x y)
(poo x y))))
(defthm lemma-1
(implies (and (p1 u x)
(bad x)
(p2 x y z)
(bar x y)
(equal x x) ; admittedly silly!
(foo x y))
(prop u))
:rule-classes ((:rewrite :match-free :all))))
; [[ output omitted ]]
Summary
Form: ( ENCAPSULATE ((P1 ...) ...) ...)
Rules: NIL
Warnings: Subsume and Non-rec
Time: 0.08 seconds (prove: 0.00, print: 0.01, other: 0.06)
T
ACL2 !>:brr t
The monitored runes are:
NIL
T
ACL2 !>:monitor (:rewrite lemma-1) t
(((:REWRITE LEMMA-1) 'T))
ACL2 !>(thm (implies (and (p1 u0 x1)
(bad x1)
(bad x3)
(bar x3 y1)
(bar x3 y3)
(p1 u0 x2)
(p1 u0 x3)
(p2 x3 y1 z1)
(p2 x3 y3 z1))
(prop u0)))
(1 Breaking (:REWRITE LEMMA-1) on (PROP U0):
1 ACL2 >:eval
1x (:REWRITE LEMMA-1) failed because :HYP 1 contains free variables.
The following display summarizes the attempts to relieve hypotheses
by binding free variables; see :DOC free-variables.
[1] X : X1
Failed because :HYP 3 contains free variables Y and Z, for which no
suitable bindings were found.
[1] X : X2
Failed because :HYP 2 rewrote to (BAD X2).
[1] X : X3
[3] Z : Z1
Y : Y1
Failed because :HYP 6 rewrote to (FOO X3 Y1).
[3] Z : Z1
Y : Y3
Failed because :HYP 6 rewrote to (POO X3 Y3).
1 ACL2 >:unify-subst
U : U0
1 ACL2 >
The :eval command above asks the rewriter to attempt to apply the
rewrite rule lemma-1 to the term (prop u0), shown just above the
line with :eval. As we can see at the end, the variable u in the
conclusion of lemma-1 is being bound to the variable u0 in the
conjecture. The first hypothesis of lemma-1 is (p1 u x), so the
rewriter looks for some x for which (p1 u0 x) is known to be true.
It finds x1, and then goes on to consider the second hypothesis,
(bad x). Since the theorem we are proving has (bad x1) in the
hypothesis and x is currently bound to x1, the rewriter is
satisfied and moves on to the third hypothesis of lemma-1, (p2 x y
z). However, x is bound to x1 and there are no instances of y and z
for which (p2 x1 y z) is known in the current context. All of the
above analysis is summarized in the first part of the output from
:eval above:
[1] X : X1
Failed because :HYP 3 contains free variables Y and Z, for which no
suitable bindings were found.
Thus, the binding of x to x1 on behalf of the first hypothesis has
failed.
The rewriter now backs up to look for other values of x that satisfy
the first hypothesis, and finds x2 because our current theorem has
a hypothesis of (p1 u0 x2). But this time, the second hypothesis of
lemma-1, (bad x), is not known to be true for x; that is, (bad x2)
does not rewrite to t; in fact, it rewrites to itself. That
explains the next part of the output from :eval above:
[1] X : X2
Failed because :HYP 2 rewrote to (BAD X2).
The rewriter now backs up again to look for other values of x that
satisfy the first hypothesis, and finds x3 because our current
theorem has a hypothesis of (p1 u0 x3). This time, the second
hypothesis of lemma-1 is not a problem, and moreover, the rewriter
is able to bind y and z to y1 and z1, respectively, in order to
satisfy the third hypothesis, (p2 x y z): that is, (p2 x2 y1 z1) is
known in the current context. That explains more of the above
output from :eval:
[1] X : X3
[3] Z : Z1
Y : Y1
Unfortunately, the sixth hypothesis, (foo x y), rewrites to itself
under the above bindings:
Failed because :HYP 6 rewrote to (FOO X3 Y1).
So the rewriter looks for other bindings to satisfy the third
hypothesis and finds these.
[3] Z : Z1
Y : Y3
This time, the sixth hypothesis can be rewritten under the above
bindings, from (foo x3 y3) to (poo x3 y3) by lemma foo-poo, but
still not to t.
Failed because :HYP 6 rewrote to (POO X3 Y3).
There are no more free variable bindings to try, so this concludes
the output from :eval.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Example 3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
The next pair of examples illustrates so-called ``binding
hypotheses'' (see [free-variables]) and explores some of their
subtleties. The first shows binding hypotheses in action on a
simple example. The second shows how binding hypotheses interact
with equivalence relations and explains the role of
[double-rewrite].
Our first example sets up a theory with two user-supplied rewrite
rules, one of which has a binding hypothesis. Below we explain how
that binding hypothesis contributes to the proof.
; Define some unary functions.
(defun f (x) (declare (ignore x)) t)
(defun g (x) x)
(defun h (x) x)
(defun k (x) x)
; Prove some simple lemmas. Note the binding hypothesis in g-rewrite.
(defthm f-k-h
(f (k (h x))))
(defthm g-rewrite
(implies (and (equal y (k x)) ; binding hypothesis
(f y))
(equal (g x) y)))
; Restrict to a theory that includes the above lemmas but avoids the above
; definitions.
(in-theory (union-theories (theory 'minimal-theory)
'(f-k-h g-rewrite)))
; Prove a theorem.
(thm (equal (g (h a)) (k (h a))))
Let us look at how ACL2 uses the above binding hypothesis in the
proof of the preceding thm form. The rewriter considers the term (g
(h a)) and finds a match with the left-hand side of the rule
g-rewrite, binding x to (h a). The first hypothesis binds y to the
result of rewriting (k x) in the current context, where the
variable x is bound to the term (h a); thus y is bound to (k (h
a)). The second hypothesis, (f y), is then rewritten under this
binding, and the result is t by application of the rewrite rule
f-k-h. The rule g-rewrite is then applied under the
already-mentioned binding of x to (h a). This rule application
triggers a recursive rewrite of the right-hand side of g-rewrite,
which is y, in a context where y is bound (as discussed above) to
(k (h a)). The result of this rewrite is that same term, (k (h a)).
The original call of equal then trivially rewrites to t.
We move on now to our second example, which is similar but involves a
user-defined equivalence relation. You may find it helpful to
review :equivalence rules; see [equivalence].
Recall that when a hypothesis is a call of an equivalence relation
other than equal, the second argument must be a call of
[double-rewrite] in order for the hypothesis to be treated as a
binding hypothesis. That is indeed the case below; an explanation
follows.
; Define an equivalence relation.
(defun my-equiv (x y) (equal x y))
(defequiv my-equiv) ; introduces rule MY-EQUIV-IS-AN-EQUIVALENCE
; Define some unary functions
(defun f (x) (declare (ignore x)) t)
(defun g (x) x)
(defun h1 (x) x)
(defun h2 (x) x)
; Prove some simple lemmas. Note the binding hypothesis in lemma-3.
(defthm lemma-1
(my-equiv (h1 x) (h2 x)))
(defthm lemma-2
(f (h2 x)))
(defthm lemma-3
(implies (and (my-equiv y (double-rewrite x)) ; binding hypothesis
(f y))
(equal (g x) y)))
; Restrict to a theory that includes the above lemmas but avoids the above
; definitions.
(in-theory (union-theories (theory 'minimal-theory)
'(lemma-1 lemma-2 lemma-3
my-equiv-is-an-equivalence)))
; Prove a theorem.
(thm (equal (g (h1 a)) (h2 a)))
The proof succeeds much as in the first example, but the following
observation is key: when ACL2 binds y upon considering the first
hypothesis of lemma-3, it rewrites the term (double-rewrite x) in a
context where it need only preserve the equivalence relation
my-equiv. At this point, x is bound by applying lemma-3 to the term
(g (h1 a)); so, x is bound to (h1 a). The rule lemma-1 then applies
to rewrite this occurrence of x to (h2 a), but only because it
suffices to preserve my-equiv. Thus y is ultimately bound to (h2
a), and the proof succeeds as one would expect.
If we tweak the above example slightly by disabling the user's
[equivalence] [rune], then the proof of the [thm] form fails
because the above rewrite of (double-rewrite x) is done in a
context where it no longer suffices to preserve my-equiv as we dive
into the second argument of my-equiv in the first hypothesis of
lemma-3; so, lemma-1 does not apply this time.
(in-theory (union-theories (theory 'minimal-theory)
'(lemma-1 lemma-2 lemma-3)))
; Proof fails in this case!
(thm (equal (g (h1 a)) (h2 a)))")
(FREE-VARIABLES-TYPE-PRESCRIPTION
(FREE-VARIABLES)
"Matching for free variable in [type-prescription] rules
We assume familiarity with the issue of dealing with free variables
in hypotheses; see [free-variables].
By default, starting with Version 4.3, ACL2 attempts all possible
matches for free variables. Consider the following example.
(defstub f1 (x) t)
(defstub f2 (x y) t)
(defstub f3 (y) t)
(defaxiom f1-prop
(implies (and (f2 x y) ; <-- y is free in this hypothesis
(f3 y))
(f1 x)) ; <-- (f1 x) is the type-term (type is `non-nil')
:rule-classes :type-prescription)
; Succeeds:
(thm (implies (and (f2 a b)
(f3 b))
(f1 a)))
; The following fails unless we try more than one match for free variables in
; hypotheses.
(thm (implies (and (f2 a b)
(f2 a c)
(f2 a d)
(f3 b))
(f1 a)))
There may be times when you want to match only the first free
variable. In that case, you can write a function of two arguments,
the type-prescription [rune] being applied and the current ACL2
world, that prohibits multiple matching for those times. Your
function is then `attached' to the built-in constrained function,
oncep-ts. The following examples are intended to explain how this
works.
First, let us disallow all mutliple matching of free variables (i.e.,
implement the behavior often referred to as ``:match-free :once'';
see [free-variables]).
(defun oncep-tp-always (rune wrld)
(declare (ignore rune wrld)
(xargs :mode :logic :guard t))
t)
(defattach oncep-tp oncep-tp-always)
The second thm form above will now fail, because only one
free-variable match is permitted for the first hypothesis of rule
f1-prop above.
Now suppose that instead, we want to disallow multiple matches for
free variables in hypotheses of type-prescription rules except for
the rule f1-prop above. With the following events, the second thm
form above once again succeeds.
(defun oncep-tp-always-except-f1-prop (rune wrld)
(declare (ignore wrld)
(xargs :mode :logic :guard (and (consp rune)
(consp (cdr rune))
(symbolp (cadr rune)))))
(not (eq (base-symbol rune) 'f1-prop)))
(defattach oncep-tp oncep-tp-always-except-f1-prop)
In general, your [defattach] event will attach a function symbol to
oncep-tp. The [guard] of that function symbol must be implied by
the guard of oncep-tp:
ACL2 !>:args oncep-tp
Function ONCEP-TP
Formals: (RUNE WRLD)
Signature: (ONCEP-TP * *)
=> *
Guard: (AND (PLIST-WORLDP WRLD)
(CONSP RUNE)
(CONSP (CDR RUNE))
(SYMBOLP (CADR RUNE)))
Guards Verified: T
Defun-Mode: :logic
Type: built-in (or unrestricted)
ONCEP-TP
ACL2 !>")
(FREE_VARIABLES_IN_TOP-LEVEL_INPUT
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Free Variables in Top-Level Input
ACL2 !>(equal (app (app a b) c)
(app a (app b c))))
ACL2 Error in TOP-LEVEL: Global variables, such as C, B, and A, are
not allowed. See :DOC ASSIGN and :DOC @.
ACL2 does not allow ``global variables'' in top-level input. There is
no ``top-level binding environment'' to give meaning to these
variables.
Thus, expressions involving no variables can generally be evaluated,
ACL2 !>(equal (app (app '(1 2) '(3 4)) '(5 6))
(app '(1 2) (app '(3 4) '(5 6))))
(1 2 3 4 5 6)
but expressions containing variables cannot.
There is an exception to this rule. References to ``single-threaded
objects'' may appear in top-level forms. See [stobj] [{ICON}]. A
single-threaded object is an ACL2 object, usually containing many
fields, whose use is syntactically restricted so that it may be
given as input only to certain functions and must be returned as
output by certain functions. These restrictions allow single-
threaded objects to be efficiently manipulated. For example, only a
single copy of the object actually exists, even though from a
logical perspective one might expect the object to be ``copied on
write.''
The most commonly used single-threaded object in ACL2 is the ACL2
system state, whose current value is always held in the variable
[state] [{ICON}].
ACL2 provides a way for you to use state to save values of
computations at the top-level and refer to them later. See [assign]
[{ICON}] and [@] [{ICON}].")
(FREQUENTLY-ASKED-QUESTIONS-BY-NEWCOMERS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Some questions newcomers frequently ask
This FAQ is for people who've read through all the other sections of
the tutorial introduction to the theorem prover (see
[introduction-to-the-theorem-prover] and all the links from it that
are not marked with the little warning sign (``[{ICON}]''). Do not
expect to understand our answers if you haven't taken the time to
read through the tutorial. In the answers below you will see more
links into the hypertext reference manual. While such links were
marked ``[{ICON}]'' in the tutorial, they are not marked that way
here. When you enter the reference manual be prepared to explore
and assemble a mini-course on the topic of interest, not a quick
fix.
Q. How do I find something in the ACL2 documentation? A. Try going to
the Search link on the ACL2 home page.
Q. How does the theorem prover work? A. We really don't think you
need to know much about the inner workings of the prover to become
an effective user. That doesn't mean the system is
self-explanatory! It means that stuff you need to learn is not how
the theorem prover works but how to interact with it! That is what
[introduction-to-the-theorem-prover] is about. However, if you want
the most basic overview of the prover, see
[architecture-of-the-prover].
Q. How do I define a new function? A. See [defun].
Q. How do I define a new predicate? A. See [defun].
Q. How do I define a new relation? A. See [defun].
Q. How do I define a function or predicate that takes a varying
number of arguments? A. You can't. However, see [defmacro] to learn
how to define a macro that takes a varying number of arguments and
expands into an arbitrary term that you compute.
Q. How do I define a macro that is sensitive to the state? A. You
can't. However, advanced users should consider [make-event].
Q. How do I define mutually recursive functions? A. See
[mutual-recursion]. However, you should realize that when two
functions, say f and g, are mutually recursive, properties of f
generally have to be stated simultaneously with properties of g,
since inductive proofs about one function require inductive
hypotheses about the other. Furthermore, ACL2 does not know how to
do inductions for mutually recursive functions and must be told.
See [mutual-recursion-proof-example].
Q. How do I declare the type signature of a function? A. You can't.
ACL2 is a syntactically untyped language and all functions are
defined on all objects in the ACL2 universe. We recommend that the
new user get used to this and only then explore the use of ACL2 to
express and enforce a type regime. In ACL2, the guard of a function
is akin to the type signature of a function in typed languages.
However, ACL2 guards may be arbitrary terms, not just type
conditions, they only concern the inputs to the function (not its
result), and do not affect the axiom defining the function -- all
functions are defined on every combination of objects. You may, of
course, prove theorems that establish that every function called in
a definition or theorem is supplied with input satisfying its
guards (which necessarily involves describe the outputs too). These
formulas are called guard conjectures and the process of proving
them is called guard verification. Since guards are arbitrary ACL2
formulas, the ``type regimes'' one tends to enforce in ACL2 can be
much for flexible and expressive than those in most programming
languages. However, that expressibility also means guard
verification can be challenging (indeed undecidable). On the other
hand, if one limits oneself to simple type-like guards, lemmas can
be proved that make most guard verification fully automatic and one
can configure ACL2 to do guard verification automatically at
defun-time. One may also delay guard verification until ``the
right'' lemmas have been proved. By doing guard verification one
can make functions execute faster by allowing the code to avoid
runtime checks. This is especially valuable to industrial users who
have large models used both in verification and as simulation
engines for designed artifacts. In addition, guard verification can
give you the assurance that you are using your functions within
their intended domains and hence is a form of functional
specification and verification. However, all these advantages
aside, it is remarkably easy to drift away from the simplest type
regimes and write a guard that raises deep mathematical problems.
New users should not try to confront these problems until they are
comfortable with the theorem prover and with lemma development.
Therefore, we strongly recommend that you forget about types and
guards and get used to reasoning about total functions. When you do
decide to learn about them, be prepared for a complex story
involving specification, execution efficiency, and proof
management. See [guard].
Q. How do I tell defun what measure to use? A. See [xargs],
specifically :measure.
Q. I specified a measure that always returns a natural number but
ACL2 is acting like it's not a natural number. A. There are two
likely problems. The most likely one is that your measure isn't
really always a natural! Suppose the formals of your defun are x
and y and your measure is (m x y). Suppose the recursive calls of
your function are protected by tests that insure that x and y are
naturals. Then you might assume x and y are naturals in the
measure. But ACL2 has to prove (o-p (m x y)), where [o-p] is the
predicate that recognizes ordinals (and naturals are ordinals).
Note that the theorem doesn't have any hypotheses! You might
intuitively think that your measure has to be an ordinal just under
the conditions that lead to recursive calls. That's not what ACL2
enforces. It has to be an ordinal, always. So you must change your
specified measure. For example, consider wrapping [nfix] around it
or around its uses of x and y to coerce those quantities to
naturals. The second most likely explanation is that your measure
returns a natural, always, but ACL2 doesn't know that and it takes
induction to prove. This might happen if m involves some recursive
functions. In this case, prove (natp (m x y)) before your defun.
Perhaps you should consider making the natp lemma a
:[type-prescription] lemma to make ACL2's typing algorithm aware of
it.
Q. How do I tell defun what well-founded relation to use? A. See
[xargs], specifically :well-founded-relation.
Q. How do I show that a relation is well-founded? A. Prove a theorem
establishing that there is an order preserving embedding into the
ordinals and store it with :rule-classes :[well-founded-relation].
Q. What is an ordinal? What does it mean to be well-founded? A.
Ordinals are an extension of the natural numbers used to insure
that a process can't go on forever. Like naturals, they can be
added, multiplied, and exponentiated. There is a sense of one
ordinal being less than another. Unlike the naturals, each of which
is finite, the ordinals include infinite objects. Now imagine
``standing'' on an ordinal and ``stepping'' to a smaller one. Like
the naturals, this ``walk down the ordinals'' can't go on forever,
even if you start on an infinite ordinal. That is because the
ordinals are well-founded. See [o-p] for more information about
ordinals in ACL2 and about well-foundedness. See [ordinals] for a
deeper discussion and a discussion of books that can help configure
ACL2 to reason about ordinals.
Q. How can provide hints for the termination proofs in defun? A. See
[xargs], specifically :hints (for the termination proofs) and
:guard-hints (for the guard verification proofs).
Q. How do I define a constant (something like a global variable)? A.
See [defconst]. But remember that as an applicative programming
language, ACL2 does not have global variables! You can define a
symbol to have a fixed value and use the symbol sort of like a
global variable in function definitions: you may refer to the value
of the symbol in your functions without passing the variable in as
formal parameter. But you may not ever change the value of the
symbol!
Q. How do I save the value of a top-level computation for future use?
A. See [assign] and see [@].
Q. How do I introduce new syntactic form or abbreviation? A. See
[defmacro].
Q. How can create and modify an array? A. ACL2 is a functional
language, so it is impossible to destructively modify an existing
object; technically, all ``updates'' to objects must be implemented
by ``copy-on-write'' semantics. That said, ACL2 provides support
for [arrays], provided you use them in a restricted way. They give
you constant-time access and change under the use restrictions.
Q. How do I read from or write to a file? How do I do IO? A. To
manipulate files, your function must have [state] as an argument,
so you should read about the restrictions that imposes. For
input/output facilities, see [io].
Q. How do I define a structure that can be destructively modified? A.
ACL2 is an applicative programming language. You can't modify
objects arbitrarily! You basically have to ``copy on write,'' which
means you construct new objects from old ones, making the changes
you want in the new one. If the car of some object is 1 at one
moment and 2 later, then the basic logical axiom (car x) = (car x)
is violated! However, if the only reference to the old object,
e.g., x, was to pass it to the code that copied and ``changed'' it,
then ACL2 can re-use the old object to produce the new one and the
axioms would not object. Such syntactic restrictions can make x a
modifiable structure but they will impose a heavy burden on you as
a programmer: if pass such an x to a function and the function
modifies it, then you must pass x only to that function and you
must return the modified value and use it henceforth. Such objects
are said to be single threaded. See [defstobj].
Q. How do I write a universal quantifier? An existential quantifier?
How can I say ``for all'' or ``there exists''? A You can't
literally write quantifiers. But ACL2 has the power of full first
order logic with quantification. See [quantifiers].
Q. How do I introduce an undefined or uninterpreted function symbol?
Can I constrain it to have certain properties? A. See
[encapsulate].
Q. How can I hide a lemma? I want to prove a lemma temporarily to use
in another proof but I don't want the lemma around thereafter. A.
One way to get a similar effect is to prove the lemma and then
disable it with an (in-theory (disable ...)) event; see
[in-theory]. Another way is to put the lemma and the theorem that
needs it into an [encapsulate] and wrap a [local] around the lemma.
Q. What is an event? A. An event is a command that adds information
to the ACL2 database (the ``logical world''), like defun or defthm.
See [events].
Q. How do I say that I do not want a rewrite rule generated from a
theorem? A. The command
(defthm name formula
:rule-classes nil)
will attempt to prove formula and, if successful, give formula the
name name, which you may use in hints as a theorem, but it will
build no rules from the formula.
Q. How do I say that I want a formula to be stored as a rewrite rule?
A. The command
(defthm name formula)
will attempt to prove formula and, if successful, it will give
formula the name name and generate a rewrite rule from it, with the
runic name (:rewrite name)]. It could happen that formula generates
more than one rewrite rule, e.g., this happens if the conclusion is
an AND. In this case, each conjunctive branch through the
conclusion generates a rule named (:rewrite name . i), for
i=1,2,... For more details, see [rewrite].
Q. How do I say that I want a formula to be stored as a rewrite rule
and some other kinds of rules? A. The command
(defthm name formula
:rule-classes (:class1 ... classk))
will attempt to prove formula and, if successful, it will give
formula the name name and generate a rule of each :classi
specified. Each :classi should either be a keyword, like :REWRITE
or :GENERALIZE, naming a rule class (see [rule-classes]), or else
should be a list that starts with a rule class and then lists the
relevant modifiers. Be sure to include :REWRITE among the rule
classes if you want the formula to generate a rewrite rule. It
doesn't do that automatically if you explicitly specify
:rule-classes!
Q. How do I rearrange the shape of a formula before generating a rule
from it? A. See [rule-classes] and read about the :corollary
modifier.
Q. What is a type-prescription? A. ACL2 has an algorithm for
determining the type of object returned by a term, where a type is
one of the Common Lisp primitive datatypes such as natural,
integer, Boolean, cons, true-listp, etc. Rules provided by you can
influence this algorithm. See [type-prescription].
Q. How do rewrite rules work? A. Re-read the tutorial sections:
[introduction-to-rewrite-rules-part-1] and
[introduction-to-rewrite-rules-part-2].
Q. How do I see what's in the database? A. You can't look at the
entire database with user-friendly tools. You can print the command
that introduced a particular name, print the entire sequence of
user commands, print the commands in the region between two
commands, print all the rewrite rules that apply to a given term or
function symbol, and many other options. See [history]. If you have
loaded a book from another user, you might wish to read the source
file. For example, the source file for (include-book
\"arithmetic-5/top\" :dir :system) is the file named
arithmetic-5/top.lisp on the acl2-sources/books/ directory where
ever your ACL2 sources are installed. Often, books are
well-documented by comments by their authors. Some books have
Readme or README files on the same directory.
Q. How do I undo a command? A. See [history], especially see [u]
(``undo'') and see [ubt] (``undo back through''). Q. What rewrite
rules match a given term? A. See [pl].
Q. What were those questions to ask when looking at key checkpoints?
A. See [introduction-to-key-checkpoints].
Q. How do I figure out why a rewrite rule won't fire? A. If you
activate rewrite rule monitoring (see [brr]) and then install a
monitor (see [monitor]) on the rule in question, ACL2 will enter an
interactive break whenever the pattern of the rule is matched
against a target in a proof. So after installing the monitor,
re-try the proof and then interact with the rewriter via break
commands (see [brr-commands]). Like all trace and break packages,
you have to know what you're doing to use the break rewrite
facility, so read the material in the reference manual. If no
interactive break happens after you've installed the monitor on
your rule and re-tried the proof, it means no suitable target ever
arose. Don't forget to turn off monitoring when you're done as it
slows down the system.
Q. Why is a proof taking so long? A. Unexpectedly poor performance on
simple problems is usually a sign of cyclic rewriting or
combinatoric explosion. See [dmr] and see
[accumulated-persistence].
Q. How do I tell ACL2 what induction to do for a particular formula?
A. When issuing the defthm command for the formula, supply an
:induct hint:
(defthm name
formula
:hints ((\"Goal\" :induct (f x1 ... xn))))
where f is a function that recurs the way you want the induction to
unfold and x1 ... xn are the relevant variables in formula. You
usually have to define f appropriately for each formula that needs
an induct hint, though sometimes you can re-use an earlier f or one
of the functions in the formula itself. It doesn't matter what
value (f x1 ... xn) returns. All that matters is how it recurs. The
termination analysis for f justifies the induction done. See
[hints], especially the section on :induct hints; also see
[induction].
Q. ACL2 doesn't know simple arithmetic that can simplify the term (+
1 -1 x). A. You should load an arithmetic book whenever you're
dealing with an arithmetic problem. The simplest arithmetic book is
typically loaded with the event (include-book
\"arithmetic/top-with-meta\" :dir :system). If you're using floor and
mod or non-linear arithmetic like (* x y) you should use
(include-book \"arithmetic-5/top\" :dir :system). See also the
discussion of arithmetic books under the ``Lemma Libraries and
Utilities'' link of the ACL2 home page, and see [community-books].
Q. ACL2 is not using an arithmetic lemma that I proved. A. Lemmas
concluding with arithmetic inequalities, like
(implies (member e x)
(< (len (delete e x)) (len x)))
are not good rewrite rules because they rarely match targets because
of intervening arithmetic operators. For example, the above
conclusion doesn't match (< (LEN (DELETE E X)) (+ 1 (LEN X))). You
should store such lemmas as :linear rules by using the command:
(defthm len-delete
(implies (member e x)
(< (len (delete e x)) (len x)))
:rule-classes :linear)
See [linear].
Q. What is a linear rule? A. See [linear].
Q. How do I make ACL2 treat a relation as an equality? A. We assume
you mean to treat the relation as an equivalence, i.e., replace one
term by another when they are equivalent under your relation. See
[equivalence], see [congruence], and see [refinement].
Q. One of my rewrite rules has a hypothesis that doesn't rewrite to
true. What do I do? A. Prove a rewrite rule that establishes that
hypothesis under the relevant assumptions from the context of the
intended target. Alternatively, undo the rule and restate it with a
[force] around the problematic hypothesis, making ACL2 assume the
hypothesis when the rule is applied and raising the truth of the
hypothesis as an explicit subgoal of the proof. See also
[case-split]. Of course, you should always state the strongest
rewrite rules you can think of, eliminating hypotheses or shifting
them to the right-hand side inside of IFs; see
[strong-rewrite-rules].
Q. How do I make ACL2 ``guess'' the right instantiation of a free
variable? A. You can provide a :restrict hint that names the
problematic lemma and provides an instantiation of the free
variable. See [hints], specifically :restrict. You could
alternatively give a hint that :uses the rule and provides the
appropriate instantiation in full. See [hints], specifically :use.
Recall that ACL2 guesses free variable instantiations by matching
the problematic hypothesis to the assumptions in the context of the
target. If the appropriate assumption is present but ACL2 is
finding another one, try undoing the problematic rule and proving
it again, specifying the :match-free :all modifier of the :rewrite
or :linear rule class. See [rule-classes]. Alternatively, undo and
prove the problematic rule again and use a [bind-free] form to
compute the appropriate instantiation.
Q. How can I make ACL2 do a case split to prove a certain subgoal? A.
See [hints], specifically :cases.
Q. How can I prevent ACL2 from using a rewrite rule? A. See [hints],
specifically :in-theory (disable ...). If the use of the rule is
problematic in only one subgoal and the lemma is needed in other
subgoals, disable the lemma only in the problematic subgoal by
specifying the subgoal name (e.g., \"Subgoal 1/3.2.1\") as the goal
specifier in the hint. If the rule isn't needed anywhere in the
proof, you could use the specifier \"Goal\". If you don't think the
rule will ever be needed for a while, you could globally disable it
with the event (in-theory (disable ...)) (see [in-theory]) executed
before the first problematic proof. If the rule has never been used
or must always be disabled, undo it and prove it again with
:[rule-classes] nil.
Q. How can I prevent ACL2 from running a definition on constants? I
tried disabling the function but that didn't work. A. If you have a
function named f then disabling f will disable the definitional
axiom about f. But ACL2 has another kind of rule about f, telling
it how to evaluate f. The [rune] of this rule is
(:executable-counterpart f). Try disabling that, as in the :[hints]
((... :in-theory (disable (:executable-counterpart f)) ...c[)).
Q. How can I make ACL2 use a rule in a proof? A. See [hints],
specifically :use.
Q. How can I make ACL2 expand a function call in a proof? A. You can
give an :See [expand] hint.
Q. ACL2 sometimes aborts the proof attempt before showing me all of
the subgoals. How can I make it just keep going instead of aborting
early? A. See [otf-flg], which stands for Onward Thru the Fog FLaG.
Q. How can I compute when I want a rule to fire? A. See [syntaxp].
Q. How can I add pragmatic advice to a lemma after it has been
proved? For example, how can add a forced hypothesis, a backchain
limit, or a syntaxp test? A. You can't. You can undo the lemma,
restate it appropriately, and prove it again. This produces the
cleanest database. Alternatively, you can prove the restated lemma
under a new name -- a task that should be easy since the old
version is in the database and will presumably make the proof
trivial -- and then disable the old name.
Q. How can I stop ACL2 from rewriting a term? A. If you need
rewriting done but want to prevent some particular terms from being
rewritten, see [hints], specifically :hands-off. Alternatively,
consider embedding the problematic term in a [hide]. Users sometime
develop special theories (see [theory]) containing just the rules
they want and then use hints to switch to those theories on the
appropriate subgoals.
Q. Can I compute which subgoals a hint refers to? A. Yes, see
[computed-hints]. This topic is for advanced users but knowing that
it is possible might come in handy someday.
Q. I want the rewriter to always use one theory and then switch to
another so that it doesn't use my most complicated before until
doing the simple things. A. This is possible but is something for
the advanced user. It can be done using a form of [computed-hints].
See [using-computed-hints-7].
Q. Is there a way to attach the same hint to every defthm? A. See
[default-hints].
Q. How can I just tell ACL2 the proof steps? A. See [verify] and see
[proof-checker].
Q. How can I write my own simplifier? A. See [meta].
Q. How can I add an axiom or just assume some lemma without proof? A.
This is very dangerous but is a good strategy for exploring whether
or not a certain set of lemmas (and their rules) is sufficient to
prove your goal. See [defaxiom] and see [skip-proofs].
Q. How can redefine a user-defined function? A. This is tricky. What
if you've already proved theorems about the old definition and then
wish to change it? There are several options. See
[ld-redefinition-action] (and note specifically the discussion of
updater function for it, set-ld-redefinition-action); also see
[redef], see [redef!], see [redef+], and see [redef-].
Q. How do I change a function from :program mode to :logic mode? A.
See [verify-termination].
Q. How do I change the guards on a function? A. You can't. Undo it
and redefine it.
Q. What is program mode? A. See [program].
Q. What does the ACL2 prompt mean? A. See
[introduction-to-a-few-system-considerations] or, specifically, see
[prompt].
Q. What is logic mode? A. See [logic].
Q. How do I get into or out of :program mode? :Logic mode? A. See
[program] and see [logic]. You can enter these modes temporarily
for a particular [defun] by using (declare (xargs :mode :program))
or (declare (xargs :mode :logic)) after the list of formal
parameters to the definition.
Q. How do I quit from ACL2? A. This varies depending on the interface
you're using. See [introduction-to-a-few-system-considerations].
Q. How do I load a file of definitions and theorems created by
someone else? A. See [include-book].
Q. How do I create my own book of definitions and theorems? A. See
[books].
Q. Where are the books referenced by :dir :system on my machine? A.
If your ACL2 is installed on the directory dir/acl2-sources and you
follow the standard installation instructions, then the books are
typically the files under the directory dir/acl2-sources/books/.
Q. How can I find out what books are available? A. Go to the ACL2
home page, http://www.cs.utexas.edu/u/moore/acl2/ and look at the
link labeled ``Lemma Libraries and Utilities.''
Q. How do I produce my own book? A. See [books].
Q. What is a decision procedure? What decision procedures does ACL2
have? A. A decision procedure is an algorithm that given enough
time and space can determine, for all the formulas in a certain
syntactic class of formulas, whether the formula is a theorem or
not. The most well-known decision procedure is for propositional
calculus: by testing a formula under all the combinations Boolean
assignments to the variables, one can decide if a propositional
formula is a theorem. The syntactic class consists of all formulas
you can write using just variables, constants, and compositions of
the functions and, or, not, implies, iff, and if. There are, of
course, an exponential number of different assignments so the
algorithm can be slow. ACL2 contains a propositional decision
procedure based on symbolic normalization that can be faster than
trying all the combinations of truthvalues -- but is not guaranteed
to be faster. ACL2 also contains an optional [bdd] procedure. ACL2
also contains a decision procedure for rational arithmetic
involving variables, rational constants, addition, multiplication
by rational constants, equality, and the various versions of
arithmetic inequality (<, <=, >=, and >). It can be extended with
:[linear] lemmas. ACL2 is complete for equality over uninterpreted
(e.g., undefined and unconstrained) function symbols using an
algorithm based on transitive closure of equivalence classes under
functional substitutivity. Finally, you can make ACL2 use other
decision procedures, even ones implemented outside of ACL2; see
[clause-processor].
Q. ACL2 has the change of variable trick (destructor elimination)
that it does to get rid of (CAR X) and (CDR X) by replacing x by
(CONS A B). Is there a way to make ACL2 do that for other terms? A.
Yes. See [elim].
Q. How can I prevent destructor elimination? A. See [hints],
specifically :do-not '(eliminate-destructors).
Q. How can I prevent cross-fertilization? A. See [hints],
specifically :do-not '(fertilize).
Q. How can I prevent generalization? A. See [hints], specifically
:do-not '(generalize).
Q. How can I make ACL2 impose a restriction on a new variable
introduced by destructor elimination or generalization? A. See
[generalize].
Q. What rule classes are there? A. See [rule-classes].
Q. What is a theory? A. See [theories].
Q. How are hints inherited by the children of a subgoal? A. See
[hints-and-the-waterfall].
Q. How do I use ACL2 under Emacs? A. See [emacs].
Q. How do I use ACL2 under Eclipse? A. See [ACL2-Sedan].
Q. How do I interrupt the prover? A. The keyboard sequence for
interrupting a running process depends your operating system, host
Common Lisp, and user interface (e.g., Emacs, Eclipse, etc.). But
perhaps a few examples will help you discover what you need to
know. If your host Common Lisp is GCL or Allegro and you are typing
directly to the Common Lisp process, then you can interrupt a
computation by typing ``ctrl-c'' (hold down the Control key and hit
the ``c'' key once). But other Lisps may require some other control
sequence. If you are typing to an Emacs process which is running
the GCL or Allegro Common Lisp process in a shell buffer, you
should type ctrl-c ctrl-c -- that is, you have to type the
previously mentioned sequence twice in succession. If you are
running the ACL2 Sedan, you can use the Interrupt Session button on
the tool bar. The environment you enter when you interrupt depends
on various factors and basically you should endeavor to get back to
the top level ACL2 command loop, perhaps by typing some kind of
Lisp depenent ``abort'' command like A or :q, or :abort!. You can
usually determine what environment you're in by paying attention to
the prompt.
Q. What is the ACL2 loop? A. That is the name given to the
interactive environment ACL2 provides, a ``read-eval-print loop''
in which the user submits successive commands by typing ACL2
expressions and keyword commands. See
[introduction-to-a-few-system-considerations].
Q. What is raw lisp? A. That is our name for the host Common Lisp in
which ACL2 is implemented. See
[introduction-to-a-few-system-considerations]. There is an ACL2
mode named raw mode which is different from ``raw lisp.'' See
[set-raw-mode].
Q. Can I get a tree-like view of a proof? A. See [proof-tree] for an
Emacs utility that displays proof trees and allows you to navigate
through a proof from the proof tree. The ACL2 Sedan also supports
proof trees and you should see the ACL2s documention on that topic.
Q. I used the earlier Boyer-Moore theorem prover, Nqthm. How is ACL2
different? A. See [nqthm-to-ACL2].
If you are reading this as part of the tutorial introduction to the
theorem prover, use your browser's Back Button now to return to
[introduction-to-the-theorem-prover].")
(FULL-BOOK-NAME
(BOOKS-REFERENCE)
"Book naming conventions assumed by ACL2
For this discussion we assume that the resident operating system is
Unix (trademark of AT&T), but analogous remarks apply to other
operating systems supported by ACL2; see [pathname].
ACL2 defines a ``full book name'' to be an ``absolute filename
string,'' that may be divided into contiguous sections: a
``directory string'', a ``familiar name'' and an ``extension''. See
[pathname] for the definitions of ``absolute,'' ``filename
string,'' and other notions pertaining to naming files. Below we
exhibit the three sections of one such string:
\"/usr/home/smith/project/arith.lisp\"
\"/usr/home/smith/project/\" ; directory string
\"arith\" ; familiar name
\".lisp\" ; extension
The sections are marked by the rightmost slash and rightmost dot, as
shown below.
\"/usr/home/smith/project/arith.lisp\"
| |
slash dot
| |
\"/usr/home/smith/project/\" ; directory string
\"arith\" ; familiar name
\".lisp\" ; extension
The directory string includes (and terminates with) the rightmost
slash. The extension includes (and starts with) the rightmost dot.
The dot must be strictly to the right of the slash so that the
familiar name is well-defined and nonempty.
If you are using ACL2 on a system in which file names do not have
this form, please contact the authors and we'll see what we can do
about generalizing ACL2's conventions.
We conclude with a remark about a representation of full book names
that is used in [certificate] files and [make-event] expansions.
When the system books directory is a prefix of a full book name,
ACL2 may choose to write a full book name as (:system . \"suffix\"),
where \"suffix\" is the result of removing the system books directory
from the front of the full book name. Here is an example.
; full book name:
\"/Users/smith/acl2/acl2/books/std/portcullis.lisp\"
; alternate representation
; (where \"/Users/smith/acl2/acl2/books/\" is the system books directory):
(:SYSTEM . \"std/portcullis.lisp\")
Conversely, in some contexts ACL2 will convert :system . \"suffix\" to
an absolute pathname. Generally \"suffix\" will be a relative
pathname, such as \"dir/filename.lisp\"; in that case, the system
books directory will be concatenated with \"suffix\" to form a
corresponding full book name. However, if \"suffix\" is an absolute
pathname, such as \"/u/smith/foo.lisp\", then the corresponding full
book name is simply that absolute pathname; essentially, the
:system prefix is dropped.")
(FUNCTION-THEORY
(THEORIES THEORY-FUNCTIONS)
"Function symbol rules as of logical name
Examples:
(function-theory :here)
(function-theory 'lemma3)
See [logical-name].
General Form:
(function-theory logical-name)
Returns the theory containing all the :[definition] [rune]s, whether
[enable]d or not, that existed immediately after [logical-name] was
introduced. See the documentation for [theories], [logical-name]
and [executable-counterpart-theory].
You may experience a fencepost problem in deciding which logical name
to use. [Deflabel] can always be used to mark unambiguously for
future reference a particular point in the development of your
theory. The order of [events] in the vicinity of an [encapsulate]
is confusing. See [encapsulate].
This ``function'' is actually a macro that expands to a term
mentioning the single free variable [world]. When theory
expressions are evaluated by [in-theory] or the :[in-theory] hint,
[world] is bound to the current ACL2 [world].")
(FUNCTIONAL-INSTANTIATION
(ENCAPSULATE)
"An analogue in ACL2 of higher-order logical reasoning. Functional
instantiation allows you to prove theorems ``by analogy'' with
previous theorems. See [hints] and see [lemma-instance].
Subtopics
[Functional-instantiation-example]
A small proof demonstrating functional instantiation
[Functional-instantiation-in-ACL2r]
Additional requirements for :functional-instance hints in ACL2(r)
[Lemma-instance]
An object denoting an instance of a theorem")
(FUNCTIONAL-INSTANTIATION-EXAMPLE
(FUNCTIONAL-INSTANTIATION TUTORIAL5-MISCELLANEOUS-EXAMPLES)
"A small proof demonstrating functional instantiation
The example below demonstrates the use of functional instantiation,
that is, the use of a generic result in proving a result about
specific functions. In this example we constrain a function to be
associative and commutative, with an identity or ``root,'' on a
given domain. Next, we define a corresponding function that applies
the constrained associative-commutative function to successive
elements of a list. We then prove that the latter function gives
the same value when we first reverse the elements of the list.
Finally, we use functional instantiation to derive the
corresponding result for the function that multiplies successive
elements of a list.
The details of the proof (such as the [in-theory] event and
particulars of the lemmas) are not the point here. Rather, the
point is to demonstrate the interaction of [encapsulate] [events]
and :functional-instance [lemma-instance]s. Of course, if you are
interested in details then you may find it helpful to run these
[events] through ACL2.
Also see [constraint] for more about :functional-instance and see
[lemma-instance] for general information about the use of
previously-proved lemmas.
(in-package \"ACL2\")
(encapsulate
(((ac-fn * *) => *)
((ac-fn-domain *) => *)
((ac-fn-root) => *))
(local (defun ac-fn (x y) (+ x y)))
(local (defun ac-fn-root () 0))
(local (defun ac-fn-domain (x) (acl2-numberp x)))
(defthm ac-fn-comm
(equal (ac-fn x y)
(ac-fn y x)))
(defthm ac-fn-assoc
(equal (ac-fn (ac-fn x y) z)
(ac-fn x (ac-fn y z))))
(defthm ac-fn-id
(implies (ac-fn-domain x)
(equal (ac-fn (ac-fn-root) x)
x)))
(defthm ac-fn-closed
(and (ac-fn-domain (ac-fn x y))
(ac-fn-domain (ac-fn-root)))))
;;;;;;;;;;;;;;;;;;;;;;;
; End of encapsulate. ;
;;;;;;;;;;;;;;;;;;;;;;;
; Define a ``fold'' function that iteratively applies ac-fn over a list.
(defun ac-fn-list (x)
(if (atom x)
(ac-fn-root)
(ac-fn (car x)
(ac-fn-list (cdr x)))))
; Recognize lists all of whose elements are in the intended domain.
(defun ac-fn-domain-list (x)
(if (atom x)
t
(and (ac-fn-domain (car x))
(ac-fn-domain-list (cdr x)))))
; Define a list reverse function.
(defun rev (x)
(if (atom x)
nil
(append (rev (cdr x))
(list (car x)))))
; The following is needed for proving ac-fn-list-append, which is
; needed for proving ac-fn-list-rev.
(defthm ac-fn-list-closed
(ac-fn-domain (ac-fn-list x)))
; Needed for proving ac-fn-list-rev:
(defthm ac-fn-list-append
(implies (and (ac-fn-domain-list x)
(ac-fn-domain-list y))
(equal (ac-fn-list (append x y))
(ac-fn (ac-fn-list x)
(ac-fn-list y)))))
; Needed for proving ac-fn-list-rev:
(defthm ac-fn-domain-list-rev
(equal (ac-fn-domain-list (rev x))
(ac-fn-domain-list x)))
; The following is a good idea because without it, the proof attempt
; for ac-fn-list-rev (see just below) fails with the term (HIDE
; (AC-FN-LIST NIL)). It is often a good idea to disable
; executable-counterparts of functions that call constrained
; functions.
(in-theory (disable (:executable-counterpart ac-fn-list)))
(defthm ac-fn-list-rev
(implies (ac-fn-domain-list x)
(equal (ac-fn-list (rev x))
(ac-fn-list x))))
; Our goal now is to apply functional instantiation to ac-fn-list-rev
; in order to prove the corresponding theorem, times-list-rev, based
; on * instead of ac-fn.
(defun times-list (x)
(if (atom x)
1
(* (car x)
(times-list (cdr x)))))
(defun number-listp (x)
(if (atom x)
t
(and (acl2-numberp (car x))
(number-listp (cdr x)))))
; The following relies on the following built-in rules for * (whose
; statements correspond directly to their names): commutativity-of-*,
; associativity-of-*, and unicity-of-1.
(defthm times-list-rev
(implies (number-listp x)
(equal (times-list (rev x))
(times-list x)))
:hints ((\"Goal\"
:use
((:functional-instance
ac-fn-list-rev
;; Instantiate the generic functions:
(ac-fn *)
(ac-fn-root (lambda () 1))
(ac-fn-domain acl2-numberp)
;; Instantiate the other relevant functions:
(ac-fn-list times-list)
(ac-fn-domain-list number-listp))))))")
(FUNCTIONAL-INSTANTIATION-IN-ACL2R
(FUNCTIONAL-INSTANTIATION)
"Additional requirements for :functional-instance hints in ACL2(r)
This documentation topic relates to ACL2(r), the modification of ACL2
that supports the real numbers (see [real]).
See [hints] and see [lemma-instance] for a discussion of :use hints
that employ the :functional-instance keyword. Here, we document
additional requirements for such hints that applies to ACL2(r). We
assume familiarity with lemma instances; see [lemma-instance].
(1) When functionally instantiating a non-classical formula, it is
illegal to use pseudo-lambda expressions in a lemma instance.
(2) A classical function symbol must be bound either to a classical
function symbol or to a lambda (or, if allowed, pseudo-lambda)
expression with a classical body. Similarly, a non-classical
function symbol must be bound either to a non-classical function
symbol or to a lambda (or, if allowed, pseudo-lambda) expression
with a non-classical body.")
(FUNCTIONS_FOR_MANIPULATING_THESE_OBJECTS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Functions for Manipulating these Objects
[{IMAGE}]
Consider a typical ``stack'' of control frames.
{IMAGE}
Suppose the model required that we express the idea of ``the most
recent frame whose return program counter points into MAIN.''
The natural expression of this notion involves
function application --- ``fetch the return-pc of this frame''
case analysis --- ``if the pc is MAIN, then ...''
iteration or recursion --- ``pop this frame off and repeat.''
The designers of ACL2 have taken the position that a programming
language is the natural language in which to define such notions,
provided the language has a mathematical foundation so that models
can be analyzed and properties derived logically.
Common Lisp is the language supported by ACL2. To be precise, a small
applicative subset of Common Lisp is the language supported by
ACL2.
[{IMAGE}]")
(FURTHER-INFORMATION-ON-REWRITING
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"A grab bag of advice and information on rewriting
In the following paragraphs we give some links to advanced topics,
marked with ``[{ICON}]''. If you are reading this topic as part of
the tutorial on the theorem prover, do not follow these links upon
your first reading. Just take note of the existence of the
facilities and ideas mentioned.
[Arithmetic]: If your goal theorem involves even trivial arithmetic,
such as adding or subtracting 1, we recommend that you do
(include-book \"arithmetic/top-with-meta\" :dir :system)
which loads into ACL2 all the rules in one of the so-called ACL2
``community books''. (Books are certified files of definitions,
lemmas, etc., usually prepared by other ACL2 users and explicitly
shared with the community. The ACL2 installation instructions
suggest downloading the community books.) The book \"top-with-meta\"
is the most elementary and most widely used arithmetic book. Other
community books include \"arithmetic-5/top\" and various hardware and
floating-point arithmetic books.
Rules Concluding with Arithmetic Inequalities: If you are tempted to
create a rewrite rule with an arithmetic inequality as its
conclusion or left-hand side, think again. Inequalities such as
(<= (len (delete e x)) (len x))
make poor left-hand sides for rewrite rules. For example, the
inequality above does not match the target
(<= (LEN (DELETE E X)) (+ 1 (LEN X)))
even though it is sufficient to prove the target (given some simple
arithmetic). We recommend that if you have a theorem that
establishes an arithmetic inequality, you make it a linear rule.
See [linear] [{ICON}].
Rearranging Formulas Before Making Rules: It is possible to rearrange
the propositional structure of a proved formula before processing
it as a rule. This allows you to state a theorem one way ``for
publication'' and rearrange it to be stored as a more effective
rule. See [introduction-to-the-database] (a tutorial topic you'll
come to later) and its discussion of the concept of corollary.
Also, see the discussion of corollary in [rule-classes] [{ICON}].
Rewriting with New Equivalence Relations: You may introduce new
equivalence relations, like ``set-equal'' or ``is-a-permutation''
and cause the rewriter to replace equivalents by equivalents in
suitable contexts, where you use congruence rules to inform ACL2 of
where these more relaxed notions of equivalence may be used; see
[equivalence] [{ICON}] and see [congruence] [{ICON}].
Pragmatic Advice to Control Rules: You may attach various pragmas to
a rule that allow you rather fine heuristic control over whether
and how the rule is applied. For example, you may mark a hypothesis
to be forced (see [force] [{ICON}]) meaning that the rule is to be
applied even if that hypothesis is not relieved -- but if the proof
is successful the system will turn its attention to all forced
subgoals. You may similarly mark a hypothesis so as to cause a case
split, allowing the relief of the hypothesis on one branch and
spawning another branch explicitly denying the hypothesis; see
[case-split] [{ICON}]. You may add a bogus hypothesis that looks at
the intended application of the rule and decides whether to apply
the rule or not, performing an arbitrary computation on the
syntactic context of the application; see [syntaxp] [{ICON}]. By
providing a :match-free modifier to the :rewrite rule declaration
in your rule-classes, you may tell ACL2 to try all or only the
first free variable value it guesses (see [rule-classes] [{ICON}]).
You may provide a bogus hypothesis that computes from the syntactic
environment the values to guess for the free variables in a rule;
see [bind-free] [{ICON}]. You may mark a term so that the rewriter
does not dive into it; see [hide] [{ICON}].
Programming Your Own Rewriter: If you cannot find a way to use
rewrite rules to make the transformations you desire, you might
investigate the use of metafunctions. A metafunction is just a
little theorem prover of your own design. It takes as input a list
structure representing a term and returns a list structure
representing a term. If you can prove that the meaning of the input
and output terms are equivalent, you can extend the ACL2 simplifier
to call your metafunction. See [meta] [{ICON}].
The Order in which Targets are Rewritten: The rewriter sweeps through
terms ``inside-out'' otherwise known as ``left-most innermost
first''. Thus, before trying to apply rewrite rules to (f a1 ...
an), rules are applied to the ai. This has the good effect of
normalizing the ai.
This fact might help you understand why sometimes your rules ``don't
seem to fire.'' For example, suppose you have a rule for rewriting
(len (rev x)) to (len x) and suppose you wish to prove a theorem
about (LEN (REV (CONS A B))). Suppose rev is defined in terms of
append, as shown in [programming-knowledge-taken-for-granted]. Then
you might see a checkpoint in which the (LEN (REV ...)) above has
been simplified to (LEN (APPEND (REV B) (LIST A))) instead of to
(LEN (CONS A B)). Why wasn't your rule about (len (rev x)) applied?
The reason is that (REV (CONS A B)) rewrote to (APPEND (REV B)
(LIST A)) before rules were applied to (LEN (REV ...)). You need a
rule about (len (append x y)), as you will see from the checkpoint.
The Order in which Rules are Tried: The rewriter tries the most
recently proved rules first. For example, suppose f, g, and h are
functions defined so that the following two theorems are provable
and suppose you executed the following two events in the order
shown:
(defthm rule1 (equal (f (g x)) (h 1 x)))
(defthm rule2 (equal (f (g x)) (h 2 X)))
Then if rewrite rules are applied to (F (G A)), the result will be (H
2 A), because the latter rule, rule2, is applied first. It is
generally best not to have conflicting rules or, at least, to
understand how such conflicts are resolved. The system will warn
you when you propose a rule that conflicts with an existing one.
If you were reading this topic as part of the tutorial introduction
to the theorem prover, use your browser's Back Button now to return
to [introduction-to-rewrite-rules-part-2].")
(FUTURE-WORK-RELATED-TO-THE-TAU-SYSTEM
(INTRODUCTION-TO-THE-TAU-SYSTEM)
"Some tau system problems that we hope someone will address
The tau system is inexpressive compared to modern polymorphic type
systems --- something that may be unavoidable in an untyped
first-order language. However, we believe its effectiveness could
be greatly increased by the development of some additional tools.
We also believe that most of these tools could be provided by ACL2
users creating certified community books that exploit the basic
tools already provided. It is likely the initial attempts to create
such books will show the inadequacy of some of the current
algorithms and data structures in the tau system and might point
the way to improvements.
As implementors of ACL2 our preference is to support the improvement
of the core algorithms and data structures and provide customizable
hooks allowing users to exploit them by developing effective and
convenient interfaces. However, we want the further elaboration and
optimization of the tau system to be based on user experience not
just speculation.
Some tools we think might help are listed below. We invite volunteers
and further suggestions.
A tau-centric signature notation for use in function definitions,
exploited by a macro replacing defun so that input-output
relationships phrased in tau terms are proved as :tau-system rules
immediately after functions are introduced:
We have, for example, experimented with a book defining a macro that
allows the definition of the function ap (append) accompanied by a
signature rule. Subsequent defsig events can add other signatures
in the same notation.
(defsig ap (true-listp * true-listp ==> true-listp) (x y)
(if (consp x)
(cons (car x) (ap (cdr x) y))
y))
(defsig ap (integer-listp * integer-listp ==> integer-listp))
This experimental book provides succinct syntax for all tau
signatures. For example, that book parses the signature
(NATP (/= 3 5 7) (< 16) * TRUE-LISTP ==> BOOLEANP * INTEGER-LISTP * NATP)
to be the signature of a function with two inputs and three outputs.
The first input must be a natural number, different from 3, 5, and
7, and less than 16. The second input must be a true list. The
first output is a boolean, the second a list of integers, and the
third a natural.
To express this signature for function fn as a formula requires
significantly more typing by the user:
(IMPLIES (AND (NATP X)
(NOT (EQUAL X 3))
(NOT (EQUAL X 5))
(NOT (EQUAL X 7))
(< X 16)
(TRUE-LISTP Y))
(AND (BOOLEANP (MV-NTH 0 (FN X Y)))
(INTEGER-LISP (MV-NTH 1 (FN X Y)))
(NATP (MV-NTH 2 (FN X Y)))))
We suspect that the provision of some succinct tau-centric notation
(not necessarily the one above) for signatures at definition-time
will mean users get more benefit from the tau system.
Some tau inference mechanisms: This phrase suggests two different
improvements. One is to implement a mechanism that adds or
completes signatures for function definitions by exploiting
knowledge of commonly used recursive schemas and the signatures of
the subroutines in the body. For example, the definition of ap
above rather obviously has the signature
(integer-listp * integer-listp ==> integer-listp)
and many others just based on the two recursive schemas that (a)
collect certain elements from lists and (b) check that all elements
have a certain property.
The other ``tau inference'' improvement is to implement a mechanism
for inferring relations between user-defined Booleans, perhaps by
exploiting example generation, testing, and knowledge of recursive
schemas. For example, it is fairly obvious that [symbol-alistp]
implies [alistp]. Making the user state these relations invites
omissions that render the tau system very unpredictable.
A tau assistant: It would be useful to have a way to find out what
tau rules are missing. Given a term that the user believes should
``obviously'' have some tau (``type'') what rules might be added to
make the tau algorithm compute that expected tau? For example, if
(g x) is known to satisfy P and (f x) is known to satisfy R when
its argument satisfies S:
g : T ==> P
f : S ==> R
then if the user asserts that (f (g x)) ``ought'' to have tau R, one
plausible suggestion is the simple tau rule that (P x) implies (S
x). Such assistance --- while still confronting an undecidable
problem --- might be easier to implement within the tau framework
than more generally in ACL2. (Many users have wanted such an
assistant to suggest lemmas for the rewriter.)")
(GAG-MODE
(PROVER-OUTPUT)
"Verbosity of proof output
Please see [set-gag-mode] for an explanation of gag-mode, which can
take any of the following values:
(gag-mode) ; generally evaluates to t, nil, or :goals")
(GC$
(MISCELLANEOUS ACL2-BUILT-INS)
"Invoke the garbage collector
This function is provided so that the user can call the garbage
collector of the host Lisp from inside the ACL2 loop. Specifically,
a call of gc$ is translated into a call of a function below on the
same arguments.
Allegro CL: excl:gc
CCL ccl::gc
CLISP ext:gc
CMU Common Lisp system::gc
GCL si::gbc [default argument list: (t)]
LispWorks hcl::gc-generation [default argument list:
(7) for 64-bit OS, else (3)]
SBCL sb-ext:gc
The arguments, if any, are as documented in the underlying Common
Lisp. It is up to the user to pass in the right arguments, although
we may do some rudimentary checks.
Also see [gc-verbose].
Evaluation of a call of this macro always returns nil.
To include gc$ in a book, one can use value-triple:
(value-triple (gc$))
Subtopics
[Gc-verbose]
Control printing from the garbage collector")
(GC-STRATEGY
(MISCELLANEOUS ACL2-BUILT-INS)
"The garbage collection strategy
The form (gc-strategy state) provides the value the current garbage
collection strategy if that notion is supported by the underlying
host lisp (currently, CCL only). The logical story is that
gc-strategy reads its value from the oracle field of the ACL2
[state]. The return value is thus a triple of the form (mv erp val
state), where erp will always be nil in practice, and logically,
val is the top of the acl2-oracle field of the state (see
[read-ACL2-oracle]) and the returned state has the updated (popped)
acl2-oracle.
For more information, see [set-gc-strategy].")
(GC-VERBOSE
(GC$)
"Control printing from the garbage collector
General Form:
(gc-verbose arg &optional arg2)
Garbage collection (gc) is performed by every Lisp implementation;
see [gc$]. However, different ACL2 builds might see more or fewer
messages. This macro is intended to provide an interface for
controlling the verbosity, which is off if the (first) argument
evaluates to nil and otherwise is on. The second (optional)
argument is currently ignored except when the host Common Lisp
implementation is CCL, where it specifies verbosity for EGC.
The above functionality is only supported for the following host
Common Lisp implementations: CCL, CMUCL, and GCL. Otherwise, the
only effect of this macro is to print a notice that it is not
supported. You are welcome to contact the ACL2 developers if you
would like to help in adding such support for another host Common
Lisp.
Evaluation of a call of this macro always returns nil.")
(GCL
(MISCELLANEOUS)
"Tips on building and using ACL2 based on Gnu Common Lisp
See the installation instructions for basic information about
building ACL2 on top of GCL, including information about where to
fetch GCL. Here, we provide some tips that may be useful.
1. You can place forms to evaluate at start-up into file init.lsp in
the directory where you are starting ACL2 (GCL), or into file
acl2-init.lsp in your home directory. For example, in order to
evaluate both of the lisp forms mentioned in 2 below, you could put
them both into init.lsp in the current directory or in
~/acl2-init.lsp (either way, without (lp) or :q):
(setq si::*optimize-maximum-pages* nil)
(si::allocate 'cons 75000 t)
Note that if you want to put ACL2 patches in this file, you should
precede them with (in-package \"ACL2\").
2. Suppose you run out of space, for example with an error like this:
Error: The storage for CONS is exhausted.
Currently, 59470 pages are allocated.
Use ALLOCATE to expand the space.
The following suggestion from Camm Maguire will minimize the heap
size, at the cost of more garbage collection time.
:q ; exit the ACL2 loop
(setq si::*optimize-maximum-pages* nil)
(lp) ; re-enter the ACL2 loop
A second thing to try, suggested by several people, is to preallocate
more pages before the run, e.g.:
:q ; exit the ACL2 loop
(si::allocate 'cons 75000 t)
(lp) ; re-enter the ACL2 loop
Also see [reset-kill-ring] for a suggestion on how to free up space.
3. Windows users have seen this error:
cc1.exe: unrecognized option `-fno-zero-initialized-in-bss'
Camm Maguire suggests that a solution may be to evaluate the
following in GCL before building ACL2.
(in-package 'compiler)
(let* ((x `-fno-zero-initialized-in-bss')
(i (search x *cc*)))
(setq *cc* (concatenate 'string
(subseq *cc* 0 i)
(subseq *cc* (+ i (length x))))))
4. It is possible to profile using ACL2 built on GCL. See file
save-gprof.lsp in the ACL2 source directory.
5. Some versions of GCL may have garbage-collector bugs that, on rare
occasions, cause ACL2 (when built on GCL) to break. If you run into
this, a solution may be to execute the following:
:q
(si::sgc-on nil)
(lp)
Alternatively, put (si::sgc-on nil) in your ~/acl2-init.lsp file.
A full regression test and found that this decreased performance by
about 10%. But even with that, GCL is probably one of the faster
Common Lisp implementations for ACL2 on Linux. Performance figures
may often be found by following the ``Recent changes'' link on the
ACL2 home page.
6. GCL operations on numbers can sometimes be sped up, perhaps by up
to two orders of magnitude, by suitable [declare] forms (also see
[type-spec]). The following example, developed with Warren Hunt and
Serita Nelesen, illustrates the use of such declarations.
; File iplus.lisp:
; Operations on naturals together with positive infinity (represented as -1).
; After (ld \"iplus.lisp\"), escape to raw Lisp with :q and then eavluate
; (disassemble 'big-test). You should see lots of arithmetic operations
; in C code, but no calls of C functions CMPmake_fixnum or number_plus.
(in-package \"ACL2\")
(defmacro i-max ()
(expt 2 (1- 28)))
(defmacro i+ (x y)
`(the (signed-byte 28)
(let ((x ,x)
(y ,y))
(declare (type (signed-byte 28) x y))
(cond ((or (< x 0)
(< y 0))
-1)
(t (let ((result
(the (signed-byte 29) (+ x y))))
(declare (type (signed-byte 29) result))
(cond ((>= result (i-max)) -1)
(t (the (signed-byte 28) result)))))))))
(defmacro imin (x y)
`(the (signed-byte 28)
(let ((x ,x)
(y ,y))
(declare (type (signed-byte 28) x y))
(cond ((< x 0)
(cond ((< y 0) -1)
(t y)))
((< y 0)
x)
(t
(the (signed-byte 28) (min x y)))))))
(defun big-test (x y z)
(declare (type (signed-byte 28) x y z))
(imin (i+ x y)
(i+ y (imin x z))))")
(GCS (POINTERS)
"See [get-command-sequence].")
(GENERALIZE
(RULE-CLASSES)
"Make a rule to restrict generalizations
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Example:
(defthm integer-listp-rev
(implies (integer-listp x)
(integer-listp (rev x)))
:rule-classes :generalize)
General Form:
any theorem
To use a :generalize rule, the system waits until it has decided to
generalize some term, term, by replacing it with some new variable
v. If any :generalize formula can be instantiated so that some
non-variable subterm becomes term, then that instance of the
formula is added as a hypothesis. Thus for the example above, if
the term (rev x2) is generalized to the variable rv during a proof,
then the following is added as a hypothesis when generalizing to a
new goal.
(implies (integer-listp x2)
(integer-listp rv))
At the moment, the best description of how ACL2 :generalize rules are
used may be found in the discussion of ``Generalize Rules,'' page
248 of A Computational Logic Handbook, or ``Generalization,'' page
132 of ``Computer-Aided Reasoning: An Approach.'' Also see
[introduction-to-the-theorem-prover] for detailed tutorial on using
ACL2 to prove theorems, which includes some discussion of
generalization.")
(GENERALIZED-BOOLEANS
(COMMON-LISP)
"Potential soundness issues related to ACL2 predicates
The discussion below outlines a potential source of unsoundness in
ACL2. Although to our knowledge there is no existing Lisp
implementation in which this problem can arise, nevertheless we
feel compelled to explain this situation.
Consider for example the question: What is the value of (equal 3 3)?
According to the ACL2 axioms, it's t. And as far as we know, based
on considerable testing, the value is t in every Common Lisp
implementation. However, according the Common Lisp draft proposed
ANSI standard, any non-nil value could result. Thus for example,
(equal 3 3) is allowed by the standard to be 17.
The Common Lisp standard specifies (or soon will) that a number of
Common Lisp functions that one might expect to return Boolean
values may, in fact, return arbitrary values. Examples of such
functions are [equal], [rationalp], and [<]; a much more complete
list is given below. Indeed, we dare to say that every Common Lisp
function that one may believe returns only Booleans is,
nevertheless, not specified by the standard to have that property,
with the exceptions of the functions not and null. The standard
refers to such arbitrary values as ``generalized Booleans,'' but in
fact this terminology makes no restriction on those values. Rather,
it merely specifies that they are to be viewed, in an informal
sense, as being either nil or not nil.
This situation is problematic for ACL2, which axiomatizes these
functions to return Booleans. The problem is that because (for
efficiency and simplicity) ACL2 makes very direct use of compiled
Common Lisp functions to support the execution of its functions,
there is in principle a potential for unsoundness due to these
``generalized Booleans.'' For example, ACL2's [equal] function is
defined to be Common Lisp's equal. Hence if in Common Lisp the form
(equal 3 3) were to evaluate to 17, then in ACL2 we could prove
(using the :[executable-counterpart] of [equal]) (equal (equal 3 3)
17). However, ACL2 can also prove (equal (equal x x) t), and these
two terms together are contradictory, since they imply
(instantiating x in the second term by 3) that (equal 3 3) is both
equal to 17 and to t.
To make matters worse, the standard allows (equal 3 3) to evaluate to
different non-nil values every time. That is: equal need not even
be a function!
Fortunately, no existing Lisp implementation takes advantage of the
flexibility to have (most of) its predicates return generalized
Booleans, as far as we know. We may implement appropriate
safeguards in future releases of ACL2, in analogy to (indeed,
probably extending) the existing safeguards by way of guards (see
[guard]). For now, we'll sleep a bit better knowing that we have
been up-front about this potential problem.
The following list of functions contains all those that are defined
in Common Lisp to return generalized Booleans but are assumed by
ACL2 to return Booleans. In addition, the functions [ACL2-numberp]
and [complex-rationalp] are directly defined in terms of respective
Common Lisp functions numberp and complexp.
/=
<
=
alpha-char-p
atom
char-equal
char<
char<=
char>
char>=
characterp
consp
digit-char-p
endp
eq
eql
equal
evenp
integerp
keywordp
listp
logbitp
logtest
lower-case-p
minusp
oddp
plusp
rationalp
standard-char-p
string-equal
string<
string<=
string>
string>=
stringp
subsetp
symbolp
upper-case-p
zerop")
(GENERALIZING-KEY-CHECKPOINTS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Getting rid of unnecessary specificity
Suppose MEMBER determines whether its first argument is a member of
its second, and SUBSETP determines whether every element of its
first argument is a member of its second. Suppose that you're
trying to prove some Main Theorem and are told the formula below is
a key checkpoint. What should you do?
Key Checkpoint:
(IMPLIES (AND (CONSP A)
(INTEGERP (CAR A))
(MEMBER (CAR A) B)
(SUBSETP (CDR A) B)
(NOT (SUBSETP (CDR A) (APPEND B C))))
(MEMBER (CAR A) C))
The key observation is that the third hypothesis implies the negation
of the fourth. Writing it in the contrapositive:
(IMPLIES (AND ...
(SUBSETP (CDR A) B)
...)
(SUBSETP (CDR A) (APPEND B C)))
In fact, that is more complicated than it needs to be. A ``correct''
response to the key checkpoint above is to prove
(defthm subsetp-append
(implies (subsetp a b)
(subsetp a (append b c)))).
A still better response is to prove this:
(defthm subsetp-append-2
(implies (or (subsetp a b)
(subsetp a c))
(subsetp a (append b c)))).
This version is better because it handles both of the possibilities
regarding whether a is a subset of the arguments of the append.
It would be nice if we could think of a ``strong'' version, one in
which (SUBSETP a (APPEND b c)) is rewritten to some clearly simpler
term, but nothing comes to mind.
In any case, if you cannot see any obvious simplification of the
individual terms in the Key Checkpoint, you should ask yourself
whether there are connections beween the various propositional
parts (as here, with the third and fourth hypotheses). It is a good
heuristic to look for relations between parts with the same
top-level function symbol (as here, with SUBSETP). It is also a
good heuristic to throw out parts of the formula that seem
disconnected (as here, with the terms involving (CAR A)).
This discussion suggests several ``modes'' of looking at key
checkpoints and the idea of trying the modes in sequence:
(1) look for simplifiable combinations of function symbols within
propositional components,
(2) look for relations between propositional components, and
(3) throw out irrelevant or weakly connected components.
In all cases you are bringing to bear your intuitions about the
semantics of the terms. That is, you're not just slinging symbols.
You should be looking out for obvious truths about individual parts
of the checkpoints... truths that are obvious to you but not to
ACL2!
Ultimately the three ``modes'' are the same and we do not really
recommend adhering to the given sequence. You're just looking for
simpler theorems that, in combination, imply the checkpoint.
Keeping the ``modes'' in mind may help focus your attention so you
consider all the plausible possibilities. After a little experience
you'll find yourself looking for all these things simultaneously as
part ``cleaning up'' the checkpoints.
When your main goal theorems are harder than these, your main concern
will be looking at a Key Checkpoint and asking yourself ``why is
this true?'' But you don't want to do that until you've cleaned it
up ``locally'' as much as possible and sometimes -- more often than
you might think -- local considerations can prove many of your
checkpoints.
If you have been working your way through the tutorial introduction
to the theorem prover, use your browser's Back Button now to return
to [introduction-to-key-checkpoints].")
(GET-CHECK-INVARIANT-RISK (POINTERS)
"See [set-check-invariant-risk].")
(GET-COMMAND-SEQUENCE
(HISTORY)
"Return list of [command]s that are between two [command] descriptors
Examples:
(get-command-sequence 4 12)
:gcs 4 12 ; same as above
(get-command-sequence 4 :x)
:gcs 4 :x ; same as above
See [pcs] for a utility that prints abbreviated information about the
[command]s that are between two command descriptors. The utility
get-command-sequence --- or simply gcs, so that you can just type
:gcs at the prompt --- has the same syntax but instead of printing,
it simply returns the corresponding list of commands. More
precisely, it returns an [error-triple] (mv erp val state) such
that if erp is not nil, then val is the desired list of commands.")
(GET-EVENT-DATA
(SYSTEM-UTILITIES PROVER-OUTPUT)
"Obtain data stored after at the conclusion of an event
Warning: This is a low-level system utility that may change somewhat
over time. For more details, see the ACL2 source code.
Evaluation of the form (get-event-data key state) returns the value
of key in an association list, namely, in the value of [state]
global variable last-event-data (see [programming-with-state]).
That alist contains certain information stored at the conclusion of
the immediately preceding event. For each key the corresponding
value, VAL, is as follows.
* ABORT-CAUSES: VAL is a list of reasons why the proof aborted. In
particular, if the value INTERRUPT is in the list, then the
proof was interrupted (typically with Control-C).
* FORM: VAL is the ``context'' for the event, printed in the summary,
[warnings], and [errors].
* HINT-EVENTS: VAL is as in the corresponding field of the event
summary.
* NAMEX: VAL is 0, a single name, or a list of names; see comments in
ACL2 source function access-event-tuple-namex.
* PROVER-STEPS-COUNTED: VAL is as in the corresponding field of the
event summary.
* RULES: VAL is as in the corresponding field of the event summary.
* SPLITTER-RULES: VAL represents the corresponding field of the event
summary, as the list (case-split immed-forced if-intro).
* TIME: VAL represents the corresponding field of the event summary, as
the list (prove print proof-tree other).
* WARNINGS: VAL is as in the corresponding field of the event summary.")
(GET-INTERNAL-TIME
(PROGRAMMING ACL2-BUILT-INS)
"Runtime vs. realtime in ACL2 timings
The ACL2 system provides utilities that deal with elapsed time. The
most visible of these is in the time summaries printed when
completing evaluation of [events]. For others, see
[with-prover-time-limit], see [read-run-time], see [time-tracker],
see [time-tracker-tau], and see [pstack].
By default, these utilities all use an underlying notion of run time
provided by the host Common Lisp implementation: specifically, the
Common Lisp function get-internal-run-time. However, Common Lisp
also provides the function get-internal-real-time, which returns
the real time (wall clock time). While the latter is specified to
measure elapsed time, the former is left to the implementation,
which might well only measure time spent in the Lisp process.
Consider the following example, which is a bit arcane but basically
sleeps for 2 seconds.
(defttag t) ; to allow sys-call
(make-event
(prog2$ (sys-call \"sleep\" '(\"2\"))
(value '(value-triple nil))))
A typical time summary might be as follows, drastically
under-reporting the elapsed time.
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
However, you can instruct ACL2 to switch to using elapsed time (real
time), in summaries and elsewhere, by evaluating the following
form.
(assign get-internal-time-as-realtime t)
To return to using runtime:
(assign get-internal-time-as-realtime nil)
While the above example is rather silly, the issue becomes
significant in time summaries for proofs that call out to external
tools (see [sys-call] and see [clause-processor]).
Note that a function get-internal-time is defined in raw Lisp but is
not available inside the ACL2 loop. However, the expression
(read-run-time state) provides an interface to this function that
is available inside the ACL2 loop; see [read-run-time].
We are open to changing the default to elapsed wall-clock time
(realtime), and may do so in future ACL2 releases.
Implementation note (GCL only): If the host Lisp is Gnu Common Lisp,
then get-internal-run-time has a multiple value return, and the
first two values (runtime and child runtime) are added together to
produce a result for get-internal-time.")
(GET-OUTPUT-STREAM-STRING$ (POINTERS)
"See [io].")
(GET-WORMHOLE-STATUS
(WORMHOLE)
"Make a wormhole's status visible outside the wormhole
General Form: (get-wormhole-status name state)
Name should be the name of a wormhole (see [wormhole]). This function
returns an [error-triple] of the form (mv nil s state), where s is
the status of the named wormhole. The status is obtained by reading
the oracle in the ACL2 [state].
This function makes the status of a wormhole visible outside the
wormhole. But since this function takes [state] and modifies it,
the function may only be used in contexts in which you may change
[state]. Otherwise, the wormhole status may stay in the wormhole.
See [wormhole-eval] and [wormhole].")
(GETENV$
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Read an environment variable
(Getenv$ str state), where str is a string, reads the value of
environment variable str, returning a value of nil if none is found
or if the read fails. The logical story is that getenv$ reads its
value from the oracle field of the ACL2 [state]. The return value
is thus a triple of the form (mv erp val state), where erp will
always be nil in practice, and logically, val is the top of the
acl2-oracle field of the state (see [read-ACL2-oracle]) and the
returned state has the updated (popped) acl2-oracle.
Example:
(getenv$ \"PWD\" state) ==> (mv nil \"/u/joe/work\" state)
Also see [setenv$].
Function: <getenv$>
(defun getenv$ (str state)
(declare (xargs :stobjs state
:guard (stringp str)))
(declare (ignore str))
(read-acl2-oracle state))")
(GETPROP
(WORLD ACL2-BUILT-INS)
"Access fast property lists
General form:
(getprop symb key default world-name world-alist)
See community book books/misc/getprop.lisp for an example that
illustrates the use of ACL2 utilities [getprop] and putprop to take
advantage of under-the-hood Lisp (hashed) property lists. Also see
[getpropc] for a convenient abbreviation.
Macro: <getprop>
(defmacro
getprop
(symb key default world-name world-alist)
(if (equal world-name ''current-acl2-world)
(cons 'fgetprop
(cons symb
(cons key
(cons default (cons world-alist 'nil)))))
(cons 'sgetprop
(cons symb
(cons key
(cons default
(cons world-name
(cons world-alist 'nil))))))))")
(GETPROPC
(WORLD ACL2-BUILT-INS)
"Access fast property lists
General form:
(getpropc symb key &optional default world-alist)
where default is nil if omitted, and world-alist is (w state) if
omitted. This is a convenient abbreviation for the common case in
which [getprop] is used for system programming, with
'current-acl2-world as the (implicit, for getpropc) world-name.
Macro: <getpropc>
(defmacro
getpropc
(symb key &optional default (wrld '(w state)))
(cons
'getprop
(cons symb
(cons key
(cons default
(cons (cons 'quote
(cons 'current-acl2-world 'nil))
(cons wrld 'nil)))))))")
(GETTING-STARTED (POINTERS)
"See [ACL2-tutorial].")
(GIT-QUICK-START
(ABOUT-ACL2)
"Git quick start guide
Each of the two topics [github-commit-code-using-push] and
[github-commit-code-using-pull-requests] presents a minimal guide
to using the Github repository for ACL2+Books. That {repository |
https://github.com/acl2/acl2} exists on the web and contains the
``bleeding edge'' ACL2 source code and [community-books], available
between ACL2 releases (see [release-notes]). Those who are familiar
with older version control systems, or perhaps with no version
control systems, might find this guide to be helpful. For
additional information, including the use of branches and links to
more information about git, see {the wiki page for git tips |
https://github.com/acl2/acl2/wiki/ACL2-repo-git-tips},
[books-certification], and the Internet in general. However, both
of the above-mentioned guides are intended to be sufficient for you
to obtain the latest ACL2 source code and community-books, and
optionally, for you to contribute to the [community-books].
Select the guide that is right for you based upon the headings below.
For non-contributors:
See sections (A) and (B) in [github-commit-code-using-push].
For infrequent contributors:
For those only planning on contributing a few times per year (or
less), see [github-commit-code-using-pull-requests].
For frequent contributors:
For those contributing on a monthly or weekly basis, see
[github-commit-code-using-push].
Subtopics
[Github-commit-code-using-pull-requests]
How to commit code to the books using pull requests
[Github-commit-code-using-push]
How to commit code to the books using direct push access")
(GITHUB-COMMIT-CODE-USING-PULL-REQUESTS
(GIT-QUICK-START)
"How to commit code to the books using pull requests
This guide is written for contributors who will probably only commit
to the repository a few times a year. If you find yourself
committing more often, you should see
[github-commit-code-using-push].
A nice result of using pull requests is that all changes will be
peer-reviewed before being committed. Also, we sometimes call this
method theFork and Pullmethod.
(A) GETTING STARTED
1. Go to {https://github.com/acl2/acl2 | https://github.com/acl2/acl2}
and click on the fork button on the top-right. Fork the
repository into your github space. This will create a new
repository at https://github.com/<your-github-username>/acl2.
2. In your working space on your computer, create a clone of your github
repository and cd into it:
git clone https://github.com/<your-github-username>/acl2
cd acl2
3. Add the Community ACL2 repository as a git remote:
git remote add upstream https://github.com/acl2/acl2
(B) UPDATING
The following commands will update your local repository to match the
latest contents of the ACL2 Community github repository (on the
web).
git fetch --all
git merge remotes/upstream/master
(C) CONTRIBUTING
Change and Test
1. Before beginning your edits, update, as in (B) above:
git fetch --all
git merge remotes/upstream/master
2. Build an executable.
(time nice make LISP=<your_lisp>) >& make.log
3. Make book changes. If you are creating any new books, tell git that
you intend to add them (but the local repository on the web
won't change until the commit step below is executed).
git add file1 file2 ...
4. Run a regression.
(time nice make -j 8 regression-fresh) >& make-regression.log
Note that the -j 8 option specifies the use of 8 hardware threads;
feel free to omit it or use a more suitable number (especially
if your computer has other than 8 hardware threads).
5. Look for failures, as indicated by ** in the log.
fgrep -a '**' make-regression.log
6. If there were failures, then go back to Step 1 above to make
appropriate changes and re-test, but you can replace the 'make'
step by replacing regression-fresh with regression, since
'make' is clever enough to avoid recertifying more than is
necessary. For example:
(time nice make -j 8 regression) >& make-regression-finish-1.log
Update, and Iterate If Necessary
Update again as in (B) above:
git fetch --all
git merge remotes/upstream/master
The merge may fail if there have been remote updates, that is updates
in the repository on the web. In that case, commit your changes
locally and then try the merge again. You might want to use the
-F option instead of -m; see the next section for more on those
options.
git commit -a -m '<some message, with descriptive first line>'
git merge remotes/upstream/master
If the second command (the git merge) prompts you for a message, the
empty message should suffice as a reasonable default (in emacs
-- if vi tries to come up, just type :q and <RETURN>.
You can now go on to the next step (Contribute Your Changes). But
ideally: If the output indicates that anything has changed, then go
back to ``Change and Test'' above. Of course, you can skip the
build if no ACL2 sources have changed, and you can skip making book
changes if you are still happy with your changes.
Contribute Your Changes
The following commands will update your github repository on the web.
The -m ... option is a log message whose first line should be a
summary of your changes and other lines may give more details. You
are welcome to replace the -m ... option by -F <filename>, where
<filename> is the name of a file that contains your log message.
git commit -a -m '<some message, with descriptive first line>'
git push
You now need to create apull request, where you request that changes from your github repository be
accepted into the Community ACL2 repository. To achieve this:
1. Goto https://github.com/<your-github-username>/acl2.
2. Click the Pull request button (you can search for it with your
browser).
3. In the drop-down box labeled \"base\" (next to the box labeled \"base
fork\"), change the value from \"master\" to \"testing\".
4. Click Create pull request.
5. Put some explanation about what's in the changes in the comments
section. It's helpful if you quote (possibly abbreviated)
versions of your commit log messages here, as that way the
descriptions are easily read when clicking on the Community
Repository commits tab, which goes to {
https://github.com/acl2/acl2/commits/master |
https://github.com/acl2/acl2/commits/master}.
6. Click Create pull request.
At this point, the Community ACL2 repository maintainers will be
notified, check that things seem to be in order, and then adopt your
changes.")
(GITHUB-COMMIT-CODE-USING-PUSH
(GIT-QUICK-START)
"How to commit code to the books using direct push access
This guide is written for two groups of people:
* Users of the ACL2 System and Books who do not plan to contribute to
the books, and
* Contributors who commit to the repository on a monthly or weekly
basis. In this case, a contributor will typically begin with
the [github-commit-code-using-pull-requests] method, and after
they are familiar with the process and community, they will
move to this method.
(A) GETTING STARTED
Start by obtaining an up-to-date copy of the web-based github
repository. Here, we show how to put it into into a directory
called ACL2 (but name it whatever you like).
mkdir ACL2
cd ACL2
git clone https://github.com/acl2/acl2 .
(B) UPDATING
The following commands will update your directory to match the latest
contents of the github repository (on the web).
git fetch --all
git merge remotes/origin/master
(C) CONTRIBUTING (optional)
To join the {github project | https://github.com/acl2/acl2/}, please
send email to one of the following individuals.
* Jared Davis (jared.c.davis@gmail.com)
* David Rager (ragerdl@gmail.com)
* Sol Swords (sswords@gmail.com)
After you have joined the project, you can proceed as follows when
you are ready to contribute.
Change and Test
1. Update as in (B) above:
git fetch --all
git merge remotes/origin/master
2. Build an executable.
(time nice make LISP=<your_lisp>) >& make.log
3. Make book changes. If you are creating any new books, tell git that
you intend to add them (but the repository on the web won't
change until the last step below is executed).
git add file1 file2 ...
4. Run a regression.
(time nice make -j 8 regression-fresh) >& make-regression.log
5. Look for failures, as indicated by ** in the log.
fgrep -a '**' make-regression.log
6. If there were failures, then go back to Step 1 above to make
appropriate changes and re-test, but you can replace the 'make'
step by replacing regression-fresh with regression, since
'make' is clever enough to avoid recertifying more than is
necessary. For example:
(time nice make -j 8 regression) >& make-regression-finish-1.log
Note that the -j 8 option specifies the use of 8 hardware threads;
feel free to omit it or use a more suitable number (especially
if your computer has other than 8 hardware threads).
Update, and Iterate If Necessary
Update again as in (B) above:
git fetch --all
git merge remotes/origin/master
The merge may fail if there have been remote updates, that is updates
in the repository on the web. In that case, commit your changes
locally and then try the merge again. You might want to use the
-F option instead of -m; see the next section for more on those
options.
git commit -a -m '<some message, with descriptive first line>'
git merge remotes/origin/master
If the second command prompts you for a message, the empty message
should suffice as a reasonable default. (In emacs, if vi tries
to come up, just type :q and <RETURN>.
You can now go on to the next step (Contribute Your Changes). But
ideally: If the output indicates that anything has changed, then go
back to ``Change and Test'' above. Of course, you can skip the
build if no ACL2 sources have changed, and you can skip making book
changes if you are still happy with your changes.
Contribute Your Changes
The following commands will update the github repository on the web.
The -m ... option is a log message whose first line should be a
summary of your changes and other lines may give more details. You
are welcome to replace the -m ... option by -F <filename>, where
<filename> is the name of a file that contains your log message.
git commit -a -m '<some message, with descriptive first line>'
git push")
(GOAL-SPEC
(HINTS)
"To indicate where a hint is to be used
Examples:
\"Goal\"
\"goal\"
\"Subgoal *1/3''\"
\"subgoal *1/3''\"
\"[2]Subgoal *1/3''\"
When [hints] are given to the theorem prover, a goal-spec is provided
to specify the goal to which the [hints] are to be applied. The
[hints] provided are carried along innocuously until the named goal
arises. When it arises, the [hints] are ``activated'' for that goal
and its descendents.
A legal goal specification may be extracted from the theorem prover's
output. Certain lines clearly label formulas, as in
Subgoal *1/3.2'
(IMPLIES ... ...)
and these lines all give rise to goal specifications. In general,
these lines all start either with ``Goal'' or ``Subgoal'' or else
with those words preceded by a number in square brackets, as in
[1]Subgoal *1/3.2'
(IMPLIES ... ...).
A goal specification may be obtained by deleting any surrounding
whitespace from such a line and embedding the text in string
quotation marks. Thus
\"[1]Subgoal *1/3.2'\"
is the goal specifier for the goal above.
As noted, a hint is applied to a goal when the hint's goal
specification matches the name ACL2 assigns to the goal. The
matching algorithm is case-insensitive. Thus, alternative goal
specifications for the goal above are \"[1]subgoal *1/3.2'\" and
\"[1]SUBGOAL *1/3.2'\". The matching algorithm does not tolerate
non-case discrepancies. Thus, \"[1]Subgoal*1/3.2'\" and \" [1]Subgoal
*1/3.2'\" are unacceptable.
Sometimes a formula is given two names, e.g.,
Subgoal *1/14.2'
(IMPLIES ...
...)
Name the formula above *1.1.
It is the first name (the one that starts with ``Goal'' or
``Subgoal'') and not the second which constitutes a legal
goal-spec. Roughly speaking, when the system prints the line
containing the goal specification, it activates any [hints] that
are attached to that goal-spec. Consider the example above. Suppose
Subgoal *1/14.2' could be proved by using a certain lemma instance.
Then the appropriate entry in the [hints] would be:
(\"Subgoal *1/14.2'\" :use ...)
This might surprise you because the system appears to do nothing to
*1/14.2' besides push it for a subsequent induction. But actually
between the time the system printed the goal-spec line and the time
it decides to push the goal, you can think of the system as trying
everything it has. So a use hint activated when Subgoal *1/14.2'
arises is just what you want.
But what if you want to give an :induct hint? By the time induction
is tried, the formula has been given the name *1.1. Well, this is
one you just have to remember:
(\"Subgoal *1/14.2'\" :induct ...).
When the above hint is activated the :induct directive short-circuits
the rest of the processing and sends immediately the formula into
the pool of goals to prove by induction. The induct hint is
attached to the formula in the pool and when the time comes to turn
our attention to that goal, the induct advice is followed.
We conclude by emphasizing a point made above, that a hint is applied
to a goal when the hint's goal specification matches the name ACL2
assigns to the goal. If there is no such match, then the hint is
ignored. Consider the following example.
(thm (equal (append (append x y) z) (append x y z))
:hints ((\"Subgoal *1/\" :in-theory nil)))
Normally, :in-theory hints are inherited by subgoals (see
[hints-and-the-waterfall]), so you might expect that the empty
theory is used in Subgoal *1/2 and Subgoal *1/1. But in fact, since
there is no subgoal printed that is labeled Subgoal *1/, the above
:in-theory hint is ignored. The above example is in contrast to the
following, where the hint makes the proof fail, because there
really is a Subgoal *1/ in the proof this time.
(thm (implies (and (not (endp x)) (not (endp (cdr x))))
(equal (append (append x y) z) (append x y z)))
:hints ((\"Subgoal *1/\" :in-theory nil)))
Subtopics
[Clause-identifier]
The internal form of a [goal-spec]")
(GOOD-ATOM-LISTP
(ATOM LISTS ACL2-BUILT-INS)
"Recognizer for a true list of ``good'' [atom]s
The predicate good-atom-listp tests whether its argument is a
[true-listp] of ``good'' [atom]s, i.e., where each element is a
number, a symbol, a character, or a string.
Also see [atom-listp].
Function: <good-atom-listp>
(defun good-atom-listp (lst)
(declare (xargs :guard t))
(cond ((atom lst) (eq lst nil))
(t (and (or (acl2-numberp (car lst))
(symbolp (car lst))
(characterp (car lst))
(stringp (car lst)))
(good-atom-listp (cdr lst))))))")
(GOOD-BYE
(BASICS ACL2-BUILT-INS)
"Quit entirely out of Lisp
Examples:
ACL2 !>(good-bye)
; [ACL2 is exited]
ACL2 !>(good-bye 3)
; [ACL2 is exited with Unix exit status 3]
Note: Your entire session will disappear forever when you evaluate
(good-bye).
The command (good-bye) quits not only out of the ACL2 [command] loop,
but in fact quits entirely out of the underlying Lisp. Thus, there
is no going back! You will not be able to re-enter the [command]
loop after typing (good-bye)! All your work will be lost!!!
This command may not work in some underlying Common Lisp
implementations. In such cases, there is no harm in trying; ACL2
will let you know how to proceed if it cannot exit.
In some systems, typing control-d at the top-level ACL2 prompt
(control-c control-d if inside emacs) will call this function.
If you give good-bye an argument, it should be a natural number, and
it indicates the Unix (Linux) exit status.
If you merely want to exit the ACL2 [command] loop, use :q instead
(see [q]).
Subtopics
[Exit]
Quit entirely out of Lisp
[Quit]
Quit entirely out of Lisp")
(GRANULARITY
(PARALLEL-PROGRAMMING)
"Limit the amount of parallelism
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
Some function calls are on arguments whose evaluation time is long
enough to warrant parallel execution, while others are not. A
granularity form can be used to make appropriate restrictions on
the use of parallelism.
For example, consider the Fibonacci function. Experiments have
suggested that execution time can be reduced if whenever the
argument is less than 27, a serial version of the Fibonacci
function is called. One way to utilize this information is to write
two definitions of the Fibonacci function, one serial and one
parallel.
(defun fib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
(t (binary-+ (fib (- x 1))
(fib (- x 2))))))
(defun pfib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
((< x 27) (binary-+ (fib (- x 1))
(fib (- x 2))))
(t (pargs (binary-+ (pfib (- x 1))
(pfib (- x 2)))))))
We realize quickly that writing both of these function definitions is
cumbersome and redundant. This problem can be avoided by using a
granularity declaration with a parallelism primitive. This form
ensures that a call is parallelized only if resources are available
and the granularity form evaluates to a non-nil value at the time
of the call. Below is a definition of the Fibonacci function using
a granularity form.
(defun pfib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
(t (pargs (declare (granularity (>= x 27)))
(binary-+ (pfib (- x 1))
(pfib (- x 2)))))))
A granularity form can reference an extra formal parameter that
describes the call depth of the function the user is parallelizing.
Consider for example the following parallel mergesort function,
based on Davis's Ordered Sets library. It splits the data into
symmetric chunks for computation, so we increment the depth
argument during the recursive call on both the car and cdr.
(include-book \"finite-set-theory/osets/sets\" :dir :system)
(defun set::pmergesort-exec (x depth)
(declare (xargs :mode :program))
(cond ((endp x) nil)
((endp (cdr x)) (set::insert (car x) nil))
(t (mv-let (part1 part2)
(set::split-list x nil nil)
(pargs
(declare (granularity (< depth 2)))
(set::union (set::pmergesort-exec part1
(1+ depth))
(set::pmergesort-exec part2
(1+ depth))))))))
A less intrusive method (i.e., not requiring an extra formal
parameter like the depth argument just above), which however can be
less efficient, involves analyzing the data itself for structural
properties. For example:
(defun some-depth-exceeds (x n)
(declare (xargs :guard (natp n)))
(if (atom x)
nil
(if (zp n)
t
(or (some-depth-exceeds (car x) (1- n))
(some-depth-exceeds (cdr x) (1- n))))))
(defun valid-tip (x)
(declare (xargs :guard t))
(or (eq x 'A)
(eq x 'T)
(eq x 'C)
(eq x 'G)))
(defun pvalid-tree (x)
(declare (xargs :guard t))
(if (atom x)
(valid-tip x)
(pand (declare (granularity (some-depth-exceeds x 3)))
(pvalid-tree (car x))
(pvalid-tree (cdr x)))))
If you experiment with calls of pvalid-tree, you are likely to find
that the ``speedup'' it provides over a corresponding serial
version is, in fact, a slowdown! The problem is likely that
some-depth-exceeds is an expensive function to run repeatedly.
Instead of the approach above, it is often handy to add an extra
formal parameter in order to allow for more efficient granularity
forms, as we have done above in the definition of
SET::pmergesort-exec.")
(GROUND-ZERO
(THEORIES THEORY-FUNCTIONS)
"[enable]d rules in the [startup] theory
ACL2 concludes its initialization (boot-strapping) procedure by
defining the theory ground-zero; see [theories]. In fact, this
theory is just the theory defined by (current-theory :here) at the
conclusion of initialization; see [current-theory].
Note that by evaluating the event
(in-theory (current-theory 'ground-zero))
you can restore the current theory to its value at the time you
started up ACL2.")
(GTHM
(HISTORY GUARD)
"The [guard] theorem for a given function symbol
Example Forms:
:gthm FN
(gthm 'FN) ; equivalent to the above
where FN is a function symbol. This shows the [guard] theorem for FN;
see [lemma-instance]. More precisely, evaluation of a call of this
macro --- pronounced ``gee-thumb'' --- returns an [error-triple]
whose value component is the user-level (untranslated) version of
that guard theorem. Also see [lemma-instance] for discussion of a
way to give this theorem as a :guard-theorem prover hint.
Technical note: a corresponding evaluation that provides a
(translated) [termp] is: (guard-theorem 'FN (w state) state).")
(GUARD
(PROGRAMMING XARGS)
"Restricting the domain of a function
The ACL2 system provides a mechanism for restricting a function to a
particular domain. Such restrictions are called ``guards.'' A
definition's guard has no effect on the logical axiom added when
that definition is accepted by ACL2, and novices are often best
served by avoiding guards. However, guards can be useful as a
specification device or for increasing execution efficiency. To
make such a restriction, use the :guard keyword (see [xargs]) or,
especially if you want the host Lisp compiler to use this
information, use type declarations (see [declare]; also see [xargs]
for a discussion of the :split-types keyword). The general issue of
guards and guard verification is discussed in the topics listed
below.
To begin further discussion of guards, see [guard-introduction]. That
section directs the reader to further sections for more details. To
see just a summary of some [command]s related to guards, see
[guard-quick-reference]. For a discussion of the use of proof to
verify the absence of guard violations, see [verify-guards].
Subtopics
[Ec-call]
Execute a call in the ACL2 logic instead of raw Lisp
[Extra-info]
Sources of measure or guard proof obligations
[Gthm]
The [guard] theorem for a given function symbol
[Guard-debug]
Generate markers to indicate sources of [guard] proof obligations
[Guard-evaluation-examples-log]
Log showing combinations of [defun-mode]s and [guard]-checking
[Guard-evaluation-examples-script]
A script to show combinations of [defun-mode]s and [guard]-checking
[Guard-evaluation-table]
A table that shows combinations of [defun-mode]s and
[guard]-checking
[Guard-example]
A brief transcript illustrating [guard]s in ACL2
[Guard-holders]
Remove trivial calls from a [term]
[Guard-introduction]
Introduction to [guard]s in ACL2
[Guard-miscellany]
Miscellaneous remarks about guards
[Guard-obligation]
The guard proof obligation
[Guard-quick-reference]
Brief summary of guard checking and guard verification
[Guard-theorem]
Use a previously-proved [guard] theorem
[Guard-theorem-example]
How to use a previously-proved [guard] theorem
[Guards-and-evaluation]
The relationship between guards and evaluation
[Guards-for-specification]
Guards as a specification device
[Mbe]
Attach code for execution
[Non-exec]
Mark code as non-executable
[Print-gv]
Print a form whose evaluation caused a guard violation
[Set-check-invariant-risk]
Potential slowdown for [program]-mode updates to [stobj]s or
[arrays]
[Set-guard-checking]
Control checking [guard]s during execution of top-level forms
[Set-guard-msg]
Specify what is printed when a [guard] is violated
[Set-print-gv-defaults]
Set default keyword values for [print-gv]
[Set-verify-guards-eagerness]
The eagerness with which [guard] verification is tried.
[The]
The is a special form that can be used to optimize the execution
efficiency of [guard]-verified ACL2 definitions, or (less
frequently) to carry out a low-level run-time type checks.
(Advanced)
[Verify-guards]
Verify the [guard]s of a function
[Verify-guards-formula]
View the guard proof obligation, without proving it
[With-guard-checking]
Suppressing or enable guard-checking for a form
[With-guard-checking-error-triple]
Suppressing or enable guard-checking for a form")
(GUARD-DEBUG
(GUARD DEBUGGING)
"Generate markers to indicate sources of [guard] proof obligations
ACL2 guard verification (see [guard]) is often best avoided by
beginning users of ACL2. When guard verification is employed, it
can generate numerous goals, some of which may not be theorems if
the definition being processed has bugs. It can be difficult to
find such bugs. This [documentation] topic explains a capability
provided by ACL2 to help find such bugs.
For a similar utility appropriate for proving [measure] conjectures
(that is, for termination proofs), see [measure-debug].
We begin with the following example. Although it is contrived and a
bit simplistic, it illustrates how the guard-debug utility works.
(defun length-repeat (x)
(length (append x x)))
(verify-guards length-repeat :guard-debug t)
The output produces two top-level key checkpoints, as follows.
Subgoal 2
(IMPLIES (EXTRA-INFO '(:GUARD (:BODY LENGTH-REPEAT))
'(APPEND X X))
(TRUE-LISTP X))
Subgoal 1
(IMPLIES (AND (EXTRA-INFO '(:GUARD (:BODY LENGTH-REPEAT))
'(LENGTH (APPEND X X)))
(NOT (TRUE-LISTP (APPEND X X))))
(STRINGP (APPEND X X)))
The upper subgoal (numbered 2) says that the body of the definition
of length-repeat contains a call (APPEND X X), which is the source
of the goal. In this case, that makes sense: the [guard] for a call
(append arg1 arg2) is (true-listp arg1), which in this case is
(TRUE-LISTP X). The lower subgoal (numbered 1) says that the same
definition contains the call (LENGTH (APPEND X X)), which generates
the proof obligation that if (APPEND X X) does not satisfy
true-listp, then it must satisfy stringp. That proof obligation
comes directly from the [guard] for [length].
Of course, the example above is a bit obvious. But for large
definitional bodies such information can be very helpful. Note that
guard-debug can be specified not only in [verify-guards] events but
also in [xargs] [declare] forms of [defun] events.
We now describe the guard-debug utility in some detail.
(Extra-info x y) always returns t by definition. However, if [guard]
verification takes place with a non-nil setting of guard-debug (see
below), then the goals generated for guard verification can include
hypotheses that are calls of extra-info. Typically, such a
hypothesis is of the following form:
(extra-info '(:guard (:body F))
'(G ARG1 ... ARGk))
The above form indicates that the goal in which it occurs was
generated to verify that the [guard] of the function F is satisfied
by the arguments ARG1 through ARGk, where the term (G ARG1 ...
ARGk) occurs in the body of the function F whose guard verification
is in progress. If however the above call of G occurs in the guard
of F instead of the body of F, then :body is replaced by :guard
above:
(extra-info '(:guard (:guard F))
'(G ARG1 ... ARGk))
If the same proof obligation (goal clause) arises from more than one
occurrence of the same call, then a single goal will be generated,
which has several extra-info hypotheses added to show the multiple
sources of that proof obligation.
All rules (see [rune]) associated with extra-info are [disable]d by
default, so that hypotheses of the form described above are not
simplified to t. These hypotheses are intended to ride along for
free: you can generally expect the proof to have the same structure
whether or not the :guard-debug option is supplied, though on rare
occasions the proofs may diverge.
It remains to explain the notion of a guard-debug setting of t, that
is, to explain how to obtain the additional hypotheses described
above. If guards are being verified during processing of a [defun]
event (whether or not inside a call of [mutual-recursion]), then
one specifies :guard-debug t in an [xargs] declaration of a
[declare] form; see [xargs]. If however the guard verification is
on behalf of a [verify-guards] call, whether for a definition or a
theorem, then one specifies the keyword argument :guard-debug t.
Also see [print-gv] for a utility for debugging guard violations, in
contrast to the above guard-debug mechanism, which is for debugging
failed proofs arising from guard verification.")
(GUARD-EVALUATION-EXAMPLES-LOG
(GUARD)
"Log showing combinations of [defun-mode]s and [guard]-checking
See [guard-evaluation-examples-script] for a script that shows the
interaction of [defun-mode]s with the value set by
[set-guard-checking]. Here, we present a log resulting from running
this script.
See [set-guard-checking] for discussion of the interaction between
[defun-mode]s and [guard]-checking that is illustrated by this
script. Also see [guard-evaluation-table] for a succinct table,
with associated discussion, that covers in detail the interactions
illustrated here.
ACL2 !>(defun fact (x)
(declare (xargs :guard (integerp x)
:mode :program))
(if (posp x)
(* x (fact (1- x)))
1))
Summary
Form: ( DEFUN FACT ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FACT
ACL2 !>(trace$ fact)
((FACT))
ACL2 !>:set-guard-checking t
Guard-checking-on already has value T.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
ACL2 Error in TOP-LEVEL: The guard for the :program function symbol
FACT, which is (INTEGERP X), is violated by the arguments in the call
(FACT T). See :DOC trace for a useful debugging utility. See :DOC
set-guard-checking for information about suppressing this check with
(set-guard-checking :none), as recommended for new users.
ACL2 !>:set-guard-checking :all
Leaving guard checking on, but changing value to :ALL.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
ACL2 Error in TOP-LEVEL: The guard for the :program function symbol
FACT, which is (INTEGERP X), is violated by the arguments in the call
(FACT T). See :DOC trace for a useful debugging utility. See :DOC
set-guard-checking for information about suppressing this check with
(set-guard-checking :none), as recommended for new users.
ACL2 !>:set-guard-checking :none
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:set-guard-checking nil
Masking guard violations but still checking guards except for self-
recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING
:NONE. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
2> (FACT T)
<2 (FACT 1)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:u
0:x(EXIT-BOOT-STRAP-MODE)
ACL2 >(defun fact (x)
(declare (xargs :guard t
:mode :program))
(if (posp x)
(* x (fact (1- x)))
1))
Summary
Form: ( DEFUN FACT ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FACT
ACL2 >(trace$ fact)
((FACT))
ACL2 >:set-guard-checking t
Turning guard checking on, value T.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
2> (FACT T)
<2 (FACT 1)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 !>:set-guard-checking :all
Leaving guard checking on, but changing value to :ALL.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 !>:set-guard-checking :none
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:set-guard-checking nil
Masking guard violations but still checking guards except for self-
recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING
:NONE. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
2> (FACT T)
<2 (FACT 1)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:u
0:x(EXIT-BOOT-STRAP-MODE)
ACL2 >(defun fact (x)
(declare (xargs :guard (integerp x)
:verify-guards nil
:mode :logic))
(if (posp x)
(* x (fact (1- x)))
1))
For the admission of FACT we will use the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT X). The non-trivial part of the measure conjecture is
[[output omitted here]]
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FACT
ACL2 >(trace$ fact)
((FACT))
ACL2 >:set-guard-checking t
Turning guard checking on, value T.
ACL2 !>(fact 2)
[[Comment added to the log:
Normally you would get a message about guard-checking being
inhibited on recursive calls. However, when a function is
traced the guard-checking is done on recursive calls unless
the guards have been verified (see :DOC verify-guards).
]]
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which
is (INTEGERP X), is violated by the arguments in the call (FACT T).
See :DOC trace for a useful debugging utility. See :DOC set-guard-
checking for information about suppressing this check with (set-guard-
checking :none), as recommended for new users.
ACL2 !>:set-guard-checking :all
Leaving guard checking on, but changing value to :ALL.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which
is (INTEGERP X), is violated by the arguments in the call (FACT T).
See :DOC trace for a useful debugging utility. See :DOC set-guard-
checking for information about suppressing this check with (set-guard-
checking :none), as recommended for new users.
ACL2 !>:set-guard-checking :none
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:set-guard-checking nil
Masking guard violations but still checking guards except for self-
recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING
:NONE. See :DOC set-guard-checking.
ACL2 >(fact 2)
[[Comment added to the log:
In spite of the warning above, guards are checked here on
self-recursive calls, because the function is traced.
]]
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >(verify-guards fact)
Computing the guard conjecture for FACT....
The guard conjecture for FACT is trivial to prove, given the :compound-
recognizer rule POSP-COMPOUND-RECOGNIZER, primitive type reasoning
and the :type-prescription rule FACT. FACT is compliant with Common
Lisp.
Summary
Form: ( VERIFY-GUARDS FACT)
Rules: ((:COMPOUND-RECOGNIZER POSP-COMPOUND-RECOGNIZER)
(:FAKE-RUNE-FOR-TYPE-SET NIL)
(:TYPE-PRESCRIPTION FACT))
Warnings: None
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
FACT
ACL2 >(trace$ fact)
((FACT))
ACL2 >:set-guard-checking t
Turning guard checking on, value T.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which
is (INTEGERP X), is violated by the arguments in the call (FACT T).
See :DOC trace for a useful debugging utility. See :DOC set-guard-
checking for information about suppressing this check with (set-guard-
checking :none), as recommended for new users.
ACL2 !>:set-guard-checking :all
Leaving guard checking on, but changing value to :ALL.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which
is (INTEGERP X), is violated by the arguments in the call (FACT T).
See :DOC trace for a useful debugging utility. See :DOC set-guard-
checking for information about suppressing this check with (set-guard-
checking :none), as recommended for new users.
ACL2 !>:set-guard-checking :none
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:set-guard-checking nil
Masking guard violations but still checking guards except for self-
recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING
:NONE. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:u
L 1:x(DEFUN FACT (X) ...)
ACL2 >:u
0:x(EXIT-BOOT-STRAP-MODE)
ACL2 >(defun fact (x)
(declare (xargs :guard (integerp x)
:mode :logic))
(if (posp x)
(* x (fact (1- x)))
1))
For the admission of FACT we will use the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT X). The non-trivial part of the measure conjecture is
[[output omitted here]]
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FACT
ACL2 >(trace$ fact)
((FACT))
ACL2 >:set-guard-checking t
Turning guard checking on, value T.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which
is (INTEGERP X), is violated by the arguments in the call (FACT T).
See :DOC trace for a useful debugging utility. See :DOC set-guard-
checking for information about suppressing this check with (set-guard-
checking :none), as recommended for new users.
ACL2 !>:set-guard-checking :all
Leaving guard checking on, but changing value to :ALL.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which
is (INTEGERP X), is violated by the arguments in the call (FACT T).
See :DOC trace for a useful debugging utility. See :DOC set-guard-
checking for information about suppressing this check with (set-guard-
checking :none), as recommended for new users.
ACL2 !>:set-guard-checking :none
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:set-guard-checking nil
Masking guard violations but still checking guards except for self-
recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING
:NONE. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:u
0:x(EXIT-BOOT-STRAP-MODE)
ACL2 >(defun fact (x)
(declare (xargs :guard t
:verify-guards nil
:mode :logic))
(if (posp x)
(* x (fact (1- x)))
1))
For the admission of FACT we will use the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT X). The non-trivial part of the measure conjecture is
[[output omitted here]]
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FACT
ACL2 >(trace$ fact)
((FACT))
ACL2 >:set-guard-checking t
Turning guard checking on, value T.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 !>:set-guard-checking :all
Leaving guard checking on, but changing value to :ALL.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 !>:set-guard-checking :none
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:set-guard-checking nil
Masking guard violations but still checking guards except for self-
recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING
:NONE. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (ACL2_*1*_ACL2::FACT 1)
3> (ACL2_*1*_ACL2::FACT 0)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 1)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >(verify-guards fact)
Computing the guard conjecture for FACT....
The guard conjecture for FACT is trivial to prove, given the :compound-
recognizer rule POSP-COMPOUND-RECOGNIZER and the :type-prescription
rule FACT. FACT is compliant with Common Lisp.
Summary
Form: ( VERIFY-GUARDS FACT)
Rules: ((:COMPOUND-RECOGNIZER POSP-COMPOUND-RECOGNIZER)
(:TYPE-PRESCRIPTION FACT))
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FACT
[[Note added to log: No need to trace fact again after verify-guards.]]
ACL2 >:set-guard-checking t
Turning guard checking on, value T.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
2> (FACT T)
<2 (FACT 1)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 !>:set-guard-checking :all
Leaving guard checking on, but changing value to :ALL.
ACL2 !>(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 !>(fact t)
1> (ACL2_*1*_ACL2::FACT T)
2> (FACT T)
<2 (FACT 1)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 !>:set-guard-checking :none
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
2> (FACT T)
<2 (FACT 1)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >:set-guard-checking nil
Masking guard violations but still checking guards except for self-
recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING
:NONE. See :DOC set-guard-checking.
ACL2 >(fact 2)
1> (ACL2_*1*_ACL2::FACT 2)
2> (FACT 2)
3> (FACT 1)
4> (FACT 0)
<4 (FACT 1)
<3 (FACT 1)
<2 (FACT 2)
<1 (ACL2_*1*_ACL2::FACT 2)
2
ACL2 >(fact t)
1> (ACL2_*1*_ACL2::FACT T)
2> (FACT T)
<2 (FACT 1)
<1 (ACL2_*1*_ACL2::FACT 1)
1
ACL2 >")
(GUARD-EVALUATION-EXAMPLES-SCRIPT
(GUARD)
"A script to show combinations of [defun-mode]s and [guard]-checking
Below is a script that illustrates the combination of [defun-mode]s
--- :[program] mode, :[logic] mode without [guard]s verified, and
:[logic] mode with [guard]s verified --- with values from
[set-guard-checking] --- t (the default), :all, :none, and nil. (It
does not illustrate the value :nowarn, which is the same as t
except for inhibiting a warning.) The script also illustrates cases
where the guard is not, or is, t.
See [guard-evaluation-examples-log] for result of running this
script. Before presenting the script below, we give some
instructions in case you want to run it yourself.
See [set-guard-checking] for discussion of the interaction between
[defun-mode]s and [guard]-checking that is illustrated by this
script. Also see [guard-evaluation-table] for a succinct table,
with associated discussion, that covers in detail the interactions
illustrated here.
The script mentions the running of ``Tracing Code''. The code is the
following sequence of commands.
(trace$ fact)
:set-guard-checking t
(fact 2)
(fact t)
:set-guard-checking :all
(fact 2)
(fact t)
:set-guard-checking :none
(fact 2)
(fact t)
:set-guard-checking nil
(fact 2)
(fact t)
If you want to run the script yourself, you may find it handy to use
the following Emacs keyboard macro for running the tracing code in
2-window mode, with the cursor in the window with the script and
ACL2 running in the other window.
(fset 'step-guard-script
[?C-a ?C- ?C-e ?M-w ?C-a ?C-n
?C-x ?o ?M-> ?C-y return ?C-x ?o])
; Put it on a key (if you have defined the indicated keymap by using
; emacs/emacs-acl2.el):
(define-key ctl-t-keymap \"r\" 'step-guard-script)
The script follows.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Program mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun fact (x)
(declare (xargs :guard (integerp x)
:mode :program))
(if (posp x)
(* x (fact (1- x)))
1))
; Run the Tracing Code here. It shows execution in raw Lisp in the t and nil
; cases of :set-guard-checking, but not in the :all or :none cases. We get a
; guard violation for argument t in the case :set-guard-checking t.
:u
(defun fact (x)
(declare (xargs :guard t
:mode :program))
(if (posp x)
(* x (fact (1- x)))
1))
; Run the Tracing Code here. It should give the same results as above,
; except that we no longer get a guard violation in the case
; :set-guard-checking t.
:u
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Logic mode, guard other than t
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun fact (x)
(declare (xargs :guard (integerp x)
:verify-guards nil
:mode :logic))
(if (posp x)
(* x (fact (1- x)))
1))
; Run the Tracing Code here. It should give guard violations for (fact t)
; with guard-checking set to t or :all. It should never run in raw Lisp,
; because we have not verified guards. In the t case, we can get a warning
; about avoiding the guard check on recursive calls, but only if we do not
; trace the function, fact.
(verify-guards fact)
; Run the Tracing Code here. The results should be as described just above,
; except that now we go into raw Lisp for (fact 2) with guard-checking other
; than :none.
:u
:u
; The following definition is the same as above, except that guards are
; verified.
(defun fact (x)
(declare (xargs :guard (integerp x)
:mode :logic))
(if (posp x)
(* x (fact (1- x)))
1))
; Run the Tracing Code here. We should get the same traces as in the
; immediately preceding case, since guards had been verified in both cases.
:u
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Logic mode, guard t
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun fact (x)
(declare (xargs :guard t
:verify-guards nil
:mode :logic))
(if (posp x)
(* x (fact (1- x)))
1))
; Run the Tracing Code here. We should never go in to raw Lisp, because
; guards have not been verified. We will see the same traces for (fact 2) as
; with the (integerp x) guard above with :verify-guards nil specified, except
; that even without tracing, there is no warning for :set-guard-checking t
; about recursive calls. And, there are no guard violations for (fact t), of
; course, since posp (necessarily, if we are to verify guards) has a guard of
; t.
(verify-guards fact)
; Run the Tracing Code here. You shouldn't see any surprises. Note however
; that if we back up to the start (using :u :u) and then define fact as just
; above but without :verify-guards nil, then the :none setting will allow us
; to go into raw Lisp: although :none generally avoids execution of raw Lisp
; counterparts, it allows this when the guard is T and guards have been
; verified.")
(GUARD-EVALUATION-TABLE
(GUARD)
"A table that shows combinations of [defun-mode]s and [guard]-checking
See [set-guard-checking] for an introduction to the topic discussed
here. Also see [guard] for a general discussion of guards, and see
[guard-evaluation-examples-script] for a script that illustrates
combinations presented below.
Note: The default setting for guard-checking (that is, the initial
value for (@ guard-checking-on)) is T.
The table below illustrates the interaction of the [defun-mode] with
the value supplied to [set-guard-checking]. The first row considers
functions defined in :[program] mode; the other two consider
functions defined in :[logic] mode. The columns correspond to four
values of state global 'guard-checking-on, as supplied to
[set-guard-checking]. (A fifth value, :nowarn, is similar to t but
suppresses warnings encountered with t (as explained in those
warning messages), and is not considered here.) During proofs,
[certify-book], and [include-book], 'guard-checking-on is set to
nil regardless of how this variable has been set in the top-level
loop (see the ``Essay on Guard Checking'' in source file
other-events.lisp if you are interested in a rationale).
Below this table, we make some comments about its entries, ordered by
row and then by column. For example, when we refer to ``b2'' we are
discussing the execution of a :[logic] mode function whose guards
have not been verified, after having executed :[set-guard-checking]
:all.
guard-checking-on: (1)t (2):all (3):none (4)nil
(a) :program a1 a2 a3 a4
(b) guards not verified b1 b2 b3 b4
(c) guards verified c1 c2 c3 c4
a1. Check the [guard] upon entry, then use the raw Lisp code if the
guard checks (else cause an error). This is a common setting when
one wants a little guard checking but also wants the efficiency of
raw Lisp. But note that you can get raw Lisp errors. For example,
if you make the definition (defun foo (x) (car x)) in :[program]
mode and execute :[set-guard-checking] t, and then execute (foo 3),
you will likely get an error from the call (car 3) made in raw
Lisp.
a2. For built-in (predefined) functions, see a1 instead. Otherwise:
Check the [guard], without exception. Thus, we never run the raw
Lisp code in this case. This can be useful when testing :[program]
mode functions, but you may want to run :[comp] t or at least
:[comp] :exec in this case, so that the execution is done using
compiled code.
a3. For built-in (predefined) functions, see a4 instead. Otherwise:
Do not check the [guard]. For :[program] mode functions, we never
run the raw Lisp code in this case; so if you care about
efficiency, see the comment in a2 above about :[comp]. This
combination is useful if you are using ACL2 as a programming
language and do not want to prove theorems about your functions or
suffer [guard] violations. In this case, you can forget about any
connection between ACL2 and Common Lisp.
a4. Run the raw Lisp code without checking [guard]s at all. Thus, for
:[program] mode functions, the nil setting is often preferable to
the :none setting because you get the efficiency of raw Lisp
execution. However, with nil you can therefore get hard Lisp errors
as in a1 above.
b1. Guards are checked at the top-level, though not at self-recursive
calls. We never run the raw Lisp code in this case; guards would
need to be verified first.
b2. Unlike the t setting, guards are checked even on self-recursive
calls. But like the t setting, we do not run the raw Lisp code. Use
this setting if you want guards checked on each recursive call in
spite of the cost of doing so.
b3, b4. Execution avoids the raw Lisp code and never checks guards.
The nil and :none settings behave the same in this case (i.e., for
:[logic] mode functions whose guards have not been verified),
except that recursive calls are never inlined for :none and tracing
(see [trace]) will show recursive calls for :none but not for nil.
c1, c2. Guards are checked. If the checks pass, evaluation takes
place using the raw Lisp code. If the checks fail, we get a guard
violation. Either way, we do not execute ``in the logic''; we only
execute using the raw Lisp code. Note that t and :all behave the
same in this case, (i.e. for :[logic] mode functions whose [guard]s
have been verified).
c3, c4. For the :none and nil settings, :[logic] mode functions whose
guards have been verified will never cause guard violations.
However, with nil and for built-in functions in :logic mode, guards
are still checked: if the check succeeds, then evaluation is done
using the raw Lisp code, and if not, it is done by the ``logic''
code, including self-recursive calls (though unlike the t case, we
will not see a warning about this). But with :none for user-defined
functions, no guard checking is done, and the only time the raw
Lisp code will be executed is when the guard is t and guards are
verified at the time the executable counterpart of the function is
defined (i.e., when the function is admitted unless it is later
defined again and compiled using :[comp]). Thus, if you use :none
and you want a function (foo x) with guard (g x) to execute using
raw Lisp code, you can write a ``wrapper''function with a guard of
t:
(defun foo-wrap (x)
(declare (xargs :guard t))
(if (g x)
(foo x)
'do-not-case))
If you want the speed of executing raw Lisp code and you have
non-trivial guards on functions that you want to call at the
top-level, use nil rather than :none.")
(GUARD-EXAMPLE
(TUTORIAL5-MISCELLANEOUS-EXAMPLES GUARD)
"A brief transcript illustrating [guard]s in ACL2
This note addresses the question: what is the use of [guard]s in
ACL2? Although we recommend that beginners try to avoid [guard]s
for a while, we hope that the summary here is reasonably
self-contained and will provide a reasonable introduction to guards
in ACL2. For a more systematic discussion, see [guard]. For a
summary of that topic, see [guard-quick-reference].
Before we get into the issue of [guard]s, let us note that there are
two important ``modes'':
[defun-mode] --- ``Does this [defun] add an axiom (`:logic mode') or
not (`:program mode')?'' (See [defun-mode].) Only :[logic] mode
functions can have their ``[guard]s verified'' via mechanized
proof; see [verify-guards].
[set-guard-checking] --- ``Should runtime [guard] violations signal
an error (:all, and usually with t or :nowarn) or go undetected
(nil, :none)? Equivalently, are expressions evaluated in Common
Lisp or in the logic?'' (See [set-guard-checking].)
Prompt examples
Here some examples of the relation between the ACL2 [prompt] and the
``modes'' discussed above. Also see [default-print-prompt]. The
first examples all have ld-skip-proofsp nil; that is, proofs are
not skipped.
ACL2 !> ; logic mode with guard checking on
ACL2 > ; logic mode with guard checking off
ACL2 p!> ; program mode with guard checking on
ACL2 p> ; program mode with guard checking off
Here are some examples with [default-defun-mode] of :[logic].
ACL2 > ; guard checking off, ld-skip-proofsp nil
ACL2 s> ; guard checking off, ld-skip-proofsp t
ACL2 !> ; guard checking on, ld-skip-proofsp nil
ACL2 !s> ; guard checking on, ld-skip-proofsp t
Sample session
ACL2 !>(+ 'abc 3)
ACL2 Error in TOP-LEVEL: The guard for the function symbol
BINARY-+, which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)),
is violated by the arguments in the call (+ 'ABC 3).
ACL2 !>:set-guard-checking nil
;;;; verbose output omitted here
ACL2 >(+ 'abc 3)
3
ACL2 >(< 'abc 3)
T
ACL2 >(< 3 'abc)
NIL
ACL2 >(< -3 'abc)
T
ACL2 >:set-guard-checking t
Turning guard checking on, value T.
ACL2 !>(defun sum-list (x)
(declare (xargs :guard (integer-listp x)
:verify-guards nil))
(cond ((endp x) 0)
(t (+ (car x) (sum-list (cdr x))))))
The admission of SUM-LIST is trivial, using the relation
O< (which is known to be well-founded on the domain
recognized by O-P) and the measure (ACL2-COUNT X).
We observe that the type of SUM-LIST is described by the
theorem (ACL2-NUMBERP (SUM-LIST X)). We used primitive type
reasoning.
Summary
Form: ( DEFUN SUM-LIST ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: None
Time: 0.03 seconds
(prove: 0.00, print: 0.00, proof tree: 0.00, other: 0.03)
SUM-LIST
ACL2 !>(sum-list '(1 2 3))
ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited
on recursive calls of the executable counterpart (i.e., in the ACL2
logic) of SUM-LIST. To check guards on all recursive calls:
(set-guard-checking :all)
To leave behavior unchanged except for inhibiting this message:
(set-guard-checking :nowarn)
6
ACL2 !>(sum-list '(1 2 abc 3))
ACL2 Error in TOP-LEVEL: The guard for the function symbol
BINARY-+, which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)),
is violated by the arguments in the call (+ 'ABC 3).
ACL2 !>:set-guard-checking nil
;;;; verbose output omitted here
ACL2 >(sum-list '(1 2 abc 3))
6
ACL2 >(defthm sum-list-append
(equal (sum-list (append a b))
(+ (sum-list a) (sum-list b))))
<< Starting proof tree logging >>
Name the formula above *1.
Perhaps we can prove *1 by induction. Three induction
schemes are suggested by this conjecture. Subsumption
reduces that number to two. However, one of these is flawed
and so we are left with one viable candidate.
...
That completes the proof of *1.
Q.E.D.
Guard verification vs. defun
Declare Form Guards Verified?
(declare (xargs :mode :program ...)) no
(declare (xargs :guard g)) yes
(declare (xargs :guard g :verify-guards nil)) no
(declare (xargs ...<no :guard>...)) no
ACL2 >:pe sum-list
l 8 (DEFUN SUM-LIST (X)
(DECLARE (XARGS :GUARD (INTEGER-LISTP X)
:VERIFY-GUARDS NIL))
(COND ((ENDP X) 0)
(T (+ (CAR X) (SUM-LIST (CDR X))))))
ACL2 >(verify-guards sum-list)
The non-trivial part of the guard conjecture for SUM-LIST,
given the :type-prescription rule SUM-LIST, is
Goal
(AND (IMPLIES (AND (INTEGER-LISTP X) (NOT (CONSP X)))
(EQUAL X NIL))
(IMPLIES (AND (INTEGER-LISTP X) (NOT (ENDP X)))
(INTEGER-LISTP (CDR X)))
(IMPLIES (AND (INTEGER-LISTP X) (NOT (ENDP X)))
(ACL2-NUMBERP (CAR X)))).
...
ACL2 >:pe sum-list
lv 8 (DEFUN SUM-LIST (X)
(DECLARE (XARGS :GUARD (INTEGER-LISTP X)
:VERIFY-GUARDS NIL))
ACL2 >:set-guard-checking t
Turning guard checking on, value T.
ACL2 !>(sum-list '(1 2 abc 3))
ACL2 Error in TOP-LEVEL: The guard for the function symbol
SUM-LIST, which is (INTEGER-LISTP X), is violated by the
arguments in the call (SUM-LIST '(1 2 ABC ...)). See :DOC trace for a useful
debugging utility. See :DOC set-guard-checking for information about
suppressing this check with (set-guard-checking :none), as recommended for
new users.
ACL2 !>:set-guard-checking nil
;;;; verbose output omitted here
ACL2 >(sum-list '(1 2 abc 3))
6
ACL2 >:comp sum-list
Compiling gazonk0.lsp.
End of Pass 1.
End of Pass 2.
Finished compiling gazonk0.lsp.
Loading gazonk0.o
start address -T 1bbf0b4 Finished loading gazonk0.o
Compiling gazonk0.lsp.
End of Pass 1.
End of Pass 2.
Finished compiling gazonk0.lsp.
Loading gazonk0.o
start address -T 1bc4408 Finished loading gazonk0.o
SUM-LIST
ACL2 >:q
Exiting the ACL2 read-eval-print loop.
ACL2>(trace sum-list)
(SUM-LIST)
ACL2>(lp)
ACL2 Version 1.8. Level 1. Cbd \"/slocal/src/acl2/v1-9/\".
Type :help for help.
ACL2 >(sum-list '(1 2 abc 3))
6
ACL2 >(sum-list '(1 2 3))
1> (SUM-LIST (1 2 3))>
2> (SUM-LIST (2 3))>
3> (SUM-LIST (3))>
4> (SUM-LIST NIL)>
<4 (SUM-LIST 0)>
<3 (SUM-LIST 3)>
<2 (SUM-LIST 5)>
<1 (SUM-LIST 6)>
6
ACL2 >:pe sum-list-append
9 (DEFTHM SUM-LIST-APPEND
(EQUAL (SUM-LIST (APPEND A B))
(+ (SUM-LIST A) (SUM-LIST B))))
ACL2 >(verify-guards sum-list-append)
The non-trivial part of the guard conjecture for
SUM-LIST-APPEND, given the :type-prescription rule SUM-LIST,
is
Goal
(AND (TRUE-LISTP A)
(INTEGER-LISTP (APPEND A B))
(INTEGER-LISTP A)
(INTEGER-LISTP B)).
...
****** FAILED ******* See :DOC failure ****** FAILED ******
ACL2 >(defthm common-lisp-sum-list-append
(if (and (integer-listp a)
(integer-listp b))
(equal (sum-list (append a b))
(+ (sum-list a) (sum-list b)))
t)
:rule-classes nil)
<< Starting proof tree logging >>
By the simple :rewrite rule SUM-LIST-APPEND we reduce the
conjecture to
Goal'
(IMPLIES (AND (INTEGER-LISTP A)
(INTEGER-LISTP B))
(EQUAL (+ (SUM-LIST A) (SUM-LIST B))
(+ (SUM-LIST A) (SUM-LIST B)))).
But we reduce the conjecture to T, by primitive type
reasoning.
Q.E.D.
;;;; summary omitted here
ACL2 >(verify-guards common-lisp-sum-list-append)
The non-trivial part of the guard conjecture for
COMMON-LISP-SUM-LIST-APPEND, given the :type-prescription
rule SUM-LIST, is
Goal
(AND (IMPLIES (AND (INTEGER-LISTP A)
(INTEGER-LISTP B))
(TRUE-LISTP A))
(IMPLIES (AND (INTEGER-LISTP A)
(INTEGER-LISTP B))
(INTEGER-LISTP (APPEND A B)))).
...
Q.E.D.
That completes the proof of the guard theorem for
COMMON-LISP-SUM-LIST-APPEND. COMMON-LISP-SUM-LIST-APPEND
is compliant with Common Lisp.
;;;; Summary omitted here.
ACL2 >(defthm foo (consp (mv x y)))
...
Q.E.D.
ACL2 >(verify-guards foo)
ACL2 Error in (VERIFY-GUARDS FOO): The number of values we
need to return is 1 but the number of values returned by the
call (MV X Y) is 2.
> (CONSP (MV X Y))
ACL2 Error in (VERIFY-GUARDS FOO): The guards for FOO cannot
be verified because the theorem has the wrong syntactic
form. See :DOC verify-guards.")
(GUARD-HINTS (POINTERS)
"See [xargs] for keyword :guard-hints.")
(GUARD-HOLDERS
(RULE-CLASSES TERM GUARD)
"Remove trivial calls from a [term]
For many [rule-classes], the process of converting terms to rules
includes the removal of certain trivial calls from the term. In all
such cases, the resulting term is provably equivalent to the input
term. A common example is to replace the term (prog2$ term1 term2)
by the term term2. But (prog2$ term1 term2) is really an
abbreviation for (i.e., macroexpands to) the term (return-last
'progn term1 term2); so a more accurate explanation, at the level
of proper ACL2 [term]s, is that the call of function [return-last]
is replaced by its last argument. ACL2 identifies certain such
transformations, from a term to a trivial simplification of it such
that the input and output are provably equal. We historically have
refered to the process of making such replacements as ``removing
guard holders.'' (For a discussion of the connection to guards, see
the ``Essay on the Removal of Guard Holders'' in the ACL2 sources.)
As of this writing, the process of removing guard-holders includes
the transformations below. That process is also applied to each
argument of a function call and to the bodies of [lambda]
expressions (see [term]).
(return-last term0 term1 term2) ==> term2
(mv-list term0 ... termk) ==> termk
; For replacing a term (the type term) by term:
((lambda (y) (the-check guard x y))
val) ==> val
Because of how [mbe] and [ec-call] are defined in terms of
[return-last], the expressions (mbe :logic l :exec e) and (ec-call
(f t1 ... tk)) are effective transformed by removing guard holders
into l and (f t1 ... tk), respectively.")
(GUARD-INTRODUCTION
(GUARD)
"Introduction to [guard]s in ACL2
Most users can probably profit by avoiding dealing with guards most
of the time. If they seem to get in the way, they can be ``turned
off'' using the command :[set-guard-checking] nil; for more about
this, see [set-guard-checking]. For more about guards in general,
see [guard].
The guard on a function symbol is a formula about the formals of the
function. To see the guard on a function, use the keyword command
:[args]. See [args]. To specify the guard on a function at
defun-time, use the :[guard] xarg (See [xargs]) or type
declarations (see [declare]). The latter may be preferable if you
want the host Lisp compiler to use this information.
Guards can be seen as having either of two roles: (a) they are a
specification device allowing you to characterize the kinds of
inputs a function ``should'' have, or (b) they are an efficiency
device allowing logically defined functions to be executed directly
in Common Lisp. Briefly: If the guards of a function definition are
``verified'' (see [verify-guards]), then the evaluation of a call
of that function on arguments satisfying its guard will have the
following property:
All subsequent function calls during that evaluation will be on
arguments satisfying the guard of the called function.
The consequence of this fact for (a) is that your specification
function is well-formed, in the sense that the values returned by
this function on appropriate arguments only depend on the
restrictions of the called functions to their intended domains. The
consequence of this fact for (b) is that in the ACL2 system, when a
function whose guards have been verified is called on arguments
that satisfy its guard, then the raw lisp function defined by this
function's [defun] event is used to evaluate the call. Note however
that even when the user-supplied [defun] is not used, ACL2 uses a
corresponding ``executable counterpart'' that generally performs,
we expect, nearly as well as the raw lisp function. See [comp] to
see how [compilation] can speed up both kinds of execution.
Let us turn next to the issue of the relationship between guards and
evaluation. See [guards-and-evaluation].")
(GUARD-MISCELLANY
(GUARD)
"Miscellaneous remarks about guards
The discussion of guards concludes here with a few miscellaneous
remarks. (Presumably you found this documentation by following a
link; see [guards-for-specification].) For further information
related to guards other than what you find under ``[guard],'' see
any of the following documentation topics: [guard-example],
[set-verify-guards-eagerness], [set-guard-checking],
[verify-guards], and (for a discussion of keyword :split-types)
[xargs].
[Defun] can be made to try to verify the guards on a function. This
is controlled by the ``[defun-mode]'' of the [defun]; see
[defun-mode]. The [defun-mode] is either as specified with the
:mode xarg of the [defun] or else defaults to the default
[defun-mode]. See [default-defun-mode]. If the [defun-mode] of the
[defun] is :[logic] and either a [guard] is specified explicitly or
:[verify-guards] t is specified in the [xargs], then we attempt to
verify the guards of the function. Otherwise we do not. (But see
[set-verify-guards-eagerness] for how to modify this behavior.)
It is sometimes impossible for the system to verify the guards of a
recursive function at definition time. For example, the guard
conjectures might require the invention and proof of some
inductively derived property of the function (as often happens when
the value of a recursive call is fed to a guarded subroutine). So
sometimes it is necessary to define the function using
:verify-guards nil then to state and prove key theorems about the
function, and only then have the system attempt guard verification.
Post-[defun] guard verification is achieved via the event
[verify-guards]. See [verify-guards].
It should be emphasized that guard verification affects only two
things: how fast ACL2 can evaluate the function and whether the
function is executed correctly by raw Common Lisp, without guard
violations. Since ACL2 does not use the raw Common Lisp definition
of a function to evaluate its calls unless that function's guards
have been verified, the latter effect is felt only if you run
functions in raw Common Lisp rather than via ACL2's command loop.
Guard verification does not otherwise affect the theorem prover or
the semantics of a definition. If you are not planning on running
your function on ``big'' inputs and you don't care if your function
runs correctly in raw Common Lisp (e.g., you have formalized some
abstract mathematical property and just happened to use ACL2 as
your language), there is no need to suffer through guard
verification. Often users start by not doing guard verification and
address that problem later. Sometimes you are driven to it, even in
mathematical projects, because you find that you want to run your
functions particularly fast or in raw Common Lisp.
If [certify-book] is used to compile a file, and the file contains
functions with unverified guard conjectures, then you will be
warned that the compiled file cannot be loaded into raw Common Lisp
with the expectation that the functions will run correctly. This is
just the same point we have been making: ACL2 and Common Lisp agree
only on the restricted domains specified by our guards. When guards
are violated, Common Lisp can do anything. When you call a compiled
function on arguments violating its guards, the chances are only
increased that Common Lisp will go berserk, because compiled
functions generally check fewer things at runtime and tend to be
more fragile than interpreted ones.
Finally, we note that ACL2 collects up [guard]s from [declare] forms
in order of appearance. So for example, the [declare] form
(declare (xargs :guard (foo x))
(type string x)
will generate the guard (and (foo x) (stringp x)), while the form
(declare (type string x)
(xargs :guard (foo x))
will generate the guard (and (stringp x) (foo x)). The only exception
to this rule is the case that :guard and :stobjs are both specified
in which case all :stobjs declarations will be treated as through
they precede all :guard and type declarations.")
(GUARD-MSG-TABLE (POINTERS)
"See [set-guard-msg].")
(GUARD-OBLIGATION
(GUARD)
"The guard proof obligation
See [verify-guards], and see [guard] for a discussion of guards. Also
see [verify-guards-formula] for a utility provided for viewing the
guard proof obligation, without proof. Guard-obligation is a lower
level function for use in system programs, not typically
appropriate for most ACL2 users. If you simply want to see the
guard proof obligations, see [verify-guards-formula]. Also see
[lemma-instance] for a discussion of a utility, guard-theorem, that
provides an unsimplified version of the guard proof obligation, and
see [gthm] for a corresponding user-level utility.
Example Form:
(guard-obligation 'foo nil 'top-level state)
(guard-obligation '(if (consp x) (foo (car x)) t) nil 'my-function state)
General Forms:
(guard-obligation name guard-debug ctx state)
(guard-obligation term guard-debug ctx state)
where the first argument is either the name of a function or theorem
or is a non-variable term that may be in untranslated form;
guard-debug is typically nil but may be t (see [guard-debug]); ctx
is a context (typically, a symbol used in error and warning
messages); and [state] references the ACL2 [state].
If you want to obtain the formula but you don't care about the
so-called ``tag tree'':
(mv-let (erp val state)
(guard-obligation x guard-debug 'top-level state)
(if erp
( .. code for handling error case, e.g., name is undefined .. )
(let ((cl-set (cadr val))) ; to be proved for guard verification
( .. code using cl-set, which is a list of clauses,
implicitly conjoined, each of which is viewed as
a disjunction .. ))))
The form (guard-obligation x guard-debug ctx state) evaluates to a
triple (mv erp val state), where erp is nil unless there is an
error, and [state] is the ACL2 state. Suppose erp is nil. Then val
is the keyword :redundant if the corresponding [verify-guards]
event would be redundant; see [redundant-events]. Otherwise, val is
a tuple (list* names cl-set ttree), where: names is (cons :term xt)
if x is not a variable, where xt is the translated form of x; and
otherwise is a list containing x along with, if x is defined in a
mutual-recursion, any other functions defined in the same
[mutual-recursion] nest; cl-set is a list of lists of terms, viewed
as a conjunction of clauses (each viewed (as a disjunction); and
ttree is an assumption-free tag-tree that justifies cl-set. (The
notion of ``tag-tree'' may probably be ignored except for system
developers.)
Guard-obligation is typically used for function names or non-variable
terms, but as for [verify-guards], it may also be applied to
theorem names.
See the source code for [verify-guards-formula] for an example of how
to use guard-obligation.")
(GUARD-QUICK-REFERENCE
(GUARD)
"Brief summary of guard checking and guard verification
For a careful introduction to guards, see [guard].
I. GUARD CHECKING DURING EXECUTION
Effect
Guards on definitions are checked at execution time (except for
guards on subsidiary calls of recursive or mutually recursive
functions).
When does it happen
By default, guards are checked for all forms submitted at the top
level.
To disable
:set-guard-checking nil ; skip raw Lisp if there is a guard
violation :set-guard-checking :none ; skip guard checking entirely
To (re-)enable
:set-guard-checking t
See [set-guard-checking] for more options.
II. GUARD VERIFICATION
Effect
A proof is attempted of the obligations arising from the guards of
subsidiary functions in a [defun], [defthm], or [defaxiom] event.
In the case of a defun, the guard itself is also verified (under an
implicit guard of t).
When does it happen
Only names of defined functions, [defthm]s, and [defaxiom]s are
subject to guard verification. Guard verification may occur when
functions are defined (using [defun]), but it requires an explicit
call of [verify-guards] in order to verify guards for [defthm]s and
[defaxiom]s. Constrained functions (see [encapsulate]) may not have
their guards verified.
(verify-guards foo ...)
causes guard verification for the [defun], [defthm], or [defaxiom]
named by foo, if it has not already been successfully done. The
default [defun-mode] (see [default-defun-mode]) must be :[logic],
or else this event is ignored.
(defun foo ...)
causes guard verification of foo if and only if the following two
conditions are both met. First, foo is processed in :[logic] mode
(either by setting mode :[logic] globally, or by including :mode
:logic in the [xargs] declaration). Second, at least one of the
following sub-conditions is met. Also see [xargs], and see
[set-verify-guards-eagerness] for how to change this behavior.
1. The [xargs] declaration specifies a :[guard].
2. There is at least one type declaration (see [declare]).
3. The [xargs] declaration specifies :[stobj]s.
4. The [xargs] declaration specifies :[verify-guards] t.
(verify-termination foo ...)
causes guard verification of foo if foo is a function currently
defined in :[program] mode and the criteria for guard verification
of a [defun] form are met, as discussed above. The default
[defun-mode] (see [default-defun-mode]) must be :[logic], or else
this event is ignored.")
(GUARD-THEOREM
(LEMMA-INSTANCE GUARD HINTS)
"Use a previously-proved [guard] theorem
See [lemma-instance] for a discussion of :guard-theorem lemma
instances, and see [gthm] for a related user-level query utility.
Also see [guard-theorem-example] for a simple example of the use of
a [guard] theorem in [hints].")
(GUARD-THEOREM-EXAMPLE
(LEMMA-INSTANCE GUARD HINTS)
"How to use a previously-proved [guard] theorem
See [lemma-instance] for a discussion of :guard-theorem lemma
instances, and see [gthm] for a related user-level query utility.
In this topic, we illustrate the use of such lemma instances to
take advantage of a [guard] theorem already proved for an existing
definition, when attempting to admit a new definition.
The following example is contrived but should get the idea across.
Suppose that the event displayed just below was previously
executed, for example when including a book. The [mbe] call
generates a guard proof obligation, but there is only one thing to
know about that for this example: without the local lemma shown,
the guard proof fails for f1.
(encapsulate
()
(local (defthm append-revappend
(equal (append (revappend x y) z)
(revappend x (append y z)))))
(defun f1 (x y)
(declare (xargs :guard (and (true-listp x)
(true-listp y))))
(mbe :logic (append (reverse x) y)
:exec (revappend x y))))
Now suppose that later, we wish to admit a function with the same
guard and body. Since the lemma append-revappend above is [local],
guard verification will likely fail. However, we can tell the
prover to use the guard theorem already proved for f1, as follows;
then the guard verification proof succeeds.
(defun f2 (x y)
(declare (xargs :guard (and (true-listp x)
(true-listp y))
:guard-hints ((\"Goal\" :use ((:guard-theorem f1))))))
(mbe :logic (append (reverse x) y)
:exec (revappend x y)))
See [termination-theorem-example] for an example use of the analogous
lemma instance type, :termination-theorem. That topic also includes
discussion of the use of event names in prover output.")
(GUARDS (POINTERS) "See [guard].")
(GUARDS-AND-EVALUATION
(GUARD)
"The relationship between guards and evaluation
The guard has no effect on the logical axiom added by the definition
of a function. It does, however, have consequences for how calls of
that function are evaluated in ACL2. We begin by explaining those
consequences, when ACL2 is in its default ``mode,'' i.e., as
originally brought up. In subsequent discussion we'll consider
other ways that guards can interact with evaluation.
For more about guards in general, see [guard]. For in-depth
discussion of the interaction between the [defun-mode] and guard
checking, see [set-guard-checking], see [guard-evaluation-table],
see [guard-evaluation-examples-script], and see
[guard-evaluation-examples-log]. Also see [generalized-booleans]
for discussion about a subtle issue in the evaluation of certain
Common Lisp functions.
Guards and evaluation I: the default
Consider the following very simple definition.
(defun foo (x) (cons 1 (cdr x)))
First consider how raw Common Lisp behaves when evaluating calls of
this function. To evaluate (foo x) for some expression x, first x
is evaluated to some value v, and then (cons 1 (cdr x)) is
evaluated with x bound to v. For example, if v is (cons 'a 3), then
Common Lisp computes (cons 1 3). But if (for example) v is a
number, e.g., 7, then there is no way to predict what Common Lisp
might do. Some implementations would cause ``sensible'' errors,
others might return nonsense, still others might crash the host
machine. The results tend toward the catastrophic if the call of
foo in question is in compiled code.
Now by default, ACL2 evaluates calls of foo exactly as Common Lisp
does, except that it uses guards to check the ``legality'' of each
function call. So for example, since (cdr x) has a guard of (or
(consp x) (equal x nil)), the call (foo 7) would cause a ``guard
violation,'' as illustrated below.
ACL2 !>(foo 7)
ACL2 Error in TOP-LEVEL: The guard for the function symbol CDR, which
is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
call (CDR 7).
ACL2 !>
Thus, the relation between evaluation in ACL2 and evaluation in
Common Lisp is that the two produce the very same results, provided
there is no guard violation.
Guards and evaluation II: :[set-guard-checking].
The ACL2 logic is a logic of total functions. That is, every
application of a function defined has a completely specified
result. See the [documentation] for each individual primitive for
the specification of what it returns when its guard is violated;
for example, see [cdr].
The presence of guards thus introduces a choice in the sense of
evaluation. When you type a form for evaluation do you mean for
guards to be checked or not? Put another way, do you mean for the
form to be evaluated in Common Lisp (if possible) or in the ACL2
logic? Note: If Common Lisp delivers an answer, it will be the same
as in the logic, but it might be erroneous to execute the form in
Common Lisp. For example, the ACL2 logic definition of [cdr]
implies that the [cdr] of an [atom] is nil; see [cdr]. So: should
(cdr 7) cause a guard violation error or return nil?
The top-level ACL2 loop has a variable which controls which sense of
execution is provided. By default, ``guard checking'' is on, by
which we mean that guards are checked at runtime, in the sense
already described. To allow execution to proceed in the logic when
there is a guard violation, do :[set-guard-checking] nil; or
evaluate :[set-guard-checking] :none to skip guard checking
entirely. To turn ``guard checking'' back on, execute the top-level
form :[set-guard-checking] t. The status of guard checking
reflected in the [prompt]; guard-checking is ``on'' when the
[prompt] contains an exclamation mark (also see
[default-print-prompt]). For example,
ACL2 !>
means guard checking is on and
ACL2 >
means guard checking is off. The exclamation mark can be thought of
as ``barring'' certain computations. The absence of the mark
suggests the absence of error messages or unbarred access to the
logical axioms. Thus, for example
ACL2 !>(car 'abc)
will signal an error, while
ACL2 >(car 'abc)
will return nil. To return to our previous example: with guard
checking off, (foo 7) evaluates to (cons 1 nil). Also see
[set-guard-checking].
Guards and evaluation III: guard verification
Consider the defininition of foo given above, but modified so that a
reasonable guard of (consp x) is specified, as shown below.
(defun foo (x)
(declare (xargs :guard (consp x)))
(cons 1 (cdr x)))
We say ``reasonable guard'' above because if x is such that (consp x)
holds, then the call of [cdr] in the evaluation of (foo x) will not
cause a guard violation. Thus, it ``should'' be legal to evaluate
(foo x), for any such x, simply by evaluating this form in raw
Common Lisp.
The [verify-guards] event has been provided for this purpose. Details
may be found elsewhere; see [verify-guards]. Briefly, for any
defined function fn, the event (verify-guards fn) attempts to check
the condition discussed above, that whenever fn is called on
arguments that satisfy its guard, the evaluation of this call will
proceed without any guard violation. (Moreover, the guard itself
should be evaluable without any guard violation.) If this check is
successful, then future calls of this sort will be evaluated in raw
Common Lisp.
Returning to our example above, the (verify-guards foo) will succeed
because the guard (consp x) of foo implies the guard generated from
the call (cdr x) in the body of the definition, namely, (or (consp
x) (equal x nil)) (see [cdr]). Then the evaluation of (foo (cons 'a
3)) will take place in raw Common Lisp, because (cons 'a 3)
satisfies the guard of foo.
This ability to dive into raw Common Lisp hinges on the proof that
the guards you attach to your own functions are sufficient to
ensure that the guards encountered in the body are satisfied. This
is called ``guard verification.'' Once a function has had its
guards verified, then ACL2 can evaluate the function somewhat
faster (but see ``Guards and evaluation V: efficiency issues''
below). Perhaps more importantly, ACL2 can also guarantee that the
function will be evaluated correctly by any implementation of
Common Lisp (provided the guard of the function is satisfied on the
input). That is, if you have verified the guards of a system of
functions and you have determined that they work as you wish in
your host ACL2 (perhaps by proving it, perhaps by testing), then
they will work identically in any Common Lisp.
There is a subtlety to our treatment of evaluation of calls of
functions whose guards have been verified. If the function's guard
is not satisfied by such a call, then no further attempt is made to
evaluate any call of that function in raw lisp during the course of
evaluation of that call. This is obvious if guard checking is on,
because an error is signalled the first time its guard is violated;
but in fact it is also true when guard checking is off. See
[guard-example] for an example.
Guards and evaluation IV: functions having :program mode
Strictly speaking, functions in :[program] mode (see [defun-mode]) do
not have definitions in the ACL2 logic. So what does it mean to
evaluate calls of such functions in ACL2? In general we treat
:[program] functions much as we treat :[logic] functions whose
guards have been verified, except that when no error occurs then
the corresponding raw Lisp function is always called. (We say ``in
general'' because there are exceptions, discussed in the ``Aside''
just below.) Note that when the guard of a function in :[logic]
mode is violated, there is still a value that the ACL2 logic proves
is equal to the given call. But the same cannot be said for a
function in :[program] mode. Nevertheless, for the sake of
convenience we go ahead and evaluate the corresponding raw Lisp
function except in the situation where the guard is violated and
guard-checking is on, aside from the following:
Aside. There are exceptions to the use of raw Lisp, discussed just
above, to evaluate calls of :[program] mode functions. The primary
one is that after :[set-guard-checking] :none, evaluation of
user-defined :[program] mode function calls is done in the ACL2
logic, not in raw Lisp. The more obscure exception is that during
expansion of macros and [make-event] forms, and during evaluation
of [defconst] forms, ACL2 enters a ``safe mode'' in which this
escape to raw Lisp is prevented. The following example illustrates
how the user can experiment directly with safe mode, though it is
preferred to use :[set-guard-checking] :none if you are happy to
skip all guard checking and evaluate forms in the logic.
ACL2 !>(defun foo (x)
(declare (xargs :mode :program :guard t))
(car x))
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO
ACL2 !>(foo 3)
Error: Attempt to take the car of 3 which is not listp.
[condition type: SIMPLE-ERROR]
Restart actions (select using :continue):
0: Return to Top Level (an \"abort\" restart).
1: Abort entirely from this process.
[1] ACL2(2): :pop
ACL2 !>(assign safe-mode t)
T
ACL2 !>(foo 3)
ACL2 Error in TOP-LEVEL: The guard for the function symbol CAR, which
is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
call (CAR 3). See :DOC trace for a useful debugging utility. See
:DOC set-guard-checking for information about suppressing this check
with (set-guard-checking :none), as recommended for new users.
ACL2 !>(assign safe-mode nil)
NIL
ACL2 !>(foo 3)
Error: Attempt to take the car of 3 which is not listp.
[condition type: SIMPLE-ERROR]
Restart actions (select using :continue):
0: Return to Top Level (an \"abort\" restart).
1: Abort entirely from this process.
[1] ACL2(2):
The other exception occurs after [set-guard-checking] can be called
with a value of :all; see [set-guard-checking]. End of aside.
Thus, as with :[logic] functions: when a guard has been satisfied on
a call of a function with :[program] mode, no subsidiary guard
checking will be done.
Notice that by treating functions in :[program] mode like functions
whose guards have been verified, we are using raw lisp to compute
their values when their guards are met. We do not check guards any
further once raw lisp is invoked. This can lead to hard lisp errors
if the guards are not appropriate, as illustrated below.
ACL2 >:program
ACL2 p>(defun foo (x)
(declare (xargs :guard t))
(cons 1 (cdr x)))
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.02 seconds (prove: 0.00, print: 0.00, proof tree: 0.00, other: 0.02)
FOO
ACL2 p>(foo 3)
Error: 3 is not of type LIST.
Fast links are on: do (use-fast-links nil) for debugging
Error signalled by CDR.
Broken at COND. Type :H for Help.
ACL2>>
See [defun-mode-caveat].
However, here is a way to get ACL2 to do run-time guard checking for
user-defined :[program] mode functions. With this method, ACL2 will
evaluate calls of user-defined :program mode functions in a manner
that follows their ACL2 definitions. Simply execute the following
in the ACL2 loop to put ACL2 into a ``safe mode.''
(f-put-global 'safe-mode t state)
Let us revisit the example above, using safe mode. Notice that the
guard of [cdr] is now being checked, because the executable
counterpart of foo is being called even though the [guard] is t.
ACL2 !>(f-put-global 'safe-mode t state)
<state>
ACL2 !>:program
ACL2 p!>(defun foo (x)
(declare (xargs :guard t))
(cons 1 (cdr x)))
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO
ACL2 p!>(foo 3)
ACL2 Error in TOP-LEVEL: The guard for the function symbol CDR, which
is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
call (CDR 3). See :DOC trace for a useful debugging utility. See
:DOC set-guard-checking for information about suppressing this check
with (set-guard-checking :none), as recommended for new users.
ACL2 p!>
If we go back into ``unsafe'' mode, then we once again see a raw Lisp
error, as we now illustrate.
ACL2 p!>(f-put-global 'safe-mode nil state)
<state>
ACL2 p!>(foo 3)
Error: 3 is not of type LIST.
Fast links are on: do (si::use-fast-links nil) for debugging
Error signalled by CDR.
Broken at COND. Type :H for Help.
ACL2>>
Guards and evaluation V: efficiency issues
We have seen that by verifying the guards for a :[logic] function, we
arrange that raw lisp is used for evaluation of calls of such
functions when the arguments satisfy its guard.
This has several apparent advantages over the checking of guards as
we go. First, the savings is magnified as your system of functions
gets deeper: the guard is checked upon the top-level entry to your
system and then raw Common Lisp does all the computing. Second, if
the raw Common Lisp is compiled (see [compilation]), enormous
speed-ups are possible. Third, if your Common Lisp or its compiler
does such optimizations as tail-recursion removal, raw Common Lisp
may be able to compute your functions on input much ``bigger'' than
ACL2 can.
The first of these advantages is quite important if you have
complicated guards. However, the other two advantages are probably
not very important, as we now explain.
When a function is defined in :[logic] mode, its [defun] is executed
in raw Common Lisp. (We might call this the ``primary'' raw lisp
definition of the function.) However, a corresponding ``logic
definition'' is also executed. The ``logic definition'' is a
[defun] in raw lisp that checks guards at runtime and escapes to
the primary raw lisp definition if the guard holds of the arguments
and the function has already had its guards verified. Otherwise the
logic definition executes the body of the function by calling the
logic definitions of each subroutine. Now it is true that
[compilation] generally speeds up execution enormously. However,
the :[comp] command (see [comp]) compiles both of the raw lisp
definitions associated with a :[logic] function. Also, we have
attempted to arrange that for every tail recursion removal done on
the actual [defun], a corresponding tail recursion removal is done
on the ``logic definition.''
We believe that in most cases, the logic definition executes almost
as fast as the primary raw lisp definition, at least if the
evaluation of the guards is fast. So, the main advantage of guard
verification is probably that it lets you know that the function
may be executed safely in raw lisp, returning the value predicted
by the ACL2 logic, whenever its arguments satisfy its guard. We
envision the development of systems of applicative lisp functions
that have been developed and reasoned about using ACL2 but which
are intended for evaluation in raw Common Lisp (perhaps with only a
small ``core'' of ACL2 loaded), so this advantage of guard
verification is important.
Nevertheless, guard verification might be important for optimal
efficiency when the functions make use of type declarations. For
example, at this writing, the GCL implementation of Common Lisp can
often take great advantage of [declare] forms that assign small
integer types to formal parameters. Note that while type
declarations contributed to the guard by default, they can be
proved from the guard instead; see [xargs] for a discussion of the
:split-types keyword.
To continue the discussion of guards, see [guards-for-specification]
to read about the use of guards as a specification device.")
(GUARDS-FOR-SPECIFICATION
(GUARD)
"Guards as a specification device
A use of guard verification that has nothing to do with efficiency is
as a way to gain confidence in specifications. This use has the
feel of ``types'' in many traditional [programming] languages,
though guards allow much greater expressiveness than most systems
of types (and unfortunately, as a result they are not syntactically
checkable).
For more discussion of guards in general, see [guard].
Suppose you have written a collection of function definitions that
are intended to specify the behavior of some system. Perhaps
certain functions are only intended to be called on certain sorts
of inputs, so you attach guards to those functions in order to
``enforce'' that requirement. And then, you verify the guards for
all those functions.
Then what have you gained, other than somewhat increased efficiency
of execution (as explained above), which quite possibly isn't your
main concern? You have gained the confidence that when evaluating
any call of a (specification) function whose arguments satisfy that
function's guard, all subsequent function calls during the course
of evaluation will have this same property, that the arguments
satisfy the guard of the calling function.
The rest of this topic addresses those who wish to understand
[guard]s from a proof-theoretic perspective instead of (or in
addition to) the evaluation perspective given above. In logical
terms, we can say that the equality of the original call with the
returned value is provable from weakened versions of the
definitions, where each definitional axiom is replaced by an
implication whose antecedent is the requirement that the arguments
satisfy the guard and whose consequent is the original axiom. For
example,
(defun foo (x)
(declare (xargs :guard (consp x)))
(cons 1 (cdr x)))
originally generates the axiom
(equal (foo x)
(cons 1 (cdr x)))
but in fact, when evaluation involves no guard violation then the
following weaker axiom suffices in the justification of the
evaluation.
(implies (consp x)
(equal (foo x)
(cons 1 (cdr x))))
So for example, suppose we evaluate (foo '(a b c)) and get '(1 b c).
Then of course the equality of these two terms is provable from the
original axiom. The point here is that it's even provable from the
weaker axiom.
If you are following links to read this documentation as a hypertext
style document, then please see [guard-miscellany]. This concludes
our discussion of guards with miscellaneous remarks, and also
contains pointers to related topics.")
(GUARDS_IN_ACL2
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Guards
Common Lisp functions are partial; they are not defined for all
possible inputs. But ACL2 functions are total. Roughly speaking,
the logical function of a given name in ACL2 is a completion of the
Common Lisp function of the same name obtained by adding some
arbitrary but ``natural'' values on arguments outside the
``intended domain'' of the Common Lisp function.
ACL2 requires that every ACL2 function symbol have a ``guard,'' which
may be thought of as a predicate on the formals of the function
describing the intended domain. The guard on the primitive function
[car] [{ICON}], for example, is (or (consp x) (equal x nil)), which
requires the argument to be either an ordered pair or nil. We will
discuss later how to specify a guard for a defined function; when
one is not specified, the guard is t which is just to say all
arguments are allowed.
But guards are entirely extra-logical: they are not involved in the
axioms defining functions. If you put a guard on a defined
function, the defining axiom added to the logic defines the
function on all arguments, not just on the guarded domain.
So what is the purpose of guards?
The key to the utility of guards is that we provide a mechanism,
called ``guard verification,'' for checking that all the guards in
a formula are true. See [verify-guards]. This mechanism will
attempt to prove that all the guards encountered in the evaluation
of a guarded function are true every time they are encountered.
For a thorough discussion of guards, see the paper [km97] in the ACL2
[bibliography].")
(GUESSING_THE_TYPE_OF_A_NEWLY_ADMITTED_FUNCTION
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Guessing the Type of a Newly Admitted Function
When a function is admitted to the logic, ACL2 tries to ``guess''
what type of object it returns. This guess is codified as a term
that expresses a property of the value of the function. For app the
term is
(OR (CONSP (APP X Y))
(EQUAL (APP X Y) Y))
which says that app returns either a cons or its second argument.
This formula is added to ACL2's rule base as a [type-prescription]
[{ICON}] rule. Later we will discuss how rules are used by the ACL2
theorem prover. The point here is just that when you add a
definition, the database of rules is updated, not just by the
addition of the definitional axiom, but by several new rules.
You should now return to [the Walking Tour].")
(GUIDING_THE_ACL2_THEOREM_PROVER
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Guiding the ACL2 Theorem Prover
[{IMAGE}]
Now that you have seen the theorem prover in action you might be
curious as to how you guide it.
{IMAGE}
Look at the picture above. It is meant to suggest that Q is an
important lemma needed for the proof of P. Note that to lead the
prover to the proof of P the user first proves Q. In a way, the
formulation and proof of Q is a hint to the prover about how to
prove P.
The user usually doesn't think of Q or recognize the need to prove it
separately until he or she sees the theorem prover fail to prove P
without it ``knowing'' Q.
The way the user typically discovers the need for Q is to look at
failed proofs.
[{IMAGE}]")
(HANDS-OFF (POINTERS)
"See [hints] for keyword :hands-off.")
(HARD-ERROR
(ERRORS ACL2-BUILT-INS)
"Print an error message and stop execution
(Hard-error ctx str alist) causes evaluation to halt with a short
message using the ``context'' ctx. An error message is first
printed using the string str and alist alist that are of the same
kind as expected by [fmt]. See [fmt]. Also see [er] for a macro
that provides a unified way of signaling errors.
Hard-error has a guard of t. Also see [illegal] for a similar
capability which however has a guard of nil that supports static
checking using [guard] verification, rather than using dynamic
(run-time) checking. This distinction is illustrated elsewhere: see
[prog2$] for examples.
Semantically, hard-error ignores its arguments and always returns
nil. But if a call (hard-error ctx str alist) is encountered during
evaluation, then the string str is printed using the association
list alist (as in [fmt]), after which evaluation halts immediately.
Here is a trivial, contrived example.
ACL2 !>(cons 3 (hard-error 'my-context
\"Printing 4: ~n0\"
(list (cons #\\0 4))))
HARD ACL2 ERROR in MY-CONTEXT: Printing 4: four
ACL2 Error in TOP-LEVEL: Evaluation aborted.
ACL2 !>
Technical note for raw Lisp programmers only. It is possible to cause
hard errors to signal actual raw Lisp errors, simply by evaluating
the following form in raw Lisp: (setq *hard-error-is-error* t).
Indeed, any non-nil value for *hard-error-is-error* will cause
hard-error or [illegal] --- or indeed (er hard ...), (er hard!
...), or (er hard? ...) --- to produce a Lisp error whose
condition, when printed with format directive ~a, is the same error
message that ACL2 would otherwise print. Below is a sample log,
closely based on an example provided by Jared Davis.
ACL2 !>(defun f (x)
(er hard 'f \"F got bad input ~x0.~%\" x))
Since F is non-recursive, its admission is trivial. We observe that
the type of F is described by the theorem (EQUAL (F X) NIL). We used
the :type-prescription rule ILLEGAL.
Summary
Form: ( DEFUN F ...)
Rules: ((:TYPE-PRESCRIPTION ILLEGAL))
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
F
ACL2 !>:q
Exiting the ACL2 read-eval-print loop. To re-enter, execute (LP).
? (defun run-f ()
(let ((*hard-error-is-error* t))
(handler-case
(f 3)
(error (condition)
(format t \"Got the following error: ~a~%\" condition)))))
RUN-F
? (run-f)
Got the following error: HARD ACL2 ERROR in F: F got bad input 3.
NIL
?
Function: <hard-error>
(defun hard-error (ctx str alist)
(declare (xargs :guard t))
(declare (ignore ctx str alist))
nil)")
(HEADER
(ARRAYS ACL2-BUILT-INS)
"Return the header of a 1- or 2-dimensional array
Example Form:
(header 'delta1 a)
General Form:
(header name alist)
where name is arbitrary and alist is a 1- or 2-dimensional array.
This function returns the header of the array alist. The function
operates in virtually constant time if alist is the semantic value
of name. See [arrays].
Function: <header>
(defun
header (name l)
(declare (xargs :guard (or (array1p name l) (array2p name l))))
(prog2$ name (assoc-eq :header l)))")
(HEY_WAIT!__IS_ACL2_TYPED_OR_UNTYPED{Q}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Hey Wait! Is ACL2 Typed or Untyped?
The example
ACL2 !>(app 7 27)
ACL2 Error in TOP-LEVEL: The guard for the function symbol ENDP, which
is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
call (ENDP 7).
illustrates the fact that while ACL2 is an untyped language the ACL2
evaluator can be configured so as to check ``types'' at runtime. We
should not say ``types'' here but ``guards.'' Click [here] for a
discussion of guards.
The guard on [endp] [{ICON}] requires its argument to be a true list.
Since 7 is not a true list, and since ACL2 is checking guards in
this example, an error is signaled by ACL2. How do you know ACL2 is
checking guards? Because the prompt tells us (click [here]) with
its ``!''.")
(HIDDEN-DEATH-PACKAGE
(PACKAGES DEFPKG)
"Handling [defpkg] [events] that are [local]
This documentation topic explains a little bit about certain errors
users may see when attempting to evaluate a [defpkg] event. In
brief, if you see an error that refers you to this topic, you are
probably trying to admit a [defpkg] event, and you should change
the name of the package to be introduced by that event.
Recall that defpkg events introduce axioms, for example as follows.
ACL2 !>(defpkg \"PKG0\" '(a b))
Summary
Form: ( DEFPKG \"PKG0\" ...)
Rules: NIL
Warnings: None
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
\"PKG0\"
ACL2 !>:pr! \"PKG0\"
Rune: (:REWRITE PKG0-PACKAGE)
Status: Enabled
Lhs: (SYMBOL-PACKAGE-NAME (INTERN-IN-PACKAGE-OF-SYMBOL X Y))
Rhs: \"PKG0\"
Hyps: (AND (STRINGP X)
(NOT (MEMBER-SYMBOL-NAME X '(A B)))
(SYMBOLP Y)
(EQUAL (SYMBOL-PACKAGE-NAME Y) \"PKG0\"))
Equiv: EQUAL
Backchain-limit-lst: NIL
Subclass: BACKCHAIN
Loop-stopper: NIL
ACL2 !>
Now, a [defpkg] event may be executed underneath an [encapsulate] or
[include-book] form that is marked [local]. In that case, traces of
the added axiom will disappear after the surrounding [encapsulate]
or [include-book] form is admitted. This can cause inconsistencies.
(You can take our word for it, or you can look at the example shown
in the ``Essay on Hidden Packages'' in source file axioms.lisp.)
In order to prevent unsoundness, then, ACL2 maintains the following
invariant. Let us say that a defpkg event is ``hidden'' if it is in
support of the current logical [world] but is not present in that
world as an event, because it is [local] as indicated above. We
maintain the invariant that all [defpkg] [events], even if
``hidden'', are tracked under-the-hood in the current logical
[world]. Sometimes this property causes [defpkg] events to be
written to the [portcullis] of a book's [certificate] (see
[books]). At any rate, if you then try to define the package in a
manner inconsistent with the earlier such definition, that is, with
a different imports list, you will see an error because of the
above-mentioned tracking.
(By the way, this topic's name comes from Holly Bell, who heard
\"hidden death package\" instead of \"hidden defpkg\". The description
seemed to fit. Thanks, Holly!)")
(HIDDEN-DEFPKG
(PACKAGES DEFPKG)
"Handling defpkg events that are local
See [hidden-death-package]")
(HIDE
(REWRITE)
"Hide a term from the rewriter
Hide is actually the [identity] function: (hide x) = x for all x.
However, terms of the form (hide x) are ignored by the ACL2
rewriter, except when explicit :expand [hints] are given for such
terms (see [hints]) or when rewrite rules explicitly about hide are
available. An :expand hint that removes all calls of hide is:
:expand ((:free (x) (hide x)))
The above hint can be particularly useful when ACL2's equality
heuristics apply hide to an equality after substituting it into the
rest of the goal, if that goal (or a subgoal of it) fails to be
proved.
Hide terms are also ignored by the induction heuristics.
Sometimes the ACL2 simplifier inserts hide terms into a proof attempt
out of the blue, as it were. Why and what can you do about it?
Suppose you have a constrained function, say constrained-fn, and
you define another function, say another-fn, in terms of it, as in:
(defun another-fn (x y z)
(if (big-hairy-test x y z)
(constrained-fn x y z)
t))
Suppose the term (another-fn 'a 'b 'c) arises in a proof. Since the
arguments are all constants, ACL2 will try to reduce such a term to
a constant by executing the definition of another-fn. However,
after a possibly extensive computation (because of big-hairy-test)
the execution fails because of the unevaluable call of
constrained-fn. To avoid subsequent attempts to evaluate the term,
ACL2 embeds it in a hide expression, i.e., rewrites it to (hide
(another-fn 'a 'b 'c)).
You might think this rarely occurs since all the arguments of
another-fn must be constants. You would be right except for one
special case: if another-fn takes no arguments, i.e., is a constant
function, then every call of it fits this case. Thus, if you define
a function of no arguments in terms of a constrained function, you
will often see (another-fn) rewrite to (hide (another-fn)).
We do not hide the term if the executable counterpart of the function
is disabled -- because we do not try to evaluate it in the first
place. Thus, to prevent the insertion of a hide term into the proof
attempt, you can globally disable the executable counterpart of the
offending defined function, e.g.,
(in-theory (disable (:executable-counterpart another-fn))).
It is conceivable that you cannot afford to do this: perhaps some
calls of the offending function must be computed while others
cannot be. One way to handle this situation is to leave the
executable counterpart enabled, so that hide terms are introduced
on the calls that cannot be computed, but prove explicit :[rewrite]
rules for each of those hide terms. For example, suppose that in
the proof of some theorem, thm, it is necessary to leave the
executable counterpart of another-fn enabled but that the call
(another-fn 1 2 3) arises in the proof and cannot be computed. Thus
the proof attempt will introduce the term (hide (another-fn 1 2
3)). Suppose that you can show that (another-fn 1 2 3) is
(constrained-fn 1 2 3) and that such a step is necessary to the
proof. Unfortunately, proving the rewrite rule
(defthm thm-helper
(equal (another-fn 1 2 3) (constrained-fn 1 2 3)))
would not help the proof of thm because the target term is hidden
inside the hide. However,
(defthm thm-helper
(equal (hide (another-fn 1 2 3)) (constrained-fn 1 2 3)))
would be applied in the proof of thm and is the rule you should
prove.
Now to prove thm-helper you need to use the two ``tricks'' which have
already been discussed. First, to eliminate the hide term in the
proof of thm-helper you should include the hint :expand (hide
(another-fn 1 2 3)). Second, to prevent the hide term from being
reintroduced when the system tries and fails to evaluate
(another-fn 1 2 3) you should include the hint :in-theory (disable
(:executable-counterpart another-fn)). Thus, thm-helper will
actually be:
(defthm thm-helper
(equal (hide (another-fn 1 2 3)) (constrained-fn 1 2 3))
:hints
((\"Goal\" :expand (hide (another-fn 1 2 3))
:in-theory (disable (:executable-counterpart another-fn)))))
See [eviscerate-hide-terms] for how to affect the printing of hide
terms.
Function: <hide>
(defun hide (x)
(declare (xargs :guard t))
x)")
(HINTS
(MISCELLANEOUS)
"Advice to the theorem proving process
Examples:
The following :hints value is nonsensical. Nevertheless, it
illustrates all of the available hint keywords except the
``custom keywords'' (see [custom-keyword-hints]) definable
by the user.
:hints ((\"Goal\"
:do-not-induct t
:do-not '(generalize fertilize)
:expand ((assoc x a)
:lambdas
(:free (y) (:with member (member y z))))
:restrict ((<-trans ((x x) (y (foo x)))))
:hands-off (length binary-append)
:in-theory (set-difference-theories
(current-theory :here)
'(assoc))
:induct (and (nth n a) (nth n b))
:use ((:instance assoc-of-append
(x a) (y b) (z c))
(:functional-instance
(:instance p-f (x a) (y b))
(p consp)
(f assoc)))
:bdd (:vars (c a0 b0 a1 b1) :prove nil :bdd-constructors (cons))
:clause-processor (:function cl-proc :hint (my-hint clause))
:instructions (:x :prove)
:cases ((true-listp a) (consp a))
:by (:instance rev-rev (x (cdr z)))
:nonlinearp t
:backchain-limit-rw 3
:reorder (4 7 2)
:case-split-limitations (20 10)
:no-op t
:no-thanks t
:error (\"Bad value ~x0.\" 123)
:or (hint-kwd-alist-1 ... hint-kwd-alist-k)
:rw-cache-state nil
:backtrack (my-computed-hint clause processor clause-list)))
A very common hint is the :use hint, which in general takes as its
value a list of ``lemma instances'' (see [lemma-instance]) but
which allows a single lemma name as a special case. Here are two
examples, one using a single lemma name and one using a lemma
instance:
; Attach :use hint to the top-level goal, which is named \"Goal\":
:hints ((\"Goal\" :use lemma23))
; Equivalent to the above: use the trivial instance (i.e., with the empty
; substitution of lemma23:
:hints ((\"Goal\" :use ((:instance lemma23))))
; Attach :use hint to the named subgoal, where the indicated lemma is used
; with the substitution that maps x to 17 and y to (foo z):
:hints ((\"[1]Subgoal *1/1.2'\" :use ((:instance lemma23
(x 17)
(y (foo z))))))
; Equivalent to the above: ACL2 allows you to omit the outer parentheses if
; there is only one lemma used.
:hints ((\"[1]Subgoal *1/1.2'\" :use (:instance lemma23
(x 17)
(y (foo z)))))
ACL2 also provides ``custom keyword'' hints (see
[custom-keyword-hints]) and even more general ``computed hints''
for the advanced user (see [computed-hints]).
Only the first hint applicable to a goal, as specified in the
user-supplied list of :hints followed by the default hints (see
[default-hints-table]), will be applied to that goal. For an
advanced exception, see [override-hints]. For a detailed discussion
of how hints fit into the ACL2 waterfall, see
[hints-and-the-waterfall]. For examples of the sophisticated use of
hints, primarily for experts, see community book
books/hints/basic-tests.lisp.
Background: Hints are allowed in all [events] that use the theorem
prover. During [defun] [events] there are two different uses of the
theorem prover: one to prove termination and another to verify the
[guard]s. To pass a hint to the theorem prover during termination
proofs, use the :hints keyword in the [defun]'s [xargs]
declaration. To pass a hint to the theorem prover during the
[guard] verification portion of admitting a [defun], use the
:guard-hints keyword in the [defun]'s [xargs] declaration. The
[verify-guards] event and the [defthm] event also use the theorem
prover. To pass hints to them, use the :hints keyword argument to
the event.
General Form of Common :hints:
((goal-spec :key1 val1 ... :keyn valn)
...
(goal-spec :key1 val1 ... :keyn valn))
where [goal-spec] is as described elsewhere (see [goal-spec]) and the
keys and their respective values are shown below with their
interpretations. We also provide ``computed hints'' but discuss
them separately; see [computed-hints]. The hint keywords below are
considered in alphabetical order.
:backchain-limit-rw
Value is a natural number or nil, indicating the level of
backchaining for [rewrite], [meta], and [linear] rules. This
overrides, for the current goal and (as with :[in-theory]
hints) descendent goals, the default [backchain-limit] (see
[set-backchain-limit]).
:backtrack
This is an advanced hint. You can probably accomplish its effect by
the use of ordinary computed hints; see [computed-hints]. But
if you are an expert, read on. (See [hints-and-the-waterfall]
for some relevant background.)
Value is a computed hint, which is an expression that evaluates
either to nil --- indicating that the :backtrack hint is to
have no effect --- or to a non-empty alternating list of
:keyi :vali pairs, as expected for a hint. However, unlike
ordinary computed hints, :backtrack hints are evaluated after
a goal has been processed to yield zero or more subgoals, not
before. Moreover, variables PROCESSOR and CLAUSE-LIST are
allowed, but variable STABLE-UNDER-SIMPLIFICATIONP is not. We
explain in more detail below, but first consider the
following simple example. First we define a standard list
reversal function:
(defun rev (x)
(if (consp x)
(append (rev (cdr x)) (cons (car x) nil))
nil))
Now we prove:
(thm (true-listp (rev x)))
The successful proof includes the following output.
Subgoal *1/1'
(IMPLIES
(AND (CONSP X)
(TRUE-LISTP (REV (CDR X))))
(TRUE-LISTP (APPEND (REV (CDR X)) (LIST (CAR X))))).
The destructor terms (CAR X) and (CDR X) can be
eliminated by using CAR-CDR-ELIM to replace X
by (CONS X1 X2), (CAR X) by X1 and (CDR X) by
X2. This produces the following goal.
Subgoal *1/1''
(IMPLIES (AND (CONSP (CONS X1 X2))
(TRUE-LISTP (REV X2)))
(TRUE-LISTP (APPEND (REV X2) (LIST X1)))).
But suppose that we attach a :backtrack hint to the goal above at
which destructor elimination was applied:
(thm (true-listp (rev x))
:hints ((\"Subgoal *1/1'\"
:backtrack
(quote (:do-not '(eliminate-destructors))))))
Then when ACL2 applies destructor elimination as displayed above,
this time the :backtrack hint applies, evaluating to (:do-not
'(eliminate-destructors)). Since this list is not nil, the
prover decides not to keep the new subgoal, and instead
supplies this :do-not hint before attacking the goal again.
In this example, ACL2 happens to use a technique later in its
``waterfall'' arsenal than destructor elimination, namely,
generalization:
Subgoal *1/1'
(IMPLIES
(AND (CONSP X)
(TRUE-LISTP (REV (CDR X))))
(TRUE-LISTP (APPEND (REV (CDR X)) (LIST (CAR X))))).
[Note: A hint was supplied for our processing
of the goal above, because of a :backtrack hint
that is preventing destructor elimination.
Thanks!]
We generalize this conjecture, replacing
(REV (CDR X)) by RV. This produces
Subgoal *1/1''
(IMPLIES (AND (CONSP X) (TRUE-LISTP RV))
(TRUE-LISTP (APPEND RV (LIST (CAR X))))).
We now provide a careful explanation of how :backtrack hints work,
but we suggest that you keep the example above in mind. If
``:backtrack form'' is part of the hint that has been
selected for a goal, then form is evaluated when one of
ACL2's clause processors successfully applies to the current
goal to produce a list of subgoals. This evaluation takes
place in an environment just like that for any computed hint
(see [computed-hints]), with the following exceptions. First,
the variable STABLE-UNDER-SIMPLIFICATIONP is not allowed to
occur free in form, but instead the following new variables
are allowed to occur free and are bound for this evaluation
as follows: PROCESSOR is bound to the processor in the list
*preprocess-clause-ledge* that has applied to the goal, and
CLAUSE-LIST is bound to the list of clauses (each a list of
literals that is implicitly disjoined) returned by that
clause processor. Second, the variables HIST and PSPV are
bound to the history and pspv returned by the clause
processor, not the ones that were passed to the clause
processor. If this evaluation returns an error, then the
proof aborts, as for any computed hint whose evaluation
returns an error. If this evaluation returns nil, then the
:backtrack hint has no effect, and the goal is replaced by
the list of goals (the value of CLAUSE-LIST described above),
as usual. Otherwise, the clause processor is deemed to have
failed, and the goal clause is tried again starting at the
top of the waterfall after selecting the hint returned by the
above evaluation. That hint will normally be an alternating
list of hint keywords and their values, but if it is a custom
keyword hint (see [custom-keyword-hints]), then it will be
handled in the usual manner but with the first three
variables above bound to the symbol :OMITTED. Of course, if
the new hint includes a value for :BACKTRACK then this
process can loop; care should be taken to keep that from
happening.
A final note about :BACKTRACK hints: since these are a form of
computed hints, [override-hints] (if any) are applied to
their evaluation result just as with any computed hint. That
is, the backtrack hint is successively modified with each
override-hint, to produce a final hint that is actually used
(or, ignored if that final hint is nil). See
[override-hints].
:[bdd]
This hint indicates that ACL2's built-in ordered binary decision
diagrams (BDDs) with rewriting are to be used to prove or
simplify the goal. See [bdd] for an introduction to the ACL2
BDD algorithm.
Value is a list of even length, such that every other element,
starting with the first, is one of the keywords :vars,
:bdd-constructors, :prove, or :literal. Each keyword that is
supplied should be followed by a value of the appropriate
form, as shown below; for others, a default is used. Although
:vars must always be supplied, we expect that most users will
be content with the defaults used for the other values.
:vars --- A list of ACL2 variables, which are to be treated as
Boolean variables. The prover must be able to check,
using trivial reasoning (see [type-set]), that each of
these variables is Boolean in the context of the current
goal. Note that the prover will use very simple
heuristics to order any variables that do not occur in
:vars (so that they are ``greater than'' the variables
that do occur in :vars), and these heuristics are often
far from optimal. In addition, any variables not listed
may fail to be assumed Boolean by the prover, which is
likely to seriously impede the effectiveness of ACL2's
BDD algorithm. Thus, users are encouraged not to rely on
the default order, but to supply a list of variables
instead. Finally, it is allowed to use a value of t for
vars. This means the same as a nil value, except that the
BDD algorithm is directed to fail unless it can guarantee
that all variables in the input term are known to be
Boolean (in a sense discussed elsewhere; see
[bdd-algorithm]).
:literal --- An indication of which part of the current goal should
receive BDD processing. Possible values are:
:all treat entire goal as a single literal (the default)
:conc process the conclusion
n process the hypothesis with index n (1, 2, ...)
:bdd-constructors --- When supplied, this value should be a list of
function symbols in the current ACL2 [world]; it is
(cons) by default, unless :bdd-constructors has a value
in the [ACL2-defaults-table] by default, in which case
that value is the default. We expect that most users will
be content with the default. See [bdd-algorithm] for
information about how this value is used.
:prove --- When supplied, this value should be t or nil; it is t by
default. When the goal is not proved and this value is t,
the entire proof will abort. Use the value nil if you are
happy to the proof to go on with the simplified term.
:by
Value is a [lemma-instance], nil, or a new event name. If the value
is a [lemma-instance] (see [lemma-instance]), then it
indicates that the goal (when viewed as a clause) is either
equal to the proposition denoted by the instance, or is
subsumed by that proposition when both are viewed as clauses.
To view a formula as a clause, union together the negations
of the hypotheses and add the conclusion. For example,
(IMPLIES (AND (h1 t1) (h2 t2)) (c t1))
may be viewed as the clause
{~(h1 t1) ~(h2 t2) (c t1)}.
Clause c1 is ``subsumed'' by clause c2 iff some instance of c2 is a
subset of c1. For example, the clause above is subsumed by
{~(h1 x) (c x)}, which when viewed as a formula is (implies
(h1 x) (c x)).
Note that if the value is the name of a function symbol introduced by
[defun], then the original form of the body of that
definition is used. This behavior differs from that provided
by a :use hint, which uses the so-called ``normalized'' body,
for which ACL2 has propagated IF tests upward and potentially
simplified with [type-set] reasoning and the expansion of
calls of a few built-in functions.
If the value is nil or a new name, the prover does not even attempt
to prove the goal to which this hint is attached. Instead the
goal is given a ``bye'', i.e., it is skipped and the proof
attempt continues as though the goal had been proved. If the
prover terminates without error then it reports that the
proof would have succeeded had the indicated goals been
proved and it prints an appropriate [defthm] form to define
each of the :by names. The ``name'' nil means ``make up a
name.'' Here is an example (admittedly contrived for
illustration purposes).
ACL2 !>(thm (equal (append (append x y) z)
(append x y z))
:hints ((\"Subgoal *1/2'\" :by nil)))
Name the formula above *1.
[[... output omitted here ...]]
[Note: A hint was supplied for our processing of the goal below.
Thanks!]
Subgoal *1/2'
(IMPLIES (AND (CONSP X)
(EQUAL (APPEND (APPEND (CDR X) Y) Z)
(APPEND (CDR X) Y Z)))
(EQUAL (APPEND (APPEND X Y) Z)
(APPEND X Y Z))).
But we have been asked to pretend that this goal is subsumed by the
yet-to-be-proved |THM Subgoal *1/2'|.
Subgoal *1/1
[[... proof goes on; further output omitted here ...]]
The system does not attempt to check the uniqueness of the :by names
(supplied or made up), since by the time those goals are
proved the namespace will be cluttered still further.
Therefore, the final list of ``appropriate'' [defthm] forms
may be impossible to admit without some renaming by the user.
If you must invent new names, remember to substitute the new
ones for the old ones in the :by hints themselves.
:[case-split-limitations]
Value is the same as for [set-case-split-limitations]. The simplifier
will behave as though the value had instead been supplied to
set-case-split-limitations; see [set-case-split-limitations].
This behavior will persist through subgoals unless overridden
by another :CASE-SPLIT-LIMITATIONS hint.
:cases
Value is a non-empty list of terms. For each term in the list, a new
goal is created from the current goal by assuming that term;
and also, in essence, one additional new goal is created by
assuming all the terms in the list false. We say ``in
essence'' because if the disjunction of the terms supplied is
a tautology, then that final goal will be a tautology and
hence will in fact never actually be created.
:[clause-processor]
Value specifies the application of a user-defined simplifier to the
current goal. See [clause-processor], which provides
necessary background and hint syntax. Also see
[define-trusted-clause-processor] for a discussion of
``trusted clause-processors'': goal-level simplifiers that
may be external to ACL2 and do not need to be proved correct
in ACL2.
You can see all current :clause-processor rules by issuing the
command (print-clause-processor-rules), and you can see the
names of all trusted clause-processors by issuing the command
(table trusted-clause-processor-table).
:do-not
Value is a term having at most the single free variable [world],
which when evaluated (with [world] bound to the current ACL2
logical [world]) produces a list of symbols that is a subset
of the list
(preprocess ;propositional logic, simple rules
simplify ;as above plus rewriting, linear arithmetic
eliminate-destructors
fertilize ;use of equalities
generalize
eliminate-irrelevance).
The hint indicates that the ``processes'' named should not be used at
or below the goal in question. Thus, to prevent
generalization and fertilization, say, include the hint
:do-not '(generalize fertilize)
If value is a single symbol, as in
:do-not generalize,
it is taken to be '(value).
See also [do-not-hint] for a way to automatically provide :do-not
hints across several theorems.
:do-not-induct
Value is t, :otf-flg-override, :otf, name or nil, indicating whether
[induction] is permitted under the specified goal. If value
is t or :otf-flg-override, then the attempt to apply
[induction] to the indicated goal or any subgoal under the
indicated goal will immediately cause the theorem prover to
report [failure], except that if :otf-flg t is specified (see
[otf-flg]) and value is t, then the proof will continue until
the time at which the goal pushed for induction is finally
considered. The latter behavior is also what occurs if value
is :otf. Thus, any non-nil value requires the indicated goal
to be proved entirely by simplification, destructor
elimination, and the other ``waterfall'' processes.
[Induction] to prove the indicated goal (or any subgoal) is
not permitted. See however the :induct hint below. If value
is a symbol other than t, :otf-flg-override, :otf or nil, the
theorem prover will give a ``bye'' to any subgoal that would
otherwise be attacked with induction. This will cause the
theorem prover to fail eventually but will collect the
necessary subgoals. If value is nil, this hint means
[induction] is permitted. Since that is the default, there is
no reason to use the value nil. Note that a :do-not-induct
hint is ignored for any goal on which an :induct hint is
supplied. For an advanced example of the use of value :otf
with [override-hints], see community book
books/hints/basic-tests.lisp.
:error
Value is typically a ``fmt message'' to be printed by the [fmt]
tilde-directive ~@ but may be any object. The effect of this
hint is to cause an error when the hint is translated. There
is no reason to include an :ERROR hint in any user-typein,
since it will only cause an error when the form is evaluated.
:ERROR hints are useful in the definition of functions that
generate custom keyword hints ([custom-keyword-hints]) and
computed hints ([computed-hints]). For example, if you wish
to define a custom keyword hint :my-hint val and you wish the
hint to signal an error if there is something inappropriate
about val in the context of the hint, use the following code
to generate the hint
(list :ERROR (cons \"Your specified value, ~x0, is inappropriate\"
(list (cons #0 val))))
which is equivalent to
(list :ERROR (msg \"Your specified value, ~x0, is inappropriate\"
val))
which, if val has the value 123, would evaluate to the hint
(:ERROR (\"Your specified value, ~x0, is inappropriate\" (#0 . 123))).
Note that any time an :ERROR keyword is produced during hint
processing, including iterations of the expansions of custom
keyword hints or of [override-hints], an error will occur.
:expand
Value is a true list of terms, each of which is of one of the forms
(let ((v1 t1)...) b) or (fn t1 ... tn), where fn is a defined
function symbol with formals v1, ..., vn, and body b. Such a
term is said to be ``expandable:'' it can be replaced by the
result of substituting the ti's for the vi's in b. The terms
listed in the :expand hint are expanded when they are
encountered by the simplifier while working on the specified
goal or any of its subgoals. We permit value to be a single
such term instead of a singleton list. Remarks: (1) Allowed
are ``terms'' of the form (:free (var1 var2 ... varn)
pattern) where the indicated variables are distinct and
pattern is a term. Such ``terms'' indicate that we consider
the indicated variables to be instantiatable, in the
following sense: whenever the simplifier encounters a term
that can be obtained from pattern by instantiating the
variables (var1 var2 ... varn), then it expands that term.
(2) Also allowed are ``terms'' of the form (:with name term),
where name is a function symbol, a macro name that denotes a
function symbol (see [macro-aliases-table]), or a [rune]. The
corresponding rule of class :rewrite, which is often a
[definition] rule but need not be, is then used in place of
the current body for the function symbol of term; see
[show-bodies] and see [set-body]. If the rule is of the form
(implies hyp (equiv lhs rhs)), then after matching lhs to the
current term in a context that is maintaining equivalence
relation equiv, ACL2 will replace the current term with (if
hyp rhs (hide term)), or just rhs if the rule is just (equal
lhs rhs). (3) A combination of both :free and :with, as
described above, is legal. (4) The term :LAMBDAS is treated
specially. It denotes the list of all lambda applications
(i.e., [let] expressions) encountered during the proof.
Conceptually, this use of :LAMBDAS tells ACL2 to treat lambda
applications as a notation for substitutions, rather than as
function calls whose opening is subject to the ACL2
rewriter's heuristics (specifically, not allowing lambda
applications to open when they introduce ``too many'' if
terms).
:hands-off
Value is a true list of function symbols or lambda expressions,
indicating that under the specified goal applications of
these functions are not to be rewritten. Note however that
subterms will still be rewritten; see [hide] if that is not
what is intended. (The community book
books/clause-processors/autohide.lisp from Jared Davis may
also be helpful in that case.) Value may also be a single
function symbol or lambda expression instead of a list.
:[in-theory]
Value is a ``theory expression,'' i.e., a term having at most the
single free variable [world] which when evaluated (with
[world] bound to the current ACL2 logical world (see
[world])) will produce a theory to use as the current theory
for the goal specified. See [theories].
Note that an :[in-theory] hint will always be evaluated relative to
the current ACL2 logical [world], not relative to the theory
of a previous goal. Consider the following example.
(defthm prop
(p (f (g x)))
:hints ((\"Goal\" :in-theory (disable f))
(\"Subgoal 3\" :in-theory (enable g))))
Consider in particular the theory in effect at Subgoal 3. This call
of the [enable] macro enables g relative to the
[current-theory] of the current logical [world], not relative
to the theory produced by the hint at Goal. Thus, the
[disable] of f on behalf of the hint at Goal will be lost at
Subgoal 3, and f will be enabled at Subgoal 3 if was enabled
globally when prop was submitted.
:induct
Value is either t or a term containing at least one recursively
defined function symbol; if t, this hint indicates that the
system should proceed to apply its induction heuristic to the
specified goal produced (without trying simplification,
etc.); if value is a term other than t, then not only should
the system apply induction immediately, but it should analyze
value rather than the goal to generate its [induction]
scheme. Merging and the other [induction] heuristics are
applied. Thus, if value contains several mergeable
[induction]s, the ``best'' will be created and chosen. E.g.,
the :induct hint
(and (nth i a) (nth j a))
suggests simultaneous [induction] on i, j, and a.
If both an :induct and a :do-not-induct hint are supplied for a given
goal then the indicated [induction] is applied to the goal
and the :do-not-induct hint is inherited by all subgoals
generated.
:[instructions]
Value is a list of [proof-checker] instructions; see [instructions].
Unlike other hint keywords described here, this one is
actually a custom keyword hint (see [custom-keyword-hints])
that generates a suitable :[clause-processor] hint.
:no-op
Value is any object and is irrelevant. This hint does nothing. But
empty hints, such as (\"Goal\"), are illegal and there are
occasions, especially when writing custom keyword hints (see
[custom-keyword-hints]) and computed hints (see
[computed-hints]) where it is convenient to be able to
generate a non-empty no-op hint. The standard idiom is
(\"Goal\" :NO-OP T) but the T is completely ignored. Unlike
other hint keywords, multiple occurrences of the keyword
:NO-OP are tolerated.
:no-thanks
Value is any object. This hint does nothing, except that if value is
non-nil then the usual ``[Note: A hint was supplied...
Thanks!]'' is not printed.
:nonlinearp
Value is t or nil, indicating whether [non-linear-arithmetic] is
active. The default value is nil. See
[non-linear-arithmetic].
:or
Value is a list (kwd-val-listp-1 ... kwd-val-listp-k), where each
kwd-val-listp-i is a list satisfying [keyword-value-listp],
i.e., an alternating list of keywords and values. This hint
causes an attempt to prove the specified goal using hints
kwd-val-listp-i in sequence (first kwd-val-listp-1, then
kwd-val-listp-2, and so on), until the first of these
succeeds. If none succeeds, then the prover proceeds after
heuristically choosing the ``best'' result, taking into
account the goals pushed in each case for proof by induction.
The following (contrived but illustrative example illustrates how :or
hints work.
ACL2 !>(thm (f x)
:hints
((\"Goal\"
:expand ((nth x 3))
:or ((:in-theory (disable car-cons))
(:use cdr-cons :in-theory (enable append)))
:do-not '(generalize))))
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
The :OR hint for Goal gives rise to two disjunctive branches. Proving
any one of these branches would suffice to prove Goal. We explore
them in turn, describing their derivations as we go.
---
Subgoal D2
( same formula as Goal ).
The first disjunctive branch (of 2) for Goal can be created by applying
the hint:
(\"Subgoal D2\" :EXPAND ((NTH X 3))
:IN-THEORY (DISABLE CAR-CONS)
:DO-NOT '(GENERALIZE)).
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
Normally we would attempt to prove this formula by induction. However,
we prefer in this instance to focus on the original input conjecture
rather than this simplified special case. We therefore abandon our
previous work on this conjecture and reassign the name *1 to the original
conjecture. (See :DOC otf-flg.) [Note: Thanks again for the hint.]
---
Subgoal D1
( same formula as Goal ).
The second disjunctive branch (of 2) for Goal can be created by applying
the hint:
(\"Subgoal D1\" :EXPAND ((NTH X 3))
:USE CDR-CONS
:IN-THEORY (ENABLE APPEND)
:DO-NOT '(GENERALIZE)).
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
ACL2 Warning [Use] in ( THM ...): It is unusual to :USE an enabled
:REWRITE or :DEFINITION rule, so you may want to consider disabling
(:REWRITE CDR-CONS).
We augment the goal with the hypothesis provided by the :USE hint.
The hypothesis can be obtained from CDR-CONS. We are left with the
following subgoal.
Subgoal D1'
(IMPLIES (EQUAL (CDR (CONS X Y)) Y)
(F X)).
By the simple :rewrite rule CDR-CONS we reduce the conjecture to
Subgoal D1''
(F X).
... and so on. This example illustrates how ACL2 processes :or hints
in general. For each i from 1 to k, a so-called
``disjunctive'' subgoal is created by splicing
kwd-val-listp-i into the other hint values (if any) supplied
for the given goal, in order. A corresponding subgoal is
created for each i, numbered in the usual manner (hence,
counting down) except that the ``D'' is prefixed to each
resulting goal.
:reorder
Value is a list of positive integers without duplicates,
corresponding to the numbering of subgoals generated for the
[goal-spec] \"G\", say \"G.k\" down to \"G.1\". Those subgoals are
reordered so that if value is (n1 n2 ... nk), then the goal
now numbered \"G.k\" will be the goal originally numbered
\"G.n1\"; the goal now numbered \"G.k-1\" will be the goal
formerly numbered \"G.n2\"; and so on, down the list of ni,
after which the goals not yet printed are printed in their
original order. Note that reordering for subgoals of a goal
to be proved by induction, such as *1, is not supported.
:restrict
Warning: This is a sophisticated hint, suggested by Bishop Brock,
that is intended for advanced users. In particular, :restrict
hints are ignored by the preprocessor, so you might find it
useful to give the hint :do-not '(preprocess) when using any
:restrict hints, at least if the rules in question are
abbreviations (see [simple]).
Value is an association list. Its members are of the form (x subst1
subst2 ...), where: x is either (1) a [rune] whose [car] is
:[rewrite] or :[definition] or (2) an event name
corresponding to one or more such [rune]s; and (subst1 subst2
...) is a non-empty list of substitutions, i.e., of
association lists pairing variables with terms. First
consider the case that x is a :[rewrite] or :[definition]
[rune]. Recall that without this hint, the rule named x is
used by matching its left-hand side (call it lhs) against the
term currently being considered by the rewriter, that is, by
attempting to find a substitution s such that the
instantiation of lhs using s is equal to that term. If
however the :restrict hint contains (x subst1 subst2 ...),
then this behavior will be modified by restricting s so that
it must extend subst1; and if there is no such s, then s is
restricted so that it must extend subst2; and so on, until
the list of substitutions is exhausted. If no such s is
found, then the rewrite or definition rule named x is not
applied to that term. Finally, if x is an event name
corresponding to one or more :[rewrite] or :[definition]
[rune]s (that is, x is the ``base symbol'' of such [rune]s;
see [rune]), say [rune]s r1, ... rn, then the meaning is the
same except that (x subst1 subst2 ...) is replaced by (ri
subst1 subst2 ...) for each i. Once this replacement is
complete, the hint may not contain two members whose [car] is
the same [rune].
Note that the substitutions in :restrict hints refer to the variables
actually appearing in the goals, not to the variables
appearing in the rule being restricted.
Here is an example, supplied by Bishop Brock. Suppose that the
database includes the following rewrite rule, which is
probably kept [disable]d. (We ignore the question of how to
prove this rule.)
cancel-<-*$free:
(implies (and (rationalp x)
(rationalp y)
(rationalp z))
(equal (< y z)
(if (< x 0)
(> (* x y) (* x z))
(if (> x 0)
(< (* x y) (* x z))
(hide (< y z))))))
Then ACL2 can prove the following theorem (unless other rules get in
the way), essentially by multiplying both sides by x.
(thm
(implies (and (rationalp x)
(< 1 x))
(< (/ x) 1))
:hints
((\"Goal\"
:in-theory (enable cancel-<-*$free)
:restrict ((cancel-<-*$free ((x x) (y (/ x)) (z 1)))))))
The :restrict hint above says that the variables x, y, and z in the
rewrite rule cancel-<-*$free above should be instantiated
respectively by x, (/ x), and 1. Thus (< y z) becomes (< (/
x) 1), and this inequality is replaced by the corresponding
instance of the right-hand-side of cancel-<-*$free. Since the
current conjecture assumes (< 1 x), that instance of the
right-hand side simplifies to
(< (* x (/ x)) (* x 1))
which in turn simplifies to (< 1 x), a hypothesis in the present
theorem.
:rw-cache-state
Value is an element of the list constant *legal-rw-cache-states*:
:atom (the default), nil, t, or :disabled. This hint applies
to the indicated goal and all its descendents, to set the
so-called ``rw-cache-state'' to the indicated value; see
[set-rw-cache-state].
:use
Examples of :USE hints are shown near the top of this documentation
topic.
Value is a [lemma-instance] or a true list of [lemma-instance]s,
indicating that the propositions denoted by the instances be
added as hypotheses to the specified goal. See
[lemma-instance]. Note that :use makes the given instances
available as ordinary hypotheses of the formula to be proved.
The :instance form of a [lemma-instance] permits you to
instantiate the free variables of previously proved theorems
any way you wish; but it is up to you to provide the
appropriate instantiations because once the instances are
added as hypotheses their variables are no longer
instantiable. These new hypotheses participate fully in all
subsequent rewriting, etc. If the goal in question is in fact
an instance of a previously proved theorem, you may wish to
use :by below. Note that [theories] may be helpful when
employing :use hints; see [minimal-theory].
Note that if the value is the name of a function symbol introduced by
[defun], then the ``normalized'' body of that definition is
used, for which ACL2 has propagated IF tests upward. This
behavior differs from that provided by a :by hint, where the
original body of the definition is used.
Subtopics
[Computed-hints]
Computing advice to the theorem proving process
[Custom-keyword-hints]
User-defined hints
[Default-hints]
A list of hints added to every proof attempt
[Do-not]
Instruct the theorem prover not to do certain things.
[Goal-spec]
To indicate where a hint is to be used
[Guard-theorem]
Use a previously-proved [guard] theorem
[Guard-theorem-example]
How to use a previously-proved [guard] theorem
[Hints-and-the-waterfall]
How [hints] fit into the ACL2 proof waterfall
[Lemma-instance]
An object denoting an instance of a theorem
[Override-hints]
A list of hints given priority in every proof attempt
[Termination-theorem]
Use a previously-proved measure theorem
[Termination-theorem-example]
How to use a previously-proved measure theorem
[Using-computed-hints]
How to use computed hints")
(HINTS-AND-THE-WATERFALL
(HINTS)
"How [hints] fit into the ACL2 proof waterfall
Below we describe the flow of an ACL2 proof attempt, with special
attention to how [hints] are applied during a proof. For most ACL2
users, only one point is important to take away from this
[documentation] topic: you may specify hints during a proof (see
[hints]; perhaps also see [computed-hints] and see
[default-hints]), and they can be expected to behave intuitively.
See [the-method] for a summary of how to interact with the ACL2
prover; see [introduction-to-the-theorem-prover] for a more
detailed tutorial; and see [hints] for an introduction to ACL2
hints, including detailed [documentation] for specific hint types.
The remainder of this topic serves as a reference in case one needs a
deeper understanding of the workings of ACL2's handling of hints.
Also, for examples of the sophisticated use of hints, primarily for
experts, see community book books/hints/basic-tests.lisp.
First, we describe the ACL2 ``waterfall'', which handles each goal
either by replacing it with a list (possibly empty) of child goals,
or else by putting the goal into a ``pool'' for later proof by
induction. Then, we describe how hints are handled by the
waterfall.
The Waterfall.
Each goal considered by the ACL2 prover passes through a series of
proof processes, called the ``waterfall processes'', as stored in
the constant *preprocess-clause-ledge*. The top process applies
top-level hints, including :use hints; the next is a lightweight
``preprocess'' simplifier for ``simple'' rules (see [simple]); the
next is the main ACL2 simplifier; and finally ACL2 attempts (in
this order) destructor elimination, fertilization (heuristic use of
equalities), generalization, and elimination of irrelevance. See
[architecture-of-the-prover] for more information on these
processes. Each process may ``hit'', creating zero or more child
goals that are each then handled at the top of the waterfall; or it
may ``miss'', in which case the next process in the above sequence
is considered. If all processes miss, then a ``push'' process
defers the goal until it is later considered for proof by
induction. When all goals have been thus handled, the goal most
recently pushed for proof by induction is considered, and the
process repeats.
We next describe the two additional ways in which control can be
returned to the top of the waterfall.
When the simplification process is attempted unsuccessfully for a
goal, the goal is deemed to have ``settled down''. In this case,
and if no ancestor of the goal has settled down, then the
``settled-down'' process is deemed to have ``hit'' on the goal, the
effect being that the goal makes a new pass through all the
waterfall processes. (Other processes can then notice that settling
down has occurred and modify their heuristics accordingly.) For
example, if \"Goal\" simplifies to \"Subgoal 2\" (among others), and
\"Subgoal 2\" simplifies to \"Subgoal 2.3\" (among others), which in
turn is not further simplified, then the ``settled-down'' process
hits on \"Subgoal 2.3\" but not on any of its children, their
children, and so on.
When simplification has missed (and thus the goal has settled down),
the next proof process is normally destructor elimination. However,
if a computed hint is suitable (in a sense described below; also
see [computed-hints], especially the discussion of
stable-under-simplificationp), then that hint is selected as
control is returned to the top of the waterfall. A subtlety is that
in this case, if the most recent hit had been from settling down,
then the prover ``changes its mind'' and considers that the goal
has not yet settled down after all as it continues through the
waterfall.
Each time a goal is considered at the top of the waterfall, then
before passing through the proof processes as described above, ACL2
searches for a relevant hint to select unless it has already been
provided a hint in the ``stable-under-simplificationp'' case
mentioned above. We turn now to a more thorough discussion of how
hints are selected and applied.
The handling of hints.
In the discussion below we will ignore forcing rounds, as each
forcing round is simply treated as a new proof attempt that uses
the list of hints provided at the start of the proof.
When the theorem prover is called by [thm] or [events] such as
[defthm], [defun], and [verify-guards], it gathers up the hints
that have been supplied, often provided as a :[hints] argument, but
for example using a :guard-hints argument for [guard] verification
proofs. (ACL2(r) users (see [real]) may also employ :std-hints.) It
then appends these to the front of the list of default hints (see
[default-hints]). The resulting list becomes the initial value of
the list of ``pending hints'', one of two critical lists maintained
by the theorem prover to manage hints. The other critical list is a
list of ``hint settings''; the two lists are maintained as follows.
When a goal is first considered, a hint is selected from the list of
pending hints if any is found to apply, as described below. If a
hint is selected, then it takes effect and is removed from the
pending hints. Except: if the selected hint is a computed hint with
value t specified for :computed-hint-replacement, then it is not
removed; and if that value is a list of hints, then that list is
appended to the front of the list of pending hints after the
selected hint is removed (also see [computed-hints]). The selected
hint is also used to update the hint settings, as described below.
The list of hint settings associates hint keywords with values. It is
passed from the current goal to its children (and hence the
children's children, and so on), though modified by hints selected
from pending hints, as described below. This list is maintained so
that when a goal is pushed for proof by induction, the hint
settings are applied at the start of the proof by induction. Note
that the list of hint settings is not re-applied to descendents of
a goal in the current waterfall; a hint is applied only when it is
selected (and also perhaps later as just described, through the
stored hint settings at the start of a proof by induction). For
example, if the hint selected for \"Subgoal 3\" includes :in-theory
(enable foo), then the hint settings are correspondingly updated
when processing \"Subgoal 3\", and they persist at subgoals such as
\"Subgoal 3.2\" and \"Subgoal 3.2.1\" (unless overriden by hints on
those goals); but the theory specifying foo is not re-installed at
every such subgoal.
When a hint is selected, the list of hint settings is updated so that
for each keyword :kwd and associated value val from the hint, :kwd
is associated with val in the hint settings, discarding any
previous association of :kwd with a value in the hint settings.
Except, certain ``top-level'' hints are never saved in the hint
settings: :use, :cases, :by, :bdd, :or, and :clause-processor.
For example, suppose that we specify the following hints, with no
default hints.
((\"Goal\" :expand ((bar x y)))
(\"Subgoal 3\" :in-theory (enable foo)))
These hints then become the initial list of pending hints. When the
proof attempt begins, the prover encounters the top-level goal
(\"Goal\") and pulls the \"Goal\" hint from the pending hints, so that
the list of hint settings contains a value only for keyword
:expand. This hint setting will remain for all children of the
top-level goal as well, and their children, and so on, and will be
inherited by induction --- in other words, it will remain
throughout the entire proof. Now consider what happens when the
proof reaches \"Subgoal 3\". At this point there is only one pending
hint, which is in fact attached to that subgoal. Therefore, this
hint is pulled from the pending hints (leaving that list empty),
and the hint settings are extended by associating the :in-theory
keyword with the theory represented by (enable foo). That theory is
immediately installed until the prover finishes addressing \"Subgoal
3\", its children, their children, and so on; and until that
completion is reached, the :in-theory keyword remains associated
with the (enable foo) in the hint settings, although of course
there is no re-installation of the theory at any ensuing child
goal. When finally \"Subgoal 3\" and its descendents have been
completed and the prover is about to consider \"Subgoal 2\", the
:in-theory association is removed from the hint settings and the
global theory is re-installed. However, the list of pending hints
remains empty.
It remains to describe how a hint is selected for a goal. When a goal
is first considered (hence at the top of the waterfall), the list
of pending hints is scanned, in order, until one of the hints is
suitable for the goal. An explicit hint (goal-name :kwd1 val1 ...
:kwdn valn) is suitable if goal-name is the name of the current
goal and there is at least one keyword. A computed hint is suitable
if it evaluates to a non-nil value. As indicated earlier in this
documentation topic, an exception occurs when a computed hint is
selected after simplification fails (the
``stable-under-simplificationp'' case): in that case, the goal
returns to the top of the waterfall with that hint as the selected
hint, and no additional search for a hint to select is made at that
time.
The following slightly tricky example illustrates handling of hints.
ACL2 !>(set-default-hints '((\"Goal\" :do-not '(preprocess))))
((\"Goal\" :DO-NOT '(PREPROCESS)))
ACL2 !>(thm (equal (append (append x y) z) (append x y z))
:hints ((\"Goal\" :in-theory (disable car-cons))))
ACL2 Warning [Hints] in ( THM ...): The goal-spec \"Goal\" is explicitly
associated with more than one hint. All but the first of these hints
may be ignored. If you intended to give all of these hints, combine
them into a single hint of the form (\"Goal\" :kwd1 val1 :kwd2 val2 ...).
See :DOC hints-and-the-waterfall.
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
Name the formula above *1.
The warning above is printed because \"Goal\" is associated with two
pending hints: one given by the [set-default-hints] call and one
supplied by the :[hints] keyword of the [thm] form. The :in-theory
hint is selected because user-supplied hints are ahead of default
hints in the list of pending hints; we then get the first ``Note''
above. The goal progresses through the waterfall without any proof
process applying to the goal; in particular, it cannot be further
simplified. After the simplification process, a ``settled-down''
process applies, as discussed above, immediately causing another
trip through the waterfall. Since the :in-theory hint was earlier
removed from the list of pending hints when it was applied, the
default (:do-not) hint is now the only pending hint. That hint is
applied, resulting in the second ``Note'' above.
Again, more examples may be found in the community book
books/hints/basic-tests.lisp. A particularly tricky but informative
example in that book is the one related to nonlinearp-default-hint.
Also see [override-hints] for an advanced feature that allows
modification of the hint selected for a goal.")
(HISTORY
(ACL2)
"Functions that display or change history
ACL2 keeps track of the [command]s that you have executed that have
extended the logic or the rule database, as by the definition of
macros, functions, etc. Using the facilities in this section you
can review the sequence of [command]s executed so far. For example,
you can ask to see the most recently executed [command], or the
[command] 10 before that, or the [command] that introduced a given
function symbol. You can also undo back through some previous
[command], restoring the logical [world] to what it was before the
given [command].
The annotations printed in the margin in response to some of these
commands (including `P', `L', `V', `D', `d', 'M', and 'm') are
explained in the documentation for :[pc].
Several technical terms are used in the documentation of the history
[command]s. You must understand these terms to use the [command]s.
These terms are documented via :[doc] entries of their own. See
[command], see [events], see [command-descriptor], and see
[logical-name].
Subtopics
[Command]
Forms you type at the top-level, but...
[Command-descriptor]
An object describing a particular [command] typed by the user
[Enter-boot-strap-mode]
The first millisecond of the Big Bang
[Exit-boot-strap-mode]
The end of pre-history
[Extend-pe-table]
Replace [events] displayed by [history] commands
[Formula]
The formula of a name or [rune]
[Get-command-sequence]
Return list of [command]s that are between two [command] descriptors
[Gthm]
The [guard] theorem for a given function symbol
[Oops]
Undo a :u or :[ubt]
[Pbt]
Print the [command]s back through a [command] descriptor
[Pc]
Print the [command] described by a [command] descriptor
[Pcb]
Print the [command] block described by a [command] descriptor
[Pcb!]
Print in full the [command] block described by a [command]
descriptor
[Pcs]
Print the sequence of [command]s between two [command] descriptors
[Pe]
Print the events named by a logical name
[Pe!]
Print events as with [pe] but ignoring the [pe-table]
[Pf]
Print the formula corresponding to the given name
[Pl]
Print the rules for the given name or term
[Pl2]
Print rule(s) for the given form
[Pr]
Print the rules stored by the event with the given name
[Pr!]
Print rules stored by the command with a given command descriptor
[Puff]
Replace a compound [command] by its immediate subevents
[Puff*]
Replace a compound [command] by its subevents
[Reset-kill-ring]
Save memory by resetting and perhaps resizing the kill ring used by
[oops]
[Reset-prehistory]
Reset the prehistory
[Tau-database]
To see the tau database as a (very large) object
[Tthm]
The [measure] (termination) theorem for a given function symbol
[U]
Undo last [command], without a query
[Ubt]
Undo the [command]s back through a [command] descriptor
[Ubt!]
Undo [command]s, without a query or an error
[Ubt-prehistory]
Undo the [command]s back through the last [reset-prehistory] event
[Ubt?]
Undo [command]s, with queries as appropriate
[Ubu]
Undo the [command]s back up to (not including) a [command]
descriptor
[Ubu!]
Undo [command]s, without a query or an error
[Ubu?]
Undo [command]s, with queries as appropriate")
(HONS
(PROGRAMMING HONS-AND-MEMOIZATION ACL2-BUILT-INS)
"(hons x y) returns a [normed] object equal to (cons x y).
In the logic, hons is just [cons]; we leave it enabled and would
think it odd to ever prove a theorem about it.
Under the hood, hons does whatever is necessary to ensure that its
result is [normed].
What might this involve?
Since the car and cdr of any normed cons must be normed, we need to
[hons-copy] x and y. This requires little work if x and y are
already normed, but can be expensive if x or y contain large,
un-normed cons structures.
After that, we need to check whether any normed cons equal to (x . y)
already exists. If so, we return it; otherwise, we need to
construct a new cons for (x . y) and install it as the normed
version of (x . y).
Generally speaking, these extra operations make hons much slower than
cons, even when given normed arguments.
Function: <hons>
(defun hons (x y)
(declare (xargs :guard t))
(cons x y))
Subtopics
[Hons-clear]
([hons-clear] gc) is a drastic garbage collection mechanism that
clears out the underlying Hons Space.
[Hons-clear!]
A version of [hons-clear] for [parallel] execution
[Hons-copy]
([hons-copy] x) returns a [normed] object that is equal to X.
[Hons-copy-persistent]
([hons-copy-persistent] x) returns a [normed] object that is equal
to X and which will be re-normed after any calls to
[hons-clear].
[Hons-equal]
([hons-equal] x y) is a recursive equality check that optimizes when
parts of its arguments are [normed].
[Hons-equal-lite]
([hons-equal-lite] x y) is a non-recursive equality check that
optimizes if its arguments are [normed].
[Hons-note]
Notes about [hons], especially pertaining to expensive resizing
operations
[Hons-resize]
([hons-resize] ...) can be used to manually adjust the sizes of the
hash tables that govern which ACL2 Objects are considered
[normed].
[Hons-summary]
([hons-summary]) prints basic information about the sizes of the
tables in the current Hons Space.
[Hons-wash]
([hons-wash]) is like [gc$] but can also garbage collect [normed]
objects (CCL and GCL Only).
[Hons-wash!]
A version of [hons-wash] for [parallel] execution
[Normed]
Normed objects are ACL2 Objects that are \"canonical\" or \"unique\" in
a certain sense.")
(HONS-ACONS
(FAST-ALISTS ACL2-BUILT-INS)
"(hons-acons key val alist) is the main way to create or extend
[fast-alists].
Logically, hons-acons is like [acons] except that its guard does not
require [alistp]; we leave it enabled and would think it odd to
ever prove a theorem about it.
Under the hood, two things are done differently. First, the key is
copied with [hons-copy]; this lets us use EQL-based hash tables
instead of EQUAL-based hash tables for better performance. Second,
assuming there is a valid hash table associated with this alist, we
destructively update the hash table by binding key to val. The hash
table will no longer be associated with alist, but will instead be
associated with the new alist returned by hons-acons.
Hash Table Creation
A new hash table is created by hons-acons whenever alist is an atom.
Unlike ordinary acons, we do not require that alist be nil, and in
fact you may wish to use a non-nil value for one of two reasons.
1. As a size hint
By default, the new hash table will be given a quite modest default
capacity of 60 elements. As more elements are added, the table may
need to be resized to accommodate them, and this resizing has some
runtime cost.
When a natural number is used as a fast alist's name, we interpret it
as a size hint. For example, (hons-acons 'foo 'bar 1000) instructs
us to use 1000 as the initial size for this hash table and binds
'foo to 'bar. The resulting table should not need to be resized
until more than 1000 elements are added. We ignore size hints that
request fewer than 60 elements.
Because of hash collisions, hash tables typically need to have a
larger size than the actual number of elements they contain. The
hash tables for fast alists are told to grow when they reach 70%
full. So, an easy rule of thumb might be: multiply the expected
number of elements you need by 1.5 to keep your hash tables about
2/3 full.
2. As an alist name
We also frequently use a symbol for alist, and think of this symbol
as the name of the new alist. We have found that naming alists can
be valuable for two reasons:
First, the name can be helpful in identifying fast alists that should
have been freed, see [fast-alist-summary].
Second, names can sometimes be used to avoid a subtle and insidious
table-stealing phenomenon that occurs when using fast-alists that
are themselves normed; see [hons-acons!].
At the moment, there is no way to simultaneously name a fast alist
and also give it a size hint. We may eventually allow strings to
include embedded name and size components, but for now we have not
implemented this capability.
Function: <hons-acons>
(defun hons-acons (key val alist)
(declare (xargs :guard t))
(cons (cons key val) alist))")
(HONS-ACONS!
(FAST-ALISTS ACL2-BUILT-INS)
"(hons-acons! key val alist) is an alternative to [hons-acons] that
produces [normed], fast alists.
Logically, hons-acons! is like [acons] except that its guard does not
require [alistp]; we leave it enabled and would think it odd to
ever prove a theorem about it.
Ordinarily, [fast-alists] are constructed with [hons-acons] instead
of hons-acons!. In such alists, the keys are honsed, but the conses
that make up the \"spine\" of the alist itself are ordinary conses.
In other words, it is basically correct to say:
(hons-acons key val alist) == (cons (cons (hons-copy key) val) alist)
In contrast, when hons-acons! is used, the conses making up the alist
itself are also normed. That is,
(hons-acons! key val alist) == (hons (hons key val) alist)
Generally, you should not use hons-acons! unless you really know what
you're doing.
Drawback 1. hons-acons! requires you to [hons-copy] all of the values
that are being stored in the fast alist. If you are storing large
values, this may be expensive.
Drawback 2. It can be more difficult to maintain the proper
discipline when using hons-acons!. For instance, consider the
following:
(let ((al1 (hons-acons 1 'one (hons-acons 2 'two nil)))
(al2 (hons-acons 1 'one (hons-acons 2 'two nil))))
...)
Here, both al1 and al2 are valid fast alists and they can be extended
independently without any trouble. But if these alists had instead
been constructed with hons-acons!, then since both al1 and al2 are
equal, normed conses, they will literally be [eq] and hence will
refer to precisely the same hash table. In other words, hons-acons!
makes it relatively easy to inadvertently steal the hash table
associated with some other fast alist. This problem can be
alleviated somewhat by uniquely naming alists; see the discussion
in [hons-acons] for details.
Despite these drawbacks, hons-acons! is the typical way to generate a
fast alist that is normed (but also, for example, see
[fast-alist-fork!]). It is not adequate to [hons-copy] a fast alist
that was generated by ordinary [hons-acons] calls, because this
would produce an EQUAL-but-not-EQ object, and this new object would
not be associated with the fast alist's hash table.
Function: <hons-acons!>
(defun hons-acons! (key val alist)
(declare (xargs :guard t))
(cons (cons key val) alist))")
(HONS-AND-MEMOIZATION
(ACL2)
"Hash cons, function memoization, and applicative hash tables
This topic describes the hash cons, function memoization, and
applicative hash tables features available in ACL2, sometimes
called the ``[hons-enabled]'' features.
Bob Boyer and Warren Hunt, and later Jared Davis and Sol Swords, have
developed a canonical representation for ACL2 data objects and a
function memoization mechanism to facilitate reuse of previously
computed results. This facility includes procedures to read and
print ACL2 expressions in such a way that repetition of some ACL2
objects is eliminated, thereby permitting a kind of on-the-fly file
compression. The implementation does not alter the semantics of
ACL2 except to add a handful of definitions.
We historically gave the name ``ACL2(h)'' to the experimental
extension of the ACL2 system including hash cons, function
memoization, and fast association lists (applicative hash tables).
These features, which we call the ``[hons-enabled]'' features, are
now present in ACL2. The hons-enabled features are optimized for
Clozure Common Lisp (CCL) and to some extent, GNU Common Lisp (GCL
ANSI); but they are also supported in every ACL2 build.
Power users who want to take advantage of the [hons-enabled] features
of ACL2 might find it helpful to consult the document
centaur/README.html in the ACL2 community books.
Much of the documentation for the remainder of this topic is taken
from the paper ``Function Memoization and Unique Object
Representation for ACL2 Functions'' by Robert S. Boyer and Warren
A. Hunt, Jr., which has appeared in the Sixth International
Workshop on the ACL2 Theorem Prover and Its Applications, ACM
Digital Library, 2006.
In the implementation of the ACL2 logic, ACL2 data objects are
represented by Common Lisp objects of the same type, and the ACL2
pairing operation is internally implemented by the Common Lisp
[cons] function. In Common Lisp, cons is guaranteed to provide a
new pair, distinct from any previously created pair. We have
defined a new ACL2 function [hons] that is logically identical to
the ACL2 cons function, but whose implementation usually reuses an
existing pair if its components are identical to the components of
an existing pair. A record of ACL2 HONS objects is kept, and when
an ACL2 function calls hons ACL2 searches for an existing identical
pair before allocating a new pair; this operation been called
``hash consing''.
It appears that hash consing was first conceived by A. P. Ershov in
1957, to speed up the recognition of common subexpressions. Ershov
showed how to collapse trees to minimal DAGs by traversing trees
bottom up, and he used hashing to eliminate the re-evaluation of
common subexpressions. In his 1973 PhD dissertation L. Peter
Deutsch describes a program verifier that uses hash cons to
represent terms and his rewriter operated on hash consed terms.
Later, Eiichi Goto implemented a Lisp system with a built-in hash
consing operation: his h-CONS cells were rewrite protected and free
of duplicate copies, and Goto used this hash consing operation to
facilitate the implementation of a symbolic algebra system he
developed.
Memoizing functions also has a long history. In 1967, Donald Michie
proposed using memoized functions to improve the performance of
machine learning. Rote learning was improved by a learning function
not forgetting what it had previously learned; this information was
stored as memoized function values.
The use of hash consing has appeared many times. For instance, Henry
Baker used hash consing to improve the performance of the
well-known Boyer rewriting benchmark. Baker used both hash consing
and function memoization to improve the speed of the Takeuchi
function, exactly in the spirit of our implementation, but without
the automated, system-wide integration we report here.
The ACL2 implementation permits memoization of user-defined
functions. During execution a user may enable or disable function
memoization on an individual function basis, may clear memoization
tables, and may even keep a stack of memoization tables. This
facility takes advantage of our implementation where we keep one
copy of each distinct ACL2 data object. Due to the functional
nature of ACL2, it is sufficient to have at most one copy of any
data structure; thus, a user may arrange to keep data
canonicalized. This implementation extends to the entire ACL2
system the benefits enjoyed by BDDs: canonicalization, memoization,
and fast equality check.
We have defined various algorithms using these features, and we have
observed, in some cases, substantial performance increases. For
instance, we have implemented unordered set intersection and union
operations that operate in time roughly linear in the size of the
sets. Without using arrays, we defined a canonical representation
for Boolean functions using ACL2 objects. We have investigated the
performance of rewriting and tree consensus algorithms to good
effect, and we believe function memoization offers interesting
opportunities to simplify algorithm definition while simultaneously
providing performance improvements.
We recommend that users focus at first on the logical definitions of
[hons] and other primitives rather than their underlying Common
Lisp implementations. Integrated with this memoization system is a
performance monitoring system, which can provide real-time feedback
on the operation and usefulness of [hons] and function memoization.
For a more detailed description of these tools, please see the ACL2
2006 workshop paper mentioned above.
The Fibonacci function is a small example that demonstrates the
utility of function memoization. The following definition exhibits
a runtime that is exponential in its input argument.
(defun fib (x)
(declare (xargs :guard (natp x)))
(mbe
:logic
(cond ((zp x) 0)
((= x 1) 1)
(t (+ (fib (- x 1)) (fib (- x 2)))))
:exec
(if (< x 2)
x
(+ (fib (- x 1)) (fib (- x 2))))))
Below we show how the ACL2 [time$] utility can measure the time to
execute a call to the fib function (with some editing to avoid
noise from the underlying Common Lisp implementation). [Memoize] is
actually an ACL2 macro that expands to a call of the ACL2 function
used to identify a function for memoization; see [memoize]. This
function also accepts a well-formed term that must be true in order
for the system to memoize a call of the memoized function; to
ensure that an instance of the term is safe for evaluation in
Common Lisp, a check is performed that if the [guard] of the
memoized function is satisfied, then this instance will execute
without error.
ACL2 !>(time$ (fib 40))
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 0.99 seconds realtime, 0.98 seconds runtime
; (1,296 bytes allocated).
102334155
ACL2 !>(memoize 'fib)
Summary
Form: ( TABLE MEMOIZE-TABLE ...)
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
Summary
Form: ( PROGN (TABLE MEMOIZE-TABLE ...) ...)
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
FIB
ACL2 !>(time$ (fib 40))
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 0.00 seconds realtime, 0.00 seconds runtime
; (2,864 bytes allocated).
102334155
ACL2 !>(time$ (fib 100))
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 0.00 seconds realtime, 0.00 seconds runtime
; (7,024 bytes allocated).
354224848179261915075
ACL2 !>(unmemoize 'fib)
We see that once the function fib is identified as a function for
which function calls should be memoized, the execution times are
substantially reduced. Finally, we can prevent fib from being
further memoized; in fact, [unmemoize] erases the previously
memoized values.
The implementation of hash consing, memoization, and applicative hash
tables involves several facets: canonical representation of ACL2
data, function memoization, and the use of Lisp hash tables to
improve the performance of association list operations. We discuss
each of these in turn, and we mention some subtle
interrelationships. Although it is not necessary to understand the
discussion in this section, it may permit some users to better use
this implementation. This discussion may be confusing for some ACL2
users as it makes references to Lisp implementation features.
The ACL2 system is actually implemented as a Lisp program that is
layered on top of a Common Lisp system implementation. ACL2 data
constants are implemented with their corresponding counterparts in
Common Lisp; that is, ACL2 cons pairs, strings, characters,
numbers, and symbols are implemented with their specific Common
Lisp counterparts. This choice permits a number of ACL2 primitive
functions to be implemented with their corresponding Common Lisp
functions, but there are indeed differences. ACL2 is a logic, and
as such, it does not specify anything to do with physical storage
or execution performance. When ACL2 is used, the knowledgeable user
can write functions to facilitate the reuse of some previously
computed values.
Recall the three mechanisms under discussion: hash consing, function
memoization, and fast association list operations. The function
memoization mechanism takes advantage of the canonical
representation of data objects provided by the [hons] operation as
does the fast association list operation mechanism. Each time hons
is invoked, its arguments are themselves converted, if necessary,
to uniquely represented objects.
The ACL2 universe is recursively closed under the cons pairing
operation and the atoms. Hash consing ([hons]) is logically
identical to cons, but a set of tables is used to record each hons
pair. When a hons pair is requested, the implementation checks, in
the current set of tables, whether the requested pair already
exists. If not, a new pair is created and a record of that pair is
made; otherwise, a reference to the previously created pair is
returned. Thus, any data object created with hons has a unique
representation, as does every subcomponent. We also arrange for
strings to have a unique representation --- only one copy of each
different string is kept --- and when any previously unseen string
is an argument to hons, we add the string to a unique table of
strings. A system-wide benefit of having a canonical representation
for data is that equality comparisons between any two data objects
can be done in constant time.
The definition of [hons] in no way changes the operation of cons ---
hons creates a cons pair. When asked to create a hons, the
implementation checks to see if there is a cons with the same [car]
and [cdr] as the hons being requested. Thus, the only difference
between the results of a hons call and a corresponding cons call is
a notation in some invisible (to the ACL2 logic) tables where we
record which cons elements are also hons elements. Since a hons is
nothing but a cons, the operation of car and cdr is unchanged. In
fact, the implementation is designed so that at any time it is safe
to clear the table identifying which cons elements are also
considered hons elements.
User-defined functions with defined and verified guards can be
memoized. When a function is memoized, a user-supplied condition
restricts the domain when memoization is attempted. When the
condition is satisfied, memoization is attempted (assuming that
memoization for the function is presently enabled); otherwise, the
function is just evaluated. Each memoized function has a hash table
that is used to keep track of a unique list of function arguments
paired with their values. If appropriate, for each function the
corresponding table is checked to see if a previous call with
exactly the same arguments already exists in the table: if so, then
the associated value is returned; if not, then the function is
evaluated and a new key-value pair is added to the table of
memoized values so that some future call will benefit from the
memoization. With ACL2 user functions memoization can be
dynamically enabled and disabled. There is an ACL2 function that
clears a specific memoization table. And finally, just as with the
hons table, a stack of these function memoization tables is
maintained; that is, it is possible to memoize a function, use it a
bit, set the memoized values aside, start a new table, use it, and
then return to the original table.
We next discuss the fast lookup operation for association lists. When
a pair is added to an association list using the functions
[hons-acons] or [hons-acons!], the system also records the
key-value pair in an associated hash table. As long as a user only
used these two functions when placing key-value pairs on an
association list, the key-value pairs in the corresponding hash
table will be synchronized with the key-value pairs in the
association list. Later, if [hons-get] is used to look up a key,
then instead of performing a linear search of the association list
we consult the associated hash table. If a user does not strictly
follow this discipline, then a linear search may be required. In
some sense, these association lists are much like ACL2 arrays, but
without the burden of explicitly naming the arrays. The ACL2 array
[compress1] function is analogous to the functions
[fast-alist-clean] and [fast-alist-clean!]. There are user-level
ACL2 functions that allow the associated hash tables to be cleared
and removed.
As mentioned above, the [hons-enabled] features are optimized for CCL
and GCL. See [ccl-updates] for easy instructions for obtaining the
latest version of CCL.
REFERENCES
Baker, Henry G., The Boyer Benchmark at Warp Speed. ACM Lisp Pointers
V,3 (Jul-Sep 1992), pages 13-14.
Baker, Henry G., A Tachy 'TAK'. ACM Lisp Pointers Volume 3,
July-September, 1992, pages 22-23.
Robert S. Boyer and Warren A. Hunt, Jr., Function Memoization and
Unique Object Representation for ACL2 Functions, in the Sixth
International Workshop on the ACL2 Theorem Prover and Its
Applications, ACM Digital Library, 2006.
L.P. Deutsch. An Interactive Program Verifier. Tech. Rept. CSL-73-1,
Xerox Palo Alto Research Center, May, 1973.
A. P. Ershov. On Programming of Arithmetic Operations. In the
Communications of the ACM, Volume 118, Number 3, August, 1958,
pages 427-430.
Eiichi Goto, Monocopy and Associative Algorithms in Extended Lisp,
TR-74-03, University of Toyko, 1974.
Richard P. Gabriel. Performance and Evaluation of Lisp Systems. MIT
Press, 1985.
Donald Michie. Memo functions: a Language Feature with Rote Learning
Properties. Technical Report MIP-R-29, Department of Artificial
Intelligence, University of Edinburgh, Scotland, 1967.
Donald Michie. Memo Functions and Machine Learning. In Nature,
Volumne 218, 1968, pages 19-22.
Subtopics
[Ccl-updates]
Updating Clozure Common Lisp (CCL)
[Fast-alists]
Alists with hidden hash tables for faster execution
[Hons]
([hons] x y) returns a [normed] object equal to ([cons] x y).
[Hons-enabled]
Hash cons, function memoization, and applicative hash tables
[Memoize]
Turn on memoization for a specified function
[Number-subtrees]
([number-subtrees] x) returns the number of distinct subtrees of X,
in the sense of [equal]
[Unmemoize]
Turn off memoization for the specified function
[With-stolen-alist]
([with-stolen-alist] name form) ensures that name is a fast alist at
the start of the execution of form. At the end of execution, it
ensures that name is a fast alist if and only if it was
originally. That is, if name was not a fast alist originally,
its hash table link is freed, and if it was a fast alist
originally but its table was modified during the execution of
form, that table is restored. Note that any extended table
created from the original fast alist during form must be
manually freed.")
(HONS-ASSOC-EQUAL
(FAST-ALISTS ACL2-BUILT-INS)
"(hons-assoc-equal key alist) is not fast; it serves as the logical
definition for [hons-get].
The definition of hons-assoc-equal is similar to that of
[assoc-equal], except that (1) it does not require [alistp] as a
guard, and (2) it \"skips over\" any non-conses when its alist
argument is malformed.
We typically leave hons-get enabled and reason about hons-assoc-equal
instead. One benefit of this approach is that it avoids certain
\"false\" discipline warnings that might arise from execution during
theorem proving.
Function: <hons-assoc-equal>
(defun hons-assoc-equal (key alist)
(declare (xargs :guard t))
(cond ((atom alist) nil)
((and (consp (car alist))
(hons-equal key (caar alist)))
(car alist))
(t (hons-assoc-equal key (cdr alist)))))")
(HONS-CLEAR
(HONS ACL2-BUILT-INS)
"(hons-clear gc) is a drastic garbage collection mechanism that clears
out the underlying Hons Space.
Logically, hons-clear just returns nil; we leave it enabled and would
think it odd to ever prove a theorem about it.
Under the hood, hons-clear brutally (1) clears all the tables that
govern which conses are [normed], then (2) optionally garbage
collects, per the gc argument, then finally (3) re-norms the keys
of [fast-alists] and persistently normed conses; see
[hons-copy-persistent].
Notes.
* The hash tables making up the Hons Space retain their sizes after
being cleared. If you want to shrink them, see [hons-resize].
* CCL and GCL users might prefer [hons-wash], which is relatively
efficient and allows for the garbage collection of normed
conses without impacting their normed status.
* It is not recommended to interrupt this function. Doing so may cause
persistently normed conses and fast alist keys to become
un-normed, which might lead to less efficient re-norming and/or
violations of the fast-alist discipline.
* (For ACL2(p) users only; see [parallelism]) If parallel execution is
enabled (see (@see set-parallel-execution)), as it is by
default in ACL2(p), then hons-clear may be a no-op (other than
to print a warning), in order to avoid thread-unsafe behavior.
(However, In CCL you are unlikely to see this restriction
unless you are running more than one thread.) To get around
this restriction, you can instead use [hons-clear!], which
however requires a [trust-tag].
Function: <hons-clear>
(defun hons-clear (gc)
(declare (xargs :guard t))
(declare (ignore gc))
nil)")
(HONS-CLEAR!
(HONS ACL2-BUILT-INS)
"A version of [hons-clear] for [parallel] execution
This function is only of interest to ACL2(p) users; see
[parallelism], because for ACL2 it suffices to use [hons-clear].
However, if parallel execution is enabled (see (@see
set-parallel-execution)), as it is by default in ACL2(p), then
hons-clear may be a no-op (other than to print a warning), in order
to avoid thread-unsafe behavior. If you are not concerned about
thread safety, for example when you want to call hons-clear
directly in the top-level loop, you can use hons-clear!, which does
not check for parallelism violations. However, hons-clear! requires
a trust tag; see [defttag].")
(HONS-COPY
(HONS ACL2-BUILT-INS)
"(hons-copy x) returns a [normed] object that is equal to X.
In the logic, hons-copy is just the identity function; we leave it
enabled and would think it odd to ever prove a theorem about it.
Under the hood, hons-copy does whatever is necessary to produce a
[normed] version of X.
What might this involve?
If X is a symbol, character, or number, then it is already normed and
nothing is done.
If X is a string, we check if any normed version of X already exists.
If so, we return the already-normed version; otherwise, we install
X as the normed version for all strings that are [equal] to X.
If X is a cons, we must determine if there is a normed version of X,
or recursively construct and install one. Norming large cons trees
can become expensive, but there are a couple of cheap cases. In
particular, if X is already normed, or if large subtrees of X are
already normed, then not much needs to be done. The slowest case is
norming some large ACL2 cons structure that has no subtrees which
are already normed.
Note that running hons-copy on an object that was created with [cons]
is often slower than just using [hons] directly when constructing
the object.
Function: <hons-copy>
(defun hons-copy (x)
(declare (xargs :guard t))
x)")
(HONS-COPY-PERSISTENT
(HONS ACL2-BUILT-INS)
"(hons-copy-persistent x) returns a [normed] object that is equal to X
and which will be re-normed after any calls to [hons-clear].
Logically hons-copy-persistent is the identity; we leave it enabled
and would think it odd to ever prove a theorem about it.
Under the hood, hons-copy-persistent is virtually identical to
[hons-copy].
The only difference is that when [hons-clear] is used, any
persistently normed conses are automatically re-normed, and this
re-norming can be carried out more efficiently than, say, an
ordinary [hons-copy].
Function: <hons-copy-persistent>
(defun hons-copy-persistent (x)
(declare (xargs :guard t))
x)")
(HONS-ENABLED
(HONS-AND-MEMOIZATION)
"Hash cons, function memoization, and applicative hash tables
ACL2 supports hash cons, function memoization, and applicative hash
tables; see [hons-and-memoization]. These are sometimes called the
``hons-enabled features'' of ACL2.")
(HONS-EQUAL
(HONS EQUAL ACL2-BUILT-INS)
"(hons-equal x y) is a recursive equality check that optimizes when
parts of its arguments are [normed].
In the logic, hons-equal is just [equal]; we leave it enabled and
would think it odd to ever prove a theorem about it.
Under the hood, when hons-equal encounters two arguments that are
both normed, it becomes a mere [eql] check, and hence avoids the
overhead of recursively checking large cons structures for
equality.
Note. If hons-equal is given arguments that do not contain many
normed objects, it can actually be much slower than [equal]! This
is because it checks to see whether its arguments are normed at
each recursive step, and so you are repeatedly paying the price of
such checks. Also see [hons-equal-lite], which only checks at the
top level whether its arguments are normed.
Function: <hons-equal>
(defun hons-equal (x y)
(declare (xargs :guard t))
(equal x y))
Subtopics
[Hons-equal-lite]
([hons-equal-lite] x y) is a non-recursive equality check that
optimizes if its arguments are [normed].")
(HONS-EQUAL-LITE
(HONS HONS-EQUAL)
"(hons-equal-lite x y) is a non-recursive equality check that
optimizes if its arguments are [normed].
In the logic, hons-equal-lite is just [equal]; we leave it enabled
and would think it odd to ever prove a theorem about it.
Under the hood, hons-equal-lite checks whether its arguments are
normed, and if so it effectively becomes a [eql] check. Otherwise,
it immediately calls [equal] to determine if its arguments are
equal.
The idea here is to strike a useful balance between equal and
[hons-equal]. If both arguments happen to be normed, we get to use
a very fast equality comparison. Otherwise, we just get out of the
way and let equal do its work, without the extra overhead of
recursively checking whether the subtrees of x and y are normed.
Function: <hons-equal-lite>
(defun hons-equal-lite (x y)
(declare (xargs :guard t))
(equal x y))")
(HONS-GET
(FAST-ALISTS ACL2-BUILT-INS)
"(hons-get key alist) is the efficient lookup operation for
[fast-alists].
Logically, hons-get is just an alias for [hons-assoc-equal]; we
typically leave it enabled and prefer to reason about
hons-assoc-equal instead. One benefit of this approach is that it
helps to avoids \"false\" discipline warnings that might arise from
execution during theorem proving.
Under the hood, when alist is a fast alist that is associated with a
valid hash table, hons-get first norms key using [hons-copy], then
becomes a gethash operation on the hidden hash table.
Function: <hons-get>
(defun hons-get (key alist)
(declare (xargs :guard t))
(hons-assoc-equal key alist))")
(HONS-NOTE
(HONS)
"Notes about [hons], especially pertaining to expensive resizing
operations
Certain ``Hons-Notes'' are printed to the terminal to report
implementation-level information about the management of [hons]
structures. Some of these may be low-level and of interest mainly
to system developers. But below we discuss what users can learn
from a particular hons-note, ``ADDR-LIMIT reached''. In short: If
you are seeing a lot of such hons-notes, then you may be using a
lot of memory. (Maybe you can reduce that memory; for certain BDD
operations, for example (as defined in community books
books/centaur/ubdds/), variable ordering can make a big
difference.)
By way of background:
The ADDR-HT is the main hash table that lets us look up [normed]
conses, i.e., [hons]es. It is an ordinary Common Lisp hash
table, so when it starts to get too full the Lisp will grow it.
It can get really big. (It has been seen to take more than 10
GB of memory just for the hash table's array, not to mention
the actual conses!)
Hons-Notes may be printed when the ADDR-HT is getting really full.
This growth can be expensive and can lead to memory problems.
Think about what it takes to resize a hash table:
(1) allocate a new, bigger array
(2) rehash elements, copying them into the new array
(3) free the old array
Until you reach step (3) and a garbage collection takes place, you
have to have enough memory to have both the old and new arrays
allocated. If the old array was 10 GB and we want to allocate a
new one that's 15 GB, this can get pretty bad. Also, rehashing
the elements is expensive time-wise when there are lots of
elements.
Since resizing a hash table is expensive, we want to avoid it.
There's a [hons-resize] command for this. You may want your
books to start with something like the following.
(value-triple (set-max-mem (* 30 (expt 2 30)))) ; 30 GB heap
(value-triple (hons-resize :addr-ht #u_100_000_000)) ; 100M honses
Basically, if you roughly know how many honses your book will need,
you can just get them up front and then never to resize.
The Hons-Notes about ``ADDR-LIMIT reached'' are basically there to
warn you that the ADDR-HT is being resized. This can help you
realize that your [hons-resize] command had too small of an ADDR-HT
size, or might suggest that your book should have a [hons-resize]
command. There are also commands like ([hons-summary]),
[set-max-mem], and defined in community book
books/centaur/misc/memory-mgmt-logic.lisp, (hons-analyze-memory
nil). These can show you how many honses you currently have, how
much space they are taking, and that sort of thing. (A nice trick
is to call [hons-summary] at the end of a book, to get an idea of
how many honses you should ask for in your [hons-resize] command).")
(HONS-RESIZE
(HONS ACL2-BUILT-INS)
"(hons-resize ...) can be used to manually adjust the sizes of the
hash tables that govern which ACL2 Objects are considered [normed].
General form:
(hons-resize [:str-ht size]
[:nil-ht size]
[:cdr-ht size]
[:cdr-ht-eql size]
[:addr-ht size]
[:other-ht size]
[:sbits size]
[:fal-ht size]
[:persist-ht size])
Example:
(hons-resize :str-ht 100000
:addr-ht (expt 2 27))
Logically, hons-resize just returns nil; we leave it enabled and
would think it odd to ever prove a theorem about it.
Under the hood, hons-resize can be used to change the sizes of
certain hash tables in the Hons Space.
All arguments are optional. The size given to each argument should
either be nil (the default) or a natural number. A natural number
indicates the newly desired size for the hash table, whereas nil
means \"don't resize this table.\" Any non-natural argument is
regarded as nil.
You may wish to call this function for two reasons.
1. Improving Performance by Resizing Up
Since the hash tables in the Hons Space automatically grow as new
objects are normed, hons-resize is unnecessary. But automatic
growth can be slow because it is incremental: a particular hash
table might be grown dozens of times over the course of your
application. Using hons-resize to pick a more appropriate initial
size may help to reduce this overhead.
2. Reducing Memory Usage by Resizing Down
Resizing can also be used to shrink the hash tables. This might
possibly be useful immediately after a [hons-clear] to free up
memory taken by the hash tables themselves. (Of course, the tables
will grow again as you create new normed objects.)
Advice for using hons-resize.
Note that hash tables that are already close to the desired size, or
which have too many elements to fit into the desired size, will not
actually be resized. This makes resizing relatively \"safe.\"
Note that the [hons-summary] function can be used to see how large
and how full your hash tables are. This may be useful in deciding
what sizes you want to give to hons-resize.
Note that hons-resize operates by (1) allocating new hash tables,
then (2) copying everything from the old hash table into the new
table. Because of this, for best performance you should ideally
call it when the hash tables involved are minimally populated,
i.e., at the start of your application, or soon after a
[hons-clear].")
(HONS-SHRINK-ALIST
(FAST-ALIST-FORK ACL2-BUILT-INS)
"Deprecated feature
Deprecated. Alias for [fast-alist-fork].")
(HONS-SHRINK-ALIST!
(FAST-ALIST-FORK! ACL2-BUILT-INS)
"Deprecated feature
Deprecated. Alias for [fast-alist-fork!].")
(HONS-SUMMARY
(HONS ACL2-BUILT-INS)
"(hons-summary) prints basic information about the sizes of the tables
in the current Hons Space.
Logically, hons-summary just returns nil; we leave it enabled and
would think it odd to ever prove a theorem about it.
Under the hood, this function gathers and prints some basic
information about the sizes of the tables in the Hons Space.
This information may be useful for deciding if you want to garbage
collect using functions such as [hons-clear] or [hons-wash]. It may
also be useful for determining good initial sizes for the Hons
Space hash tables for your particular computation; see
[hons-resize]. For information about [fast-alists], see
[fast-alist-summary].
Function: <hons-summary>
(defun hons-summary
nil (declare (xargs :guard t))
nil)")
(HONS-WASH
(HONS ACL2-BUILT-INS)
"(hons-wash) is like [gc$] but can also garbage collect [normed]
objects (CCL and GCL Only).
Logically, hons-wash just returns nil; we leave it enabled and would
think it odd to ever prove a theorem about it.
Under the hood, in CCL and GCL, hons-wash runs a garbage collection
after taking special measures to allow normed conses to be
collected. In Lisps other than CCL, hons-wash does nothing. This is
because the efficient implementation of hons-wash is specific to
the \"static honsing\" scheme which requires CCL-specific features.
Why is this function needed? Ordinarily, it is not possible to
garbage collect any normed conses. This is because the Hons Space
includes pointers to any normed conses, and hence Lisp's garbage
collector thinks these objects are live. To correct for this,
hons-wash (1) clears out these pointers, (2) runs a garbage
collection, then (3) re-norms any previously-normed conses which
have survived the garbage collection.
Notes.
* It is not recommended to interrupt this function. Doing so may cause
persistently normed conses and fast alist keys to become
un-normed, which might lead to less efficient re-norming and/or
violations of the fast-alist discipline.
* (For ACL2(p) users only; see [parallelism]) If parallel execution is
enabled (see (@see set-parallel-execution)), as it is by
default in ACL2(p), then hons-wash may be a no-op (other than
to print a warning), in order to avoid thread-unsafe behavior.
(However, In CCL you are unlikely to see this restriction
unless you are running more than one thread.) To get around
this restriction, you can instead use [hons-wash!], which
however requires a [trust-tag].
Function: <hons-wash>
(defun hons-wash nil (declare (xargs :guard t))
nil)")
(HONS-WASH!
(HONS ACL2-BUILT-INS)
"A version of [hons-wash] for [parallel] execution
This function is only of interest to ACL2(p) users; see
[parallelism], because for ACL2 it suffices to use [hons-wash].
However, if parallel execution is enabled (see (@see
set-parallel-execution)), as it is by default in ACL2(p), then
hons-wash may be a no-op (other than to print a warning), in order
to avoid thread-unsafe behavior. If you are not concerned about
thread safety, for example when you want to call hons-wash directly
in the top-level loop, you can use hons-wash!, which does not check
for parallelism violations. However, hons-wash! requires a trust
tag; see [defttag].")
(HOW_LONG_DOES_IT_TAKE_TO_BECOME_AN_EFFECTIVE_USER{Q}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"How Long Does It Take to Become an Effective User?
[{IMAGE}]
We expect that a talented undergraduate majoring in computer science
(or perhaps mathematics) will probably take several weeks to become
an effective ACL2 user. The time will depend, of course, on that
student's familiarity with logic (or formal methods) and Lisp
programming, as well as willingness to read and study the ACL2
User's Manual.
Of course, it is critical to do some projects in order to gain
proficiency. (Hence access to an ACL2 implementation is also a
requirement, for example by downloading and installing following
links from the ACL2 home page.) But it is critical to start with
``toy'' projects before tackling a ``grand challenge.''
[{IMAGE}]")
(HOW_TO_FIND_OUT_ABOUT_ACL2_FUNCTIONS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"How To Find Out about ACL2 Functions
[{IMAGE}]
Most ACL2 primitives are documented. Here is the definition of app
again, with the documented topics highlighted. [{ICON}] All of the
links below lead into the ACL2 User's Manual. So follow these links
if you wish, but use your Back Button to return here!
([defun] app (x y)
([cond] (([endp] x) y)
(t ([cons] ([car] x)
(app ([cdr] x) y)))))
By following the link on [endp] [{ICON}] we see that it is a Common
Lisp function and is defined to be the same as [atom] [{ICON}],
which recognizes non-conses. But endp has a guard. Since we are
ignorning guards for now, we'll ignore the guard issue on endp.
So this definition reads ``to app x and y: if x is an atom, return y;
otherwise, app (cdr x) and y and then cons (car x) onto that.''
[{IMAGE}]")
(HOW_TO_FIND_OUT_ABOUT_ACL2_FUNCTIONS_{CONT}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"How To Find Out about ACL2 Functions (cont)
[{IMAGE}]
You can always use the Index [{ICON}] icon below to find the
documentation of functions. Try it. Click on the Index icon below.
Then use the Find command of your browser to find ``endp'' in that
document and follow the link. But remember to come back here.
The ACL2 documentation is also available in Emacs, via the ACL2-Doc
browser (see [ACL2-Doc]) [{ICON}], allowing you to explore the
hyperlinked documentation in the comfort of a text editor that can
also interact with ACL2.
In addition, runtime images of ACL2 have the hyperlinked text as a
large ACL2 data structure that can be explored with ACL2's :doc
command. If you have ACL2 running, try the command :doc endp.
Another way to find out about ACL2 functions, if you have an ACL2
image available, is to use the command :[args] [{ICON}] which
prints the formals, type, and guard of a function symbol.
Of course, the ACL2 documentation can also be printed out as a very
long book but we do not recommend that! See the ACL2 Home Page to
download the Postscript.
Now let's continue with app.
[{IMAGE}]")
(I-AM-HERE
(LD)
"A convenient marker for use with [rebuild] or [ld]
Example Input File for Rebuild:
(defun fn1 (x y) ...)
(defthm lemma1 ...)
(defthm lemma2 ...)
(i-am-here)
The following lemma won't go through. I started
typing the hint but realized I need to prove a
lemma first. See the failed proof attempt in foo.bar.
I'm going to quit for the night now and resume tomorrow
from home.
(defthm lemma3 ...
:hints ((\"Goal\" :use (:instance ???
...
By putting an (i-am-here) form at the ``frontier'' of an evolving
file of [command]s, you can use [rebuild] to load the file up to
the (i-am-here). I-am-here simply returns an [error-triple] that
indicates an error, and any form that ``causes an error'' will do
the same job. Note that the text of the file after the (i-am-here)
need not be machine readable.")
(I-CLOSE
(REAL)
"ACL2(r) test for whether two numbers are infinitesimally close
(I-close x y) is true if and only if x-y is an infinitesimal number.
This predicate is only defined in ACL2(r) (see [real]).")
(I-LARGE
(REAL)
"ACL2(r) recognizer for infinitely large numbers
(I-large x) is true if and only if x is non-zero and 1/x is an
infinitesimal number. This predicate is only defined in ACL2(r)
(see [real]).")
(I-LIMITED
(REAL)
"ACL2(r) recognizer for limited numbers
(I-limited x) is true if and only if x is a number that is not
infinitely large. This predicate is only defined in ACL2(r) (see
[real]).")
(I-SMALL
(REAL)
"ACL2(r) recognizer for infinitesimal numbers
(I-small x) is true if and only if x is an infinitesimal number
(possibly 0). This predicate is only defined in ACL2(r) (see
[real]).")
(IDENTITY
(BASICS ACL2-BUILT-INS)
"The identity function
(Identity x) equals x; what else can we say?
Identity is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <identity>
(defun identity (x)
(declare (xargs :guard t))
x)")
(IF
(BASICS ACL2-BUILT-INS)
"If-then-else function
(if x y z) is equal to y if x is any value other than nil, and is
equal to z if x is nil.
Only one of y, z is evaluated when (if x y z) is evaluated.
If has a [guard] of t.
If is part of Common Lisp. See any Common Lisp documentation for more
information.")
(IF*
(BDD)
"For conditional rewriting with BDDs
The function IF* is defined to be [if], but it is used in a special
way by ACL2's [bdd] package.
Function: <if*>
(defun if* (x y z) (if x y z))
As explained elsewhere (see [bdd-algorithm]), ACL2's [bdd] algorithm
gives special treatment to [term]s of the form (IF* TEST TBR FBR).
In such cases, the algorithm simplifies TEST first, and the result
of that simplification must be a constant (normally t or nil, but
any non-nil explicit value is treated like t here). Otherwise, the
algorithm aborts.
Thus, IF* may be used to implement a sort of conditional rewriting
for ACL2's [bdd] package, even though this package only nominally
supports unconditional rewriting. The following contrived example
should make this point clear.
Suppose that we want to prove that (nthcdr (length x) (append x y))
is equal to y, but that we would be happy to prove this only for
lists having length 4. We can state such a theorem as follows.
(let ((x (list x0 x1 x2 x3)))
(equal (nthcdr (length x) (append x y))
y))
If we want to prove this formula with a :[bdd] hint, then we need to
have appropriate rewrite rules around. First, note that LENGTH is
defined as follows (try :[pe] [length]):
(length x)
=
(if (stringp x)
(len (coerce x 'list))
(len x))
Since [bdd]-based rewriting is merely very simple unconditional
rewriting (see [bdd-algorithm]), we expect to have to prove a rule
reducing [stringp] of a [cons]:
(defthm stringp-cons
(equal (stringp (cons x y))
nil))
Now we need a rule to compute the LEN of X, because the definition of
LEN is recursive and hence not used by the [bdd] package.
(defthm len-cons
(equal (len (cons a x))
(1+ (len x))))
We imagine this rule simplifying (LEN (LIST X0 X1 X2 X3)) in terms of
(LEN (LIST X1 X2 X3)), and so on, and then finally (LEN nil) should
be computed by execution (see [bdd-algorithm]).
We also need to imagine simplifying (APPEND X Y), where still X is
bound to (LIST X0 X1 X2 X3). The following two rules suffice for
this purpose (but are needed, since [append], actually
[binary-append], is recursive).
(defthm append-cons
(equal (append (cons a x) y)
(cons a (append x y))))
(defthm append-nil
(equal (append nil x)
x))
Finally, we imagine needing to simplify calls of [nthcdr], where the
first argument is a number (initially, the length of (LIST X0 X1 X2
X3), which is 4). The second lemma below is the traditional way to
accomplish that goal (when not using BDDs), by proving a
conditional rewrite rule. (The first lemma is only proved in order
to assist in the proof of the second lemma.)
(defthm fold-constants-in-+
(implies (and (syntaxp (quotep x))
(syntaxp (quotep y)))
(equal (+ x y z)
(+ (+ x y) z))))
(defthm nthcdr-add1-conditional
(implies (not (zp (1+ n)))
(equal (nthcdr (1+ n) x)
(nthcdr n (cdr x)))))
The problem with this rule is that its hypothesis makes it a
conditional [rewrite] rule, and conditional rewrite rules are not
used by the [bdd] package. (See [bdd-algorithm] for a discussion of
``BDD rules.'') (Note that the hypothesis cannot simply be removed;
the resulting formula would be false for n = -1 and x = '(a), for
example.) We can solve this problem by using IF*, as follows;
comments follow.
(defthm nthcdr-add1
(equal (nthcdr (+ 1 n) x)
(if* (zp (1+ n))
x
(nthcdr n (cdr x)))))
How is nthcdr-add1 applied by the [bdd] package? Suppose that the
[bdd] computation encounters a [term] of the form (NTHCDR (+ 1 N)
X). Then the [bdd] package will apply the [rewrite] rule
nthcdr-add1. The first thing it will do when attempting to simplify
the right hand side of that rule is to attempt to simplify the term
(ZP (1+ N)). If N is an explicit number (which is the case in the
scenario we envision), this test will reduce (assuming the
executable counterparts of [zp] and [binary-+] are [enable]d) to t
or to nil. In fact, the lemmas above (not including the lemma
nthcdr-add1-conditional) suffice to prove our goal:
(thm (let ((x (list x0 x1 x2 x3)))
(equal (nthcdr (length x) (append x y))
y))
:hints ((\"Goal\" :bdd (:vars nil))))
If we execute the following form that disables the definition and
executable counterpart of the function [zp]
(in-theory (disable zp (zp)))
before attempting the proof of the theorem above, we can see more
clearly the point of using IF*. In this case, the prover makes the
following report.
ACL2 Error in ( THM ...): Unable to resolve test of IF* for term
(IF* (ZP (+ 1 N)) X (NTHCDR N (CDR X)))
under the bindings
((X (CONS X0 (CONS X1 (CONS X2 #)))) (N '3))
-- use SHOW-BDD to see a backtrace.
If we follow the advice above, we can see rather clearly what
happened. See [show-bdd].
ACL2 !>(show-bdd)
BDD computation on Goal yielded 21 nodes.
------------------------------
BDD computation was aborted on Goal, and hence there is no
falsifying assignment that can be constructed. Here is a backtrace
of calls, starting with the top-level call and ending with the one
that led to the abort. See :DOC show-bdd.
(LET ((X (LIST X0 X1 X2 X3)))
(EQUAL (NTHCDR (LENGTH X) (APPEND X Y)) Y))
alist: ((Y Y) (X3 X3) (X2 X2) (X1 X1) (X0 X0))
(NTHCDR (LENGTH X) (APPEND X Y))
alist: ((X (LIST X0 X1 X2 X3)) (Y Y))
(IF* (ZP (+ 1 N)) X (NTHCDR N (CDR X)))
alist: ((X (LIST* X0 X1 X2 X3 Y)) (N 3))
ACL2 !>
Each of these term-alist pairs led to the next, and the test of the
last one, namely (ZP (+ 1 N)) where N is bound to 3, was not
simplified to t or to nil.
What would have happened if we had used [if] in place of IF* in the
rule nthcdr-add1? In that case, if ZP and its executable
counterpart were disabled then we would be put into an infinite
loop! For, each time a term of the form (NTHCDR k V) is encountered
by the BDD package (where k is an explicit number), it will be
rewritten in terms of (NTHCDR k-1 (CDR V)). We would prefer that if
for some reason the term (ZP (+ 1 N)) cannot be decided to be t or
to be nil, then the BDD computation should simply abort.
Even if there were no infinite loop, this kind of use of IF* is
useful in order to provide feedback of the form shown above
whenever the test of an IF term fails to simplify to t or to nil.")
(IF-INTRO (POINTERS) "See [splitter].")
(IFF
(BASICS ACL2-BUILT-INS)
"Logical ``if and only if''
Iff is the ACL2 biconditional, ``if and only if''. (iff P Q) means
that either P and Q are both false (i.e., nil) or both true (i.e.,
not nil).
Function: <iff>
(defun iff (p q)
(declare (xargs :guard t))
(if p (if q t nil) (if q nil t)))")
(IFIX
(NUMBERS ACL2-BUILT-INS)
"Coerce to an integer
Ifix simply returns any integer argument unchanged, returning 0 on a
non-integer argument. Also see [nfix], see [rfix], see [realfix]
and see [fix] for analogous functions that coerce to a natural
number, a rational number, a real, and a number, respectively.
Ifix has a [guard] of t.
Function: <ifix>
(defun ifix (x)
(declare (xargs :guard t))
(if (integerp x) x 0))")
(IGNORABLE (POINTERS) "See [declare].")
(IGNORE (POINTERS) "See [declare].")
(IGNORED-ATTACHMENT
(DEFATTACH)
"Why attachments are sometimes not used
Attachments provide a way to execute constrained functions. But in
some cases, ACL2 will not permit such execution. We discuss this
issue briefly here. For more information about attachments, see
[defattach].
We illustrate this issue with the following example, discussed below.
(encapsulate
()
(defstub foo () t)
(defn foo-impl-1 () t)
(defattach foo foo-impl-1)
(defn foo-impl-2 () nil)
(local (defattach foo foo-impl-2))
(defmacro mac () (foo)) ; nil in the first pass, t in the second pass
(defun bar () (mac)) ; nil in the first pass, t in the second pass
(defthm bar-is-nil
(equal (bar) nil))
)
Here, a non-executable function foo is introduced with no
constraints, and is provided two contradictory implementations,
foo-impl-1 and foo-impl-2. A function, bar, is defined using a
macro, mac, whose expansion depends on which of foo-impl-1 or
foo-impl-2 is attached to foo. If ACL2 were to allow this, then as
indicated by the comments above, (bar) would be defined to be nil
on the first pass of the [encapsulate] form, where foo is attached
to foo-impl-2; but (bar) would be defined to be t on the second
pass, where foo is attached to foo-impl-1 because the second
[defattach] call is [local]. Thus, after execution of the
encapsulate form, (bar) would be provably equal to t even though
there would be a theorem, bar-is-nil --- proved during the first
pass of the encapsulate --- saying that (bar) is nil!
Fortunately, ACL2 does not permit this to happen. The example above
produces the following output.
ACL2 !>>(DEFUN BAR NIL (MAC))
ACL2 Error in ( DEFUN BAR ...): In the attempt to macroexpand the
form (MAC), evaluation of the macro body caused the following error:
ACL2 cannot ev the call of undefined function FOO on argument list:
NIL
Note that because of logical considerations, attachments (including
FOO-IMPL-2) must not be called in this context.
We see, then, the importance of disallowing evaluation using
attachments during macroexpansion. ACL2 is careful to avoid
attachments in situations, like this one, where using attachments
could be unsound.
We conclude with an example illustrating how [make-event] can be used
to work around the refusal of ACL2 to use attachments during
macroexpansion. The idea is that [make-event] expansions are
stored, and this avoids the issue of [local] attachments. In
particular, for the example below, the second [defattach] affects
the body of f2 even though that [defattach] is [local], because the
expansion of the corresponding [make-event] is saved during the
first pass of [certify-book], when full admissibility checks are
done. Then even after including the book, the definition of f2 will
be based on the second ([local]) [defattach] form below.
(in-package \"ACL2\")
(defun body-1 (name formals body)
(declare (ignore name))
`(if (consp ,(car formals))
,body
nil))
(defun body-2 (name formals body)
(declare (ignore name))
`(if (acl2-numberp ,(car formals))
,body
t))
(defmacro defun+ (name formals body)
`(make-event
(if (foo) ; attachable stub
'(defun ,name ,formals ,(body-1 name formals body))
'(defun ,name ,formals ,(body-2 name formals body)))))
;;; (defun+ f1 (x y) (cons x y)) ; fails because foo has no attachment
(defstub foo () t)
(defn foo-true () t)
(defn foo-false () nil)
(defattach foo foo-true)
(defun+ f1 (x y) (cons x y))
(local (defattach foo foo-false))
(defun+ f2 (x y) (cons x y))
(assert-event (equal (f1 3 t) nil))
(assert-event (equal (f2 3 t) (cons 3 t)))")
(ILLEGAL
(ERRORS ACL2-BUILT-INS)
"Print an error message and stop execution
(Illegal ctx str alist) causes evaluation to halt with a short
message using the ``context'' ctx. An error message is first
printed using the string str and alist alist that are of the same
kind as expected by [fmt]. See [fmt], and see [prog2$] for an
example of how to use a related function, [hard-error] (see
[hard-error]). Also see [er] for a macro that provides a unified
way of signaling errors.
The difference between illegal and [hard-error] is that the former
has a guard of nil while the latter has a [guard] of t. Thus, you
may want to use illegal rather than hard-error when you intend to
do [guard] verification at some point, and you expect the guard to
guarantee that the illegal call is never executed. See [prog2$] for
an example.
Technical note for raw Lisp programmers only: It is possible to cause
hard errors to signal actual raw Lisp errors. See [hard-error].
Function: <illegal>
(defun illegal (ctx str alist)
(declare (xargs :guard (hard-error ctx str alist)))
(hard-error ctx str alist))")
(IMAGPART
(NUMBERS ACL2-BUILT-INS)
"Imaginary part of a complex number
Completion Axiom (completion-of-imagpart):
(equal (imagpart x)
(if (acl2-numberp x)
(imagpart x)
0))
[Guard] for (imagpart x):
(acl2-numberp x)")
(IMMED-FORCED (POINTERS)
"See [splitter].")
(IMMEDIATE-FORCE-MODEP
(FORCE)
"When executable counterpart is [enable]d, [force]d hypotheses are
attacked immediately
Also see [disable-immediate-force-modep] and see
[enable-immediate-force-modep].
This function symbol is defined simply to provide a [rune] which can
be [enable]d and [disable]d. Enabling
(:executable-counterpart immediate-force-modep)
causes ACL2 to attack [force]d hypotheses immediately instead of
delaying them to the next forcing round.
Example Hints
:in-theory (disable (:executable-counterpart immediate-force-modep))
; delay forced hyps to forcing round
:in-theory (enable (:executable-counterpart immediate-force-modep))
; split on forced hyps immediately
See [force] for background information. When a [force]d hypothesis
cannot be established a record is made of that fact and the proof
continues. When the proof succeeds a ``forcing round'' is
undertaken in which the system attempts to prove each of the
[force]d hypotheses explicitly. However, if the [rune]
(:executable-counterpart immediate-force-modep) is [enable]d at the
time the hypothesis is [force]d, then ACL2 does not delay the
attempt to prove that hypothesis but undertakes the attempt more or
less immediately.")
(IMPLIES
(BASICS ACL2-BUILT-INS)
"Logical implication
Implies is the ACL2 implication function. (implies P Q) means that
either P is false (i.e., nil) or Q is true (i.e., not nil).
Function: <implies>
(defun implies (p q)
(declare (xargs :guard t))
(if p (if q t nil) t))")
(IMPROPER-CONSP
(LISTS ACL2-BUILT-INS)
"Recognizer for improper (non-null-terminated) non-empty lists
Improper-consp is the function that checks whether its argument is a
non-empty list that ends in other than nil. See [proper-consp] and
also see [true-listp].
Function: <improper-consp>
(defun improper-consp (x)
(declare (xargs :guard t))
(and (consp x) (not (true-listp x))))")
(IN-ARITHMETIC-THEORY
(EVENTS)
"Designate theory for some rewriting done for non-linear arithmetic
We assume familiarity with [theories]; in particular, see [in-theory]
for the normal way to set the current theory. Here, we discuss an
analogous event that pertains only to non-linear arithmetic (see
[non-linear-arithmetic]).
Example:
(in-arithmetic-theory '(lemma1 lemma2))
General Form:
(in-arithmetic-theory term)
where term is a term that when evaluated will produce a theory (see
[theories]). Except for the variable [world], term must contain no
free variables. Term is evaluated with the variable [world] bound
to the current [world] to obtain a theory and the corresponding
runic theory (see [theories]) is then used by non-linear arithmetic
(see [non-linear-arithmetic]).
Warning: If term involves macros such as [enable] and [disable] you
will probably not get what you expect! Those macros are defined
relative to the [current-theory]. But in this context you might
wish they were defined in terms of the
``CURRENT-ARITHMETIC-THEORY'' which is not actually a defined
function. We do not anticipate that users will repeatedly modify
the arithmetic theory. We expect term most often to be a constant
list of runes and so have not provided ``arithmetic theory
manipulation functions'' analogous to [current-theory] and
[enable].
See [non-linear-arithmetic].")
(IN-PACKAGE
(PACKAGES ACL2-BUILT-INS)
"Select current package
Example:
(in-package \"MY-PKG\")
General Form:
(in-package str)
where str is a string that names an existing ACL2 package, i.e., one
of the initial packages such as \"KEYWORD\" or \"ACL2\" or a package
introduced with [defpkg]. For a complete list of the known packages
created with [defpkg], evaluate
(strip-cars (known-package-alist state)).
See [defpkg]. An ACL2 book (see [books]) must contain a single
in-package form, which must be the first form in that book.")
(IN-TAU-INTERVALP
(TAU-SYSTEM ACL2-BUILT-INS)
"Boolean membership in a tau interval
General Form:
(in-tau-intervalp e x)
Here, x should be an interval (see [tau-intervalp]). This function
returns t or nil indicating whether e, which is generally but not
necessarily a number, is an element of interval x. By that is meant
that e satisfies the domain predicate of the interval and lies
between the two bounds.
Suppose x is an interval with the components dom, lo-rel, lo, hi-rel
and hi. Suppose (<? rel u v) means (< u v) when rel is true and (<=
u v) otherwise, with appropriate treatment of infinities.
Then for e to be in interval x, it must be the case that e satisfies
the domain predicate dom (where where dom=nil means there is no
restriction on the domain) and (<? lo-rel lo e) and (<? hi-rel e
hi). [Note: ``Appropriate treatment of infinities'' is slightly
awkward if both infinities are represented by the same object, nil.
However, this is handled by coercing e to a number after checking
that it is in the domain. By this trick, ``<?'' is presented with
at most one ``infinity'' and it is always negative when in the
first argument and positive when in the second.]
Note that every element in an INTEGERP interval is contained in the
analogous RATIONALP interval (i.e., the interval obtained by just
replacing the domain INTEGERP by RATIONALP). That is because every
integer is a rational. Similarly, every rational is an ACL2 number.
Note that an interval in which the relations are weak and the bounds
are equal rationals is the ``unit'' or ``identity'' interval
containing exactly that rational.
Note that an interval in which the relations are strong and the
bounds are equal rationals is empty: it contains no objects.
Note that the interval (make-tau-interval nil nil nil nil nil) is the
``universal interval:'' it contains all ACL2 objects. It contains
all numbers because they statisfy the non-existent domain
restriction and lie between minus infinity and plus infinity. It
contains all non-numbers because the interval contains 0 and ACL2's
inequalities coerce non-numbers to 0. The universal interval is
useful if you are defining a bounder (see [bounders]) for a
function and do not wish to address a certain case: return the
universal interval.
Recall that [make-tau-interval] constructs intervals. Using
make-tau-interval we give several self-explanatory examples of
in-tau-intervalp:
(in-tau-intervalp 3 (make-tau-interval 'INTEGERP nil 0 nil 10)) = t
(in-tau-intervalp 3 (make-tau-interval 'RATIONALP nil 0 nil 10)) = t
(in-tau-intervalp 3 (make-tau-interval NIL nil 0 nil 10)) = t
(in-tau-intervalp -3 (make-tau-interval 'INTEGERP nil 0 nil 10)) = nil
(in-tau-intervalp 30 (make-tau-interval 'INTEGERP nil 0 nil 10)) = nil
(in-tau-intervalp 3/5 (make-tau-interval 'INTEGERP nil 0 nil 10)) = nil
(in-tau-intervalp 3/5 (make-tau-interval 'RATIONALP nil 0 nil 10)) = t
(in-tau-intervalp #c(3 5) (make-tau-interval 'RATIONALP nil 0 nil 10)) = nil
(in-tau-intervalp #c(3 5) (make-tau-interval 'ACL2-NUMBERP nil 0 nil 10)) = t
(in-tau-intervalp 'ABC (make-tau-interval NIL nil 0 nil 10)) = t")
(IN-THEORY
(EVENTS THEORIES)
"Designate ``current'' theory (enabling its rules)
Example:
(in-theory (set-difference-theories
(universal-theory :here)
'(flatten (:executable-counterpart flatten))))
General Form:
(in-theory term)
where term is a term that when evaluated will produce a theory (see
[theories]).
Except for the variable [world], term must contain no free variables.
Term is evaluated with the variable [world] bound to the current
[world] to obtain a theory and the corresponding runic theory (see
[theories]) is then made the current theory. Thus, immediately
after the in-theory, a rule is [enable]d iff its rule name is a
member of the runic interpretation (see [theories]) of some member
of the value of term. See [theory-functions] for a list of the
commonly used theory manipulation functions.
Note that it is often useful to surround in-theory [events] with
local, that is, to use (local (in-theory ...)). This use of [local]
in [encapsulate] events and [books] will prevent the effect of this
theory change from being exported outside the context of that
encapsulate or book.
Also see [hints] for a discussion of the :in-theory hint, including
some explanation of the important point that an :in-theory hint
will always be evaluated relative to the current ACL2 logical
[world], not relative to the theory of a previous goal.
[In-theory] returns an [error-triple]. When the return is without
error, the value is of the form (mv nil (:NUMBER-OF-ENABLED-RUNES
k) state) where k is the length of the new current theory. This
value of k is what is printed when an in-theory event evaluates
without error at the top level.")
(INCLUDE-BOOK
(BOOKS-REFERENCE BOOKS-TOUR EVENTS)
"Load the [events] in a file
Examples:
(include-book \"my-arith\")
(include-book \"/home/smith/my-arith\")
(include-book \"/../../my-arith\")
General Form:
(include-book file :load-compiled-file action
:uncertified-okp t/nil/:ignore-certs ; [default t]
:defaxioms-okp t/nil ; [default t]
:skip-proofs-okp t/nil ; [default t]
:ttags ttags ; [default nil]
:dir directory)
where file is a book name. See [books] for general information, see
[book-name] for information about book names, and see [pathname]
for information about file names. Action is one of t, nil,
:default, :warn, or :comp; these values are explained below, and
the default is :default. The three -okp keyword arguments, which
default to t, determine whether errors or warnings are generated
under certain conditions explained below; when the argument is t,
warnings are generated. The dir argument, if supplied, is a keyword
that represents an absolute pathname for a directory (see
[pathname]), to be used instead of the current book directory (see
[cbd]) for resolving the given file argument to an absolute
pathname. In particular, by default :dir :system resolves file
using the books/ directory of your ACL2 installation, unless your
ACL2 executable was built somewhere other than where it currently
resides; please see the ``Books Directory'' below. To define other
keywords that can be used for dir, see [add-include-book-dir]. If
the book has no [certificate], if its [certificate] is invalid or
if the certificate was produced by a different [version] of ACL2, a
warning is printed and the book is included anyway; see
[certificate]. This can lead to serious errors, perhaps mitigated
by the presence of a .port file from an earlier certification; see
[uncertified-books]. If the portcullis of the [certificate] (see
[portcullis]) cannot be raised in the host logical [world], an
error is caused and no change occurs to the logic. Otherwise, the
non-[local] [events] in file are assumed. Then the [keep] of the
[certificate] is checked to ensure that the correct files were
read; see [keep]. A warning is printed if uncertified [books] were
included. Even if no warning is printed, include-book places a
burden on you; see [certificate].
If you use [guard]s, please note include-book is executed as though
(set-guard-checking nil) has been evaluated; see
[set-guard-checking]. If you want guards checked, please see [ld]
and/or see [rebuild].
The value of :load-compiled-file controls whether a compiled file for
the given file is loaded by include-book. Note that this keyword
applies only to the given file, not to any included sub-books. In
order to skip loading all compiled files, for the given file as
well as all included sub-books --- for example, to avoid Lisp
errors such as ``Wrong FASL version'' --- use (set-compiler-enabled
nil state); see [compilation]. Otherwise, if keyword argument
:load-compiled-file is missing or its value is the keyword
:default, then it is treated as :warn. If its value is nil, no
attempt is made to load the compiled file for the book provided. In
order to load the compiled file, it must be more recent than the
book's [certificate] (except in raw mode, where it must be more
recent than the book itself; see [set-raw-mode]). For non-nil
values of :load-compiled-file that do not result in a loaded
compiled file, ACL2 proceeds as follows. Note that a load of a
compiled file or expansion file aborts partway through whenever an
[include-book] form is encountered for which no suitable compiled
or expansion file can be loaded. For much more detail, see
[book-compiled-file].
t: Cause an error if the compiled file is not loaded. This same
requirement is imposed on every [include-book] form evaluated
during the course of evaluation of the present include-book
form, except that for those subsidiary include-books that do
not themselves specify :load-compiled-file t, it suffices to
load the expansion file (see [book-compiled-file]).
:warn: An attempt is made to load the compiled file, and a warning is
printed if that load fails to run to completion.
:comp: A compiled file is loaded as with value t, except that if a
suitable ``expansion file'' exists but the compiled file does
not, then the compiled file is first created. See
[book-compiled-file].
The three -okp arguments, :uncertified-okp, defaxioms-okp, and
skip-proofs-okp, determine the system's behavior when the book or
any sub-book is found to be uncertified, when the book or any
sub-book is found to contain [defaxiom] events, and when the book
or any sub-book is found to contain [skip-proofs] events,
respectively. All three default to t, which means it is ``ok'' for
the condition to arise. In this case, a warning is printed but the
processing to load the book is allowed to proceed. When one of
these arguments is nil and the corresponding condition arises, an
error is signaled and processing is aborted. Exceptions:
:uncertified-okp t is ignored if the include-book is being
performed on behalf of a [certify-book], and :uncertified-okp
:ignore-certs is an advanced option explained later in this topic.
The keyword argument :ttags may normally be omitted. A few
constructs, used for example if you are building your own system
based on ACL2, may require it. See [defttag] for an explanation of
this argument.
Include-book is similar in spirit to [encapsulate] in that it is a
single event that ``contains'' other [events], in this case the
[events] listed in the file named. Include-book processes the
non-[local] event forms in the file, assuming that each is
admissible. [Local] [events] in the file are ignored. You may use
include-book to load several [books], creating the logical [world]
that contains the definitions and theorems of all of them.
If any non-[local] event of the book attempts to define a [name] that
has already been defined --- and the book's definition is not
syntactically identical to the existing definition --- the attempt
to include the book fails, an error message is printed, and no
change to the logical [world] occurs. See [redundant-events] for
the details.
When a book is included, the default [defun-mode] (see
[default-defun-mode]) for the first event is always :[logic]. That
is, the default [defun-mode] ``outside'' the book --- in the
environment in which include-book was called --- is irrelevant to
the book. [Events] that change the [defun-mode] are permitted
within a book (provided they are not in [local] forms). However,
such changes within a book are not exported, i.e., at the
conclusion of an include-book, the ``outside'' default [defun-mode]
is always the same as it was before the include-book.
Unlike every other event in ACL2, include-book puts a burden on you.
Used improperly, include-book can be unsound in the sense that it
can create an inconsistent extension of a consistent logical
[world]. A certification mechanism is available to help you carry
this burden --- but it must be understood up front that even
certification is no guarantee against inconsistency here. The
fundamental problem is one of file system security. See
[certificate] for a discussion of the security issues.
At the beginning of execution of an include-book form, even before
executing [portcullis] [command]s, the value of
[ACL2-defaults-table] is restored to the value it had at startup.
After execution of an include-book form, the value of
[ACL2-defaults-table] is restored to what it was immediately before
that include-book form was executed. See [ACL2-defaults-table].
An advanced option is :uncertified-okp :ignore-certs. This tells ACL2
to ignore all [certificate] files while including the book and its
sub-books, thus treating all these books as uncertified. This
option may be useful when writing a .acl2x file for the first
``run'' of a ``two-runs approach'' to certification; see
[set-write-ACL2x]. Note however that ordinary certification (the
second ``run'') will then fail unless care is taken to avoid
:uncertified-okp :ignore-certs during that second certification
run. Finally (and speaking in general, not particularly about a
[certify-book] context), we emphasize that the option
:uncertified-okp :ignore-certs applies when including all
sub-books, not only for the current book. In particular, a
subsidiary include-book call specifying :uncertified-okp nil will
fail, because the superior :ignore-certs value causes the
subsidiary book to be treated as uncertified, which conflicts with
the requirement of :uncertified-okp nil.
Books Directory. We refer to the ``books directory'' of an executable
image as the full pathname string of the directory associated with
include-book keyword option :dir :system for that image. By
default, it is the books/ subdirectory of the directory where the
sources reside and the executable image is thus built (except for
ACL2(r) --- see [real] ---, where it is books/nonstd/). If those
books reside elsewhere, the environment variable ACL2_SYSTEM_BOOKS
can be set to the books/ directory under which they reside (a
Unix-style pathname, typically ending in books/ or books, is
permissible). In most cases, your ACL2 executable is a small script
in which you can set this environment variable just above the line
on which the actual ACL2 image is invoked, for example:
export ACL2_SYSTEM_BOOKS
ACL2_SYSTEM_BOOKS=/home/acl2/4-0/acl2-sources/books
If you follow suggestions in the installation instructions, these
books will be the ACL2 community books; see [community-books].
This concludes the guided tour through [books]. See [set-compile-fns]
for a subtle point about the interaction between include-book and
on-the-fly [compilation]. See [certify-book] for a discussion of
how to certify a book.")
(INCOMPATIBLE
(THEORIES)
"Declaring that two rules should not both be [enable]d
Example:
(theory-invariant (incompatible (:rewrite left-to-right)
(:rewrite right-to-left)))
General Form:
(incompatible rune1 rune2)
where rune1 and rune2 are two specific [rune]s. The arguments are not
evaluated. Invariant is just a macro that expands into a term that
checks that not both [rune]s are enabled. See [theory-invariant].")
(INDUCT (POINTERS)
"See [hints] for keyword :induct.")
(INDUCTION
(RULE-CLASSES)
"Make a rule that suggests a certain induction
Example:
(defthm recursion-by-sub2-induction-rule
t
:rule-classes ((:induction :pattern (* 1/2 i)
:condition (and (integerp i) (>= i 0))
:scheme (recursion-by-sub2 i))))
In ACL2, as in Nqthm, the functions in a conjecture ``suggest'' the
inductions considered by the system. Because every recursive
function must be admitted with a justification in terms of a
measure that decreases in a well-founded way on a given set of
``controlling'' arguments, every recursive function suggests a dual
induction scheme that ``unwinds'' the function from a given
application.
For example, since [append] (actually [binary-append], but we'll
ignore the distinction here) decomposes its first argument by
successive [cdr]s as long as it is a non-nil true list, the
induction scheme suggested by (append x y) has a base case
supposing x to be either not a true list or to be nil and then has
an induction step in which the induction hypothesis is obtained by
replacing x by (cdr x). This substitution decreases the same
measure used to justify the definition of [append]. Observe that an
induction scheme is suggested by a recursive function application
only if the controlling actuals are distinct variables, a condition
that is sufficient to ensure that the ``substitution'' used to
create the induction hypothesis is indeed a substitution and that
it drives down a certain measure. In particular, (append (foo x) y)
does not suggest an induction unwinding [append] because the
induction scheme suggested by (append x y) requires that we
substitute (cdr x) for x and we cannot do that if x is not a
variable symbol.
Once ACL2 has collected together all the suggested induction schemes
it massages them in various ways, combining some to simultaneously
unwind certain cliques of functions and vetoing others because they
``flaw'' others. We do not further discuss the induction heuristics
here; the interested reader should see Chapter XIV of A
Computational Logic (Boyer and Moore, Academic Press, 1979) which
represents a fairly complete description of the induction
heuristics of ACL2.
However, unlike Nqthm, ACL2 provides a means by which the user can
elaborate the rules under which function applications suggest
induction schemes. Such rules are called :induction rules. The
definitional principle automatically creates an :induction rule,
named (:induction fn), for each admitted recursive function, fn. It
is this rule that links applications of fn to the induction scheme
it suggests. Disabling (:induction fn) will prevent fn from
suggesting the induction scheme derived from its recursive
definition. It is possible for the user to create additional
:induction rules by using the :induction rule class in [defthm].
Technically we are ``overloading'' [defthm] by using it in the
creation of :induction rules because no theorem need be proved to
set up the heuristic link represented by an :induction rule.
However, since [defthm] is generally used to create rules and
rule-class objects are generally used to specify the exact form of
each rule, we maintain that convention and introduce the notion of
an :induction rule. An :induction rule can be created from any
lemma whatsoever.
General Form of an :induction Lemma or Corollary:
T
General Form of an :induction rule-class:
(:induction :pattern pat-term
:condition cond-term
:scheme scheme-term)
where pat-term, cond-term, and scheme-term are all terms, pat-term is
the application of a function symbol, fn, scheme-term is the
application of a function symbol, rec-fn, that suggests an
induction, and, finally, every free variable of cond-term and
scheme-term is a free variable of pat-term. We actually check that
rec-fn is either recursively defined --- so that it suggests the
induction that is intrinsic to its recursion --- or else that
another :induction rule has been proved linking a call of rec-fn as
the :pattern to some scheme.
The induction rule created is used as follows. When an instance of
the :pattern term occurs in a conjecture to be proved by induction
and the corresponding instance of the :condition term is known to
be non-nil (by type reasoning alone), the corresponding instance of
the :scheme term is created and the rule ``suggests'' the
induction, if any, suggested by that term. (Analysis of that term
may further involve induction rules, though the applied rule is
removed from consideration during that further analysis, in order
to avoid looping.) If rec-fn is recursive, then the suggestion is
the one that unwinds that recursion.
Consider, for example, the example given above,
(:induction :pattern (* 1/2 i)
:condition (and (integerp i) (>= i 0))
:scheme (recursion-by-sub2 i)).
In this example, we imagine that recursion-by-sub2 is the function:
(defun recursion-by-sub2 (i)
(if (and (integerp i)
(< 1 i))
(recursion-by-sub2 (- i 2))
t))
Observe that this function recursively decomposes its integer
argument by subtracting 2 from it repeatedly and stops when the
argument is 1 or less. The value of the function is irrelevant; it
is its induction scheme that concerns us. The induction scheme
suggested by (recursion-by-sub2 i) is
(and (implies (not (and (integerp i) (< 1 i))) ; base case
(:p i))
(implies (and (and (integerp i) (< 1 i)) ; induction step
(:p (- i 2)))
(:p i)))
We can think of the base case as covering two situations. The first
is when i is not an integer. The second is when the integer i is 0
or 1. In the base case we must prove (:p i) without further help.
The induction step deals with those integer i greater than 1, and
inductively assumes the conjecture for i-2 while proving it for i.
Let us call this scheme ``induction on i by twos.''
Suppose the above :induction rule has been added. Then an occurrence
of, say, (* 1/2 k) in a conjecture to be proved by induction would
suggest, via this rule, an induction on k by twos, provided k was
known to be a nonnegative integer. This is because the induction
rule's :pattern is matched in the conjecture, its :condition is
satisfied, and the :scheme suggested by the rule is that derived
from (recursion-by-sub2 k), which is induction on k by twos.
Similarly, the term (* 1/2 (length l)) would suggest no induction
via this rule, even though the rule ``fires'' because it creates
the :scheme (recursion-by-sub2 (length l)) which suggests no
inductions unwinding recursion-by-sub2 (since the controlling
argument of recursion-by-sub2 in this :scheme is not a variable
symbol).
Continuing this example one step further illustrates the utility of
:induction rules. We could define the function recursion-by-cddr
that suggests the induction scheme decomposing its [consp] argument
two [cdr]s at a time. We could then add the :induction rule linking
(* 1/2 (length x)) to (recursion-by-cddr x) and arrange for (* 1/2
(length l)) to suggest induction on l by [cddr].
Observe that :induction rules require no proofs to be done. Such a
rule is merely a heuristic link between the :pattern term, which
may occur in conjectures to be proved by induction, and the :scheme
term, from which an induction scheme may be derived. Hence, when an
:induction rule-class is specified in a [defthm] event, the theorem
proved is irrelevant. The easiest theorem to prove is, of course,
t. Thus, we suggest that when an :induction rule is to be created,
the following form be used:
(defthm name T
:rule-classes ((:induction :pattern pat-term
:condition cond-term
:scheme scheme-term)))
The name of the rule created is (:induction name). When that rune is
disabled the heuristic link between pat-term and scheme-term is
broken.")
(INITIALIZE-EVENT-USER
(PROVER-OUTPUT)
"User-supplied code to initiate [events]
This utility is intended for system hackers, not standard ACL2 users.
See [finalize-event-user] to see how to supply code to be run at the
end of [events]. We assume familiarity with finalize-event-user;
here we focus on how to supply code for the beginning as well as
the end of events.
As with [finalize-event-user], you attach your own function of
argument list (ctx qbody state) to initialize-event-user. (See
[finalize-event-user] for discussion of ctx and body.) The
attachment should return state and have a trivial guard, requiring
(implicitly) only that state satisfies state-p unless you use trust
tags to avoid that requirement. For example:
(defattach initialize-event-user initialize-event-user-test)
Why would you want to do this? Presumably you are building a system
on top of ACL2 and you want to track your own data. For example,
suppose you want to save the time in some [state] global variable,
my-time. You could do the following.
(defun my-init (ctx body state)
(declare (xargs :stobjs state
:guard-hints
((\"Goal\" :in-theory (enable read-run-time))))
(ignore ctx body))
(mv-let (seconds state)
(read-run-time state)
(f-put-global 'start-time seconds state)))
(defun my-final (ctx body state)
(declare (xargs :stobjs state
:guard-hints
((\"Goal\" :in-theory (enable read-run-time))))
(ignore ctx body))
(mv-let (seconds state)
(read-run-time state)
(prog2$ (if (boundp-global 'start-time state)
(cw \"Time: ~x0 seconds~%\"
(- seconds (fix (@ start-time))))
(cw \"BIG SURPRISE!~%\"))
(f-put-global 'end-time seconds state))))
(defattach initialize-event-user my-init)
(defattach finalize-event-user my-final)
Here is an abbreviated log, showing the time being printed at the
end.
ACL2 !>(thm (equal (append (append x y) x y x y x y x y)
(append x y x y x y x y x y)))
*1 (the initial Goal, a key checkpoint) is pushed for proof by induction.
....
ACL2 Error in ( THM ...): See :DOC failure.
******** FAILED ********
Time: 869/100 seconds
ACL2 !>")
(INLINE (POINTERS)
"See [defun-inline].")
(INSTRUCTIONS
(PROOF-CHECKER)
"Instructions to the proof checker
See [proof-checker] for an introduction to the interactive
``proof-checker'' goal manager, which supports much more direct
control of the proof process than is available by direct calls to
the prover (as are normally made using [defthm] or [thm]). In
brief, typical use is to evaluate the form (verify SOME-GOAL),
where SOME-GOAL is a formula (i.e., term) that you would like to
prove. Various commands (instructions) are available at the
resulting prompt; see [proof-checker-commands]. When the proof is
completed, suitable invocation of the exit command will print out a
form containing an :instructions field that provides the
instructions that you gave interactively, so that this form can be
evaluated non-interactively.
Thus, also see [defthm] for the role of :instructions in place of
:[hints]. As illustrated by the following example, the value
associated with :instructions is a list of [proof-checker]
commands.
Example:
(defthm associativity-of-append
(equal (append (append x y) z)
(append x (append y z)))
:instructions
(:induct (:dv 1) (:dv 1) :x :up :x (:dv 2) := (:drop 2)
:top (:dv 2) :x :top :s :bash))
See [proof-checker-commands] for a list of supported proof-checker
instructions and links to their documentation.
Below, we describe a capability for supplying :instructions as
:[hints].
The most basic utilities for directing the discharge of a proof
obligation are :[hints] and (less commonly) :instructions.
Individual instructions may call the prover with :hints; in that
sense, prover hints may occur inside instructions. We now describe
how, on the other hand, instructions may occur inside hints.
ACL2 supports :instructions as a hints keyword. The following example
forms the basis for our running example. This example does not
actually need hints, but imagine that the inductive step --- which
is \"Subgoal *1/2\" --- was difficult. You could submit that goal to
[verify], do an interactive proof, submit (exit t) to obtain the
list of :instructions, and then paste in those instructions. When
you submit the resulting event, you might see the following. Below
we'll explain the hint processing.
ACL2 !>(thm (equal (append (append x y) z)
(append x (append y z)))
:hints ((\"Subgoal *1/2\"
:instructions
(:promote (:dv 1) (:dv 1) :x :up :x (:dv 2) :=
(:drop 2) :top (:dv 2) :x :top :s))))
Name the formula above *1.
Perhaps we can prove *1 by induction. Three induction schemes are
suggested by this conjecture. Subsumption reduces that number to two.
However, one of these is flawed and so we are left with one viable
candidate.
We will induct according to a scheme suggested by (BINARY-APPEND X Y).
This suggestion was produced using the :induction rule BINARY-APPEND.
If we let (:P X Y Z) denote *1 above then the induction scheme we'll
use is
(AND (IMPLIES (AND (NOT (ENDP X)) (:P (CDR X) Y Z))
(:P X Y Z))
(IMPLIES (ENDP X) (:P X Y Z))).
This induction is justified by the same argument used to admit BINARY-APPEND.
When applied to the goal at hand the above induction scheme produces
two nontautological subgoals.
[Note: A hint was supplied for our processing of the goal below.
Thanks!]
Subgoal *1/2
(IMPLIES (AND (NOT (ENDP X))
(EQUAL (APPEND (APPEND (CDR X) Y) Z)
(APPEND (CDR X) Y Z)))
(EQUAL (APPEND (APPEND X Y) Z)
(APPEND X Y Z))).
But the trusted :CLAUSE-PROCESSOR function PROOF-CHECKER-CL-PROC replaces
this goal by T.
Subgoal *1/1
(IMPLIES (ENDP X)
(EQUAL (APPEND (APPEND X Y) Z)
(APPEND X Y Z))).
By the simple :definition ENDP we reduce the conjecture to
Subgoal *1/1'
(IMPLIES (NOT (CONSP X))
(EQUAL (APPEND (APPEND X Y) Z)
(APPEND X Y Z))).
But simplification reduces this to T, using the :definition BINARY-APPEND
and primitive type reasoning.
That completes the proof of *1.
Q.E.D.
Summary
Form: ( THM ...)
Rules: ((:DEFINITION BINARY-APPEND)
(:DEFINITION ENDP)
(:DEFINITION NOT)
(:FAKE-RUNE-FOR-TYPE-SET NIL)
(:INDUCTION BINARY-APPEND))
Time: 0.02 seconds (prove: 0.01, print: 0.01, other: 0.00)
Proof succeeded.
ACL2 !>
To understand how the :instructions supplied above were processed,
observe proof-checker instruction interpreter may be viewed as a
``clause-processor'': a function that takes an input goal and
returns a list of goals (which can be the empty list). Such a
function has the property that if all goals in that returned list
are theorems, then so is the input goal. This view of the
proof-checker instruction interpreter as a clause-processor leads
to the following crucial observation.
IMPORTANT!. Each call of the proof-checker instruction interpreter is
treated as a standalone clause-processor that is insensitive to the
surrounding prover environment. In particular:
* The proof-checker's theory is not sensitive to :in-theory [hints]
already processed in the surrounding proof. Indeed, the current
theory for which proof-checker commands are processed is just
the current theory of the ACL2 logical [world], i.e., the value
of (current-theory :here). Moreover, references to
(current-theory :here) in a proof-checker in-theory command,
even implicit references such as provided by [enable] and
[disable] expressions, are also references to the current
theory of the ACL2 logical [world].
* The [rune]s used during an :instructions hint are not tracked beyond
that hint, hence may not show up in the summary of the overall
proof. Again, think of the :instructions hint as a
[clause-processor] call, which has some effect not tracked by
the surrounding proof other than for the child goals that it
returns.
We continue now with our discussion of the proof-checker instruction
interpreter as a clause-processor.
In the example above, the input goal (\"Subgoal *1/2\") was processed
by the proof-checker instruction interpreter. The result was the
empty goal stack, therefore proving the goal, as reported in the
output, which we repeat here.
[Note: A hint was supplied for our processing of the goal below.
Thanks!]
Subgoal *1/2
(IMPLIES (AND (NOT (ENDP X))
(EQUAL (APPEND (APPEND (CDR X) Y) Z)
(APPEND (CDR X) Y Z)))
(EQUAL (APPEND (APPEND X Y) Z)
(APPEND X Y Z))).
But the trusted :CLAUSE-PROCESSOR function PROOF-CHECKER-CL-PROC replaces
this goal by T.
Remark. This brief remark can probably be ignored, but we include it
for completeness. The :CLAUSE-PROCESSOR message above may be
surprising, since the hint attached to \"Subgoal *1/2\" is an
:instructions hint, not a :clause-processor hint. But :instructions
is actually a custom keyword hint (see [custom-keyword-hints]), and
may be thought of as a macro that expands to a :[clause-processor]
hint, one that specifies proof-checker-cl-proc as the
clause-processor function. The keen observer may notice that the
clause-processor is referred to as ``trusted'' in the above output.
Normally one needs a trust tag (see [defttag]) to install a trusted
clause-processor, but that is not the case for the built-in
clause-processor, proof-checker-cl-proc. Finally, we note that
:instructions [hints] are ``spliced'' into the hints as follows:
the appropriate :[clause-processor] hint replaces the :instructions
hint, and the other hints remain intact. It may seems surprising
that one can thus, for example, use :instructions and :in-theory
together; but although the :in-theory hint will have no effect on
execution of the :instructions (see first bullet above), the
:in-theory hint will apply in the usual manner to any child goals
(see [hints-and-the-waterfall]). End of Remark.
Now consider the case that the supplied instructions do not prove the
goal. That is, suppose that the execution of those instructions
results in a non-empty goal stack. In that case, the resulting
goals become children of the input goals. The following edited log
provides an illustration using a modification of the above example,
this time with a single instruction that splits into two cases.
ACL2 !>(thm (equal (append (append x y) z)
(append x (append y z)))
:hints ((\"Subgoal *1/2\"
:instructions
((:casesplit (equal x y))))))
[[ ... output omitted ... ]]
Subgoal *1/2
(IMPLIES (AND (NOT (ENDP X))
(EQUAL (APPEND (APPEND (CDR X) Y) Z)
(APPEND (CDR X) Y Z)))
(EQUAL (APPEND (APPEND X Y) Z)
(APPEND X Y Z))).
We now apply the trusted :CLAUSE-PROCESSOR function PROOF-CHECKER-CL-PROC
to produce two new subgoals.
Subgoal *1/2.2
[[ ... output omitted ... ]]
Subgoal *1/2.1
[[ ... output omitted ... ]]
We have seen that an :instructions hint may produce zero or more
subgoals. There may be times where you wish to insist that it
produce zero subgoals, i.e., that it prove the desired goal. The
proof-checker `finish' command works nicely for this purpose. For
example, the following form is successfully admitted, but if you
delete some of the commands (for example, the :s command at the
end), you will see an informative error message.
(thm (equal (append (append x y) z)
(append x (append y z)))
:hints ((\"Subgoal *1/2\"
:instructions
((finish :promote (:dv 1) (:dv 1) :x :up :x (:dv 2) :=
(:drop 2) :top (:dv 2) :x :top :s)))))
If an :instructions hint of the form ((finish ...)) fails to prove
the goal, the clause-processor is deemed to have caused an error.
Indeed, any ``failure'' of a supplied proof-checker instruction
will be deemed to cause an error. In this case, you should see an
error message such as the following:
Saving proof-checker error state; see :DOC instructions. To retrieve:
(RETRIEVE :ERROR1)
In this case, you can evaluate the indicated [retrieve] command in
the ACL2 read-eval-print loop, to get to the point of failure.
You may have noticed that there is no output from the proof-checker
in the examples above. This default behavior prevents confusion
that could arise from use of proof-checker commands that call the
theorem prover such as prove, bash, split, and induct. These
commands produce output for what amounts to a fresh proof attempt,
which could confuse attempts to understand the surrounding proof
log. You can override the default behavior by providing a command
of the form
(comment inhibit-output-lst VAL)
where VAL is either the keyword :SAME (indicating that no change
should be made to which output is inhibited) or else is a legal
value for inhibited output; see [set-inhibit-output-lst]. The
following two variants of the immediately preceding THM form will
each produce output from the proof-checker commands, assuming in
the first variant that output hasn't already been inhibited.
(thm (equal (append (append x y) z)
(append x (append y z)))
:hints ((\"Subgoal *1/2\"
:instructions
((comment inhibit-output-lst :same)
(:casesplit (equal x y))))))
(thm (equal (append (append x y) z)
(append x (append y z)))
:hints ((\"Subgoal *1/2\"
:instructions
((comment inhibit-output-lst (proof-tree))
(:casesplit (equal x y))))))
Note that such a comment instruction must be provided explicitly
(i.e., not by way of a proof-checker [macro-command]) as the first
instruction, in order to have the effect on inhibited output that
is described above.
The following contrived example gives a sense of how one might want
to use :instructions within :[hints]. If you submit the following
theorem
(thm (implies (true-listp x)
(equal (reverse (reverse x)) x)))
then you will see the following checkpoint printed with the summary.
Subgoal *1/3''
(IMPLIES (AND (CONSP X)
(EQUAL (REVAPPEND (REVAPPEND (CDR X) NIL) NIL)
(CDR X))
(TRUE-LISTP (CDR X)))
(EQUAL (REVAPPEND (REVAPPEND (CDR X) (LIST (CAR X)))
NIL)
X))
This suggests proving the following theorem. Here we state it using
[defthmd], so that it is immediately disabled. Normally disabling
would be unnecessary, but for our contrived example it is useful to
imagine disabling it, say because we are following a methodology
that tends to keep [rewrite] rules disabled.
(defthmd revappend-revappend
(equal (revappend (revappend x y) z)
(revappend y (append x z))))
We might then enter the [proof-checker] to prove the original theorem
interactively, as follows.
ACL2 !>(verify (implies (true-listp x)
(equal (reverse (reverse x)) x)))
->: bash
***** Now entering the theorem prover *****
Goal'
([ A key checkpoint:
Goal'
(IMPLIES (TRUE-LISTP X)
(EQUAL (REVAPPEND (REVAPPEND X NIL) NIL)
X))
Goal' is subsumed by a goal yet to be proved.
])
Q.E.D.
Creating one new goal: (MAIN . 1).
The proof of the current goal, MAIN, has been completed. However,
the following subgoals remain to be proved:
(MAIN . 1).
Now proving (MAIN . 1).
->: th ; show current goal (\"th\" for \"theorem\")
*** Top-level hypotheses:
1. (TRUE-LISTP X)
The current subterm is:
(EQUAL (REVAPPEND (REVAPPEND X NIL) NIL)
X)
->: p ; show current subterm only
(EQUAL (REVAPPEND (REVAPPEND X NIL) NIL)
X)
->: 1 ; dive to first argument
->: p
(REVAPPEND (REVAPPEND X NIL) NIL)
->: sr ; show-rewrites
1. REVAPPEND-REVAPPEND (disabled)
New term: (REVAPPEND NIL (APPEND X NIL))
Hypotheses: <none>
Equiv: EQUAL
2. REVAPPEND
New term: (AND (CONSP (REVAPPEND X NIL))
(REVAPPEND (CDR (REVAPPEND X NIL))
(LIST (CAR (REVAPPEND X NIL)))))
Hypotheses: <none>
Equiv: EQUAL
->: (r 1) ; rewrite with rule #1 above
Rewriting with REVAPPEND-REVAPPEND.
->: p
(REVAPPEND NIL (APPEND X NIL))
->: top ; move to the top of the conclusion, making it the current subterm
->: p
(EQUAL (REVAPPEND NIL (APPEND X NIL)) X)
->: prove ; finish the proof
***** Now entering the theorem prover *****
Q.E.D.
*!*!*!*!*!*!* All goals have been proved! *!*!*!*!*!*!*
You may wish to exit.
->: (exit t) ; the argument, t, causes :instructions to be printed
(DEFTHM T
(IMPLIES (TRUE-LISTP X)
(EQUAL (REVERSE (REVERSE X)) X))
:INSTRUCTIONS (:BASH (:DV 1)
(:REWRITE REVAPPEND-REVAPPEND)
:TOP :PROVE))
NIL
ACL2 !>(thm
(IMPLIES (TRUE-LISTP X)
(EQUAL (REVERSE (REVERSE X)) X))
:hints ((\"Goal\"
:INSTRUCTIONS ; copy what was printed above:
(:BASH (:DV 1)
(:REWRITE REVAPPEND-REVAPPEND)
:TOP :PROVE))))
Goal'
Q.E.D.
Q.E.D.
Q.E.D.
Summary
Form: ( THM ...)
Rules: NIL
Hint-events: ((:CLAUSE-PROCESSOR PROOF-CHECKER-CL-PROC))
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Proof succeeded.
ACL2 !>
Finally we present an even more contrived example, based on the one
above. This example illustrates that there is actually no limit
imposed on the nesting of :instructions within :[hints] within
:instructions, and so on. Notice the indication of nesting levels:
``1>'' to ``<1'' for output from nesting level 1, and ``2>'' to
``<2'' for output from nesting level 2.
(thm (implies (true-listp x)
(equal (reverse (reverse x)) x))
:hints ((\"Goal\"
:instructions
((comment inhibit-output-lst :same)
(:prove
:hints ((\"Goal\" :in-theory (disable append))
(\"Subgoal *1/3''\"
:instructions
((comment inhibit-output-lst :same)
:bash
(:dv 1)
(:rewrite revappend-revappend)))))))))
Here is an edited version of the resulting log.
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
[[1> Executing proof-checker instructions]]
->: (COMMENT INHIBIT-OUTPUT-LST :SAME)
->: (:PROVE
:HINTS
((\"Goal\" :IN-THEORY (DISABLE APPEND))
(\"Subgoal *1/3''\" :INSTRUCTIONS ((COMMENT INHIBIT-OUTPUT-LST :SAME)
:BASH (:DV 1)
(:REWRITE REVAPPEND-REVAPPEND)))))
***** Now entering the theorem prover *****
[[ ... output omitted ... ]]
[Note: A hint was supplied for our processing of the goal below.
Thanks!]
Subgoal *1/3''
(IMPLIES (AND (CONSP X)
(EQUAL (REVAPPEND (REVAPPEND (CDR X) NIL) NIL)
(CDR X))
(TRUE-LISTP (CDR X)))
(EQUAL (REVAPPEND (REVAPPEND (CDR X) (LIST (CAR X)))
NIL)
X)).
[[2> Executing proof-checker instructions]]
->: (COMMENT INHIBIT-OUTPUT-LST :SAME)
->: :BASH
***** Now entering the theorem prover *****
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
But we have been asked to pretend that this goal is subsumed by the
yet-to-be-proved |PROOF-CHECKER Goal|.
Q.E.D.
Creating one new goal: (MAIN . 1).
The proof of the current goal, MAIN, has been completed. However,
the following subgoals remain to be proved:
(MAIN . 1).
Now proving (MAIN . 1).
->: (:DV 1)
->: (:REWRITE REVAPPEND-REVAPPEND)
Rewriting with REVAPPEND-REVAPPEND.
[[<2 Completed proof-checker instructions]]
We now apply the trusted :CLAUSE-PROCESSOR function PROOF-CHECKER-CL-PROC
to produce one new subgoal.
Subgoal *1/3'''
[[ ... output omitted ... ]]
[[<1 Completed proof-checker instructions]]
The nesting levels are independent of whether or not output is
enabled; for example, if the first (comment ...) form below is
omitted, then we will see only the output bracketed by ``2>'' to
``<2''. Note also that these levels are part of the error states
saved for access by [retrieve] (as indicated above); for example, a
failure at level 1 would be associated with symbol :ERROR1 as
indicated above, while a failure at level 2 would be associated
with symbol :ERROR2.")
(INT=
(NUMBERS ACL2-BUILT-INS)
"Test equality of two integers
(int= x y) is logically equivalent to (equal x y).
Unlike [equal], int= requires its arguments to be numbers (or else
causes a [guard] violation; see [guard]). Generally, int= is
executed more efficiently than [equal] or [=] on integers.
Macro: <int=>
(defmacro int= (i j)
(list 'eql
(if (integerp i)
i (list 'the 'integer i))
(if (integerp j)
j (list 'the 'integer j))))")
(INTEGER-LENGTH
(NUMBERS ACL2-BUILT-INS)
"Number of bits in two's complement integer representation
For non-negative integers, (integer-length i) is the minimum number
of bits needed to represent the integer. Any integer can be
represented as a signed two's complement field with a minimum of (+
(integer-length i) 1) bits.
The [guard] for integer-length requires its argument to be an
integer. Integer-length is defined in Common Lisp. See any Common
Lisp documentation for more information.
Function: <integer-length>
(defun integer-length (i)
(declare (xargs :guard (integerp i)))
(if (zip i)
0
(if (= i -1)
0 (+ 1 (integer-length (floor i 2))))))")
(INTEGER-LISTP
(NUMBERS LISTS ACL2-BUILT-INS)
"Recognizer for a true list of integers
The predicate integer-listp tests whether its argument is a true list
of integers.
Function: <integer-listp>
(defun integer-listp (l)
(declare (xargs :guard t))
(cond ((atom l) (eq l nil))
(t (and (integerp (car l))
(integer-listp (cdr l))))))")
(INTEGER-RANGE-P
(NUMBERS ACL2-BUILT-INS)
"Recognizer for integers between two bounds.
The predicate (integer-range-p lower upper x) tests whether x is an
integer greater than or equal to lower and less than upper.
Function: <integer-range-p>
(defun integer-range-p (lower upper x)
(declare (xargs :guard (and (integerp lower)
(integerp upper))))
(and (integerp x)
(<= lower x)
(< x upper)))")
(INTEGERP
(NUMBERS ACL2-BUILT-INS)
"Recognizer for whole numbers
(integerp x) is true if and only if x is an integer.")
(INTERESTING-APPLICATIONS
(ACL2-TUTORIAL)
"Some industrial examples of ACL2 use
ACL2 is an interactive system in which you can model digital
artifacts and guide the system to mathematical proofs about the
behavior of those models. It has been used at such places as AMD,
Centaur, IBM, and Rockwell Collins to verify interesting properties
of commercial designs. It has been used to verify properties of
models of microprocessors, microcode, the Sun Java Virtual Machine,
operating system kernels, other verifiers, and interesting
algorithms.
Here we list just a few of the industrially-relevant results obtained
with ACL2. Reading the list may help you decide you want to learn
how to use ACL2. If you do decide you want to learn more, we
recommend that you take [The Tours] after you leave this page.
ACL2 was used at Motorola Government Systems to certify several
microcode programs for the Motorola CAP digital signal processor,
including a comparator sort program that is particularly subtle. In
the same project, ACL2 was used to model the CAP at both the
pipelined architectural level and the instruction set level. The
architectural model was bit- and cycle-accurate: it could be used
to predict every bit of memory on every cycle. The models were
proved equivalent under certain hypotheses, the most important
being a predicate that analyzed the microcode for certain pipeline
hazards. This predicate defined what the hazards were,
syntactically, and the equivalence of the two models established
the correctness of this syntactic characterization of hazards.
Because ACL2 is a functional programming language, the ACL2 models
and the hazard predicate could be executed. ACL2 executed microcode
interpretr several times faster than the hardware simulator could
execute it -- with assurance that the answers were equivalent. In
addition, the ACL2 hazard predicate was executed on over fifty
microcode programs written by Motorola engineers and extracted from
the ROM mechanically. Hazards were found in some of these. (See,
for example, Bishop Brock and Warren. A. Hunt, Jr. ``Formal
analysis of the motorola CAP DSP.'' In Industrial-Strength Formal
Methods. Springer-Verlag, 1999.)
ACL2 was used at Advanced Micro Devices (AMD) to verify the
compliance of the AMD Athon's (TM) elementary floating point
operations with their IEEE 754 specifications. This followed
ground-breaking work in 1995 when ACL2 was used to prove the
correctness of the microcode for floating-point division on the AMD
K5. The AMD Athlon work proved addition, subtraction,
multiplication, division, and square root compliant with the IEEE
standard. Bugs were found in RTL designs. These bugs had survived
undetected in hundreds of millions of tests but were uncovered by
ACL2 proof attempts. The RTL in the fabricated Athlon FPU has been
mechanically verified by ACL2. Similar ACL2 proofs have been
carried out for every major AMD FPU design fabricated since the
Athlon. (See for example, David Russinoff. ``A mechanically checked
proof of correctness of the AMD5K86 floating-point square root
microcode''. Formal Methods in System Design Special Issue on
Arithmetic Circuits, 1997.)
ACL2 was used at IBM to verify the floating point divide and square
root on the IBM Power 4. (See Jun Sawada. ``Formal verification of
divide and square root algorithms using series calculation''. In
Proceedings of the ACL2 Workshop 2002, Grenoble, April 2002.)
ACL2 was used to verify floating-point addition/subtraction
instructions for the media unit from Centaur Technology's 64-bit,
X86-compatible microprocessor. This unit implements over one
hundred instructions, with the most complex being floating-point
addition/subtraction. The media unit can add/subtract four pairs of
floating-point numbers every clock cycle with an industry-leading
two-cycle latency. The media unit was modeled by translating its
Verilog design into an HDL deeply embedded in the ACL2 logic. The
proofs used a combination of AIG- and BDD-based symbolic
simulation, case splitting, and theorem proving. (See Warren A.
Hunt, Jr. and Sol Swords. ``Centaur Technology Media Unit
Verification''. In CAV '09: Proceedings of the 21st International
Conference on Computer Aided Verification, pages 353--367, Berlin,
Heidelberg, 2009. Springer-Verlag.)
Rockwell Collins used ACL2 to prove information flow properties about
its Advanced Architecture MicroProcessor 7 Government Version
(AAMP7G), a Multiple Independent Levels of Security (MILS) device
for use in cryptographic applications. The AAMP7G provides MILS
capability via a verified secure hardware-based separation kernel.
The AAMP7G's design was proved to achieve MILS using ACL2, in
accordance with the standards set by EAL-7 of the Common Criteria
and Rockwell Collins has received National Security Agency (NSA)
certification for the device based on this work. (See Matthew M.
Wilding, David A. Greve, Raymond J. Richards, and David S. Hardin.
``Formal Verification of Partition Management for the AAMP7G
Microprocessor''. In Design and Verification of Microprocessor
Systems for High-Assurance Applications, David S. Hardin, ed.,
pages 175--191, Springer US, 2010.)
Key properties of the Sun Java Virtual Machine and its bytecode
verifier were verified in ACL2. Among the properties proved were
that certain invariants are maintained by class loading and that
the bytecode verifier insures that execution is safe. In addition,
various JVM bytecode programs have been verified using this model
of the JVM. (See Hanbing Liu. Formal Specification and Verification
of a JVM and its Bytecode Verifier. PhD thesis, University of Texas
at Austin, 2006.)
The Boyer-Moore fast string searching algorithm was verified with
ACL2, including a model of the JVM bytecode for the search
algorithm itself (but not the preprocessing). (See J S. Moore and
Matt Martinez. ``A mechanically checked proof of the correctness of
the Boyer-Moore fast string searching algorithm.'' In Engineering
Methods and Tools for Software Safety and Security pages 267--284.
IOS Press, 2009.)
ACL2 was used to verify the fidelity between an ACL2-like theorem
prover and a simple (``trusted by inspection'') proof checker,
thereby establishing (up to the soundness of ACL2) the soundness of
the ACL2-like theorem prover. This project was only part of a much
larger project in which the resulting ACL2 proof script was then
hand-massaged into a script suitable for the ACL2-like theorem
prover to process, generating a formal proof of its fidelity that
has been checked by the trusted proof checker. (See Jared Davis.
Milawa: A Self-Verifying Theorem Prover. Ph.D. Thesis, University
of Texas at Austin, December, 2009.)
These are but a few of the interesting projects carried out with
ACL2. Many of the authors mentioned above have versions of the
papers on their web pages. In addition, see {Books and Papers about
ACL2 and its Applications |
http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html}.
Also, see the presentations in each of the {ACL2 Workshops |
http://www.cs.utexas.edu/users/moore/acl2/workshops.html}.")
(INTERFACING-TOOLS
(TOP ACL2)
"Libraries and tools for doing basic [file i/o], using raw [Common
Lisp libraries], working with the [operating system], and
interfacing with [other programs].
Subtopics
[Command-line]
Handling of command-line arguments when ACL2 is invoked
[Defttag]
Introduce a trust tag (ttag)
[Io]
Input/output facilities in ACL2
[Save-exec]
Save an executable image and a wrapper script
[Sys-call]
Make a system call to the host operating system")
(INTERN
(SYMBOLP PACKAGES ACL2-BUILT-INS)
"Create a new symbol in a given package
(intern symbol-name symbol-package-name) returns a symbol with the
given [symbol-name] and the given [symbol-package-name]. We
restrict Common Lisp's intern so that the second argument is either
the symbol *main-lisp-package-name*, the value of that constant, or
is one of \"ACL2\", \"ACL2-INPUT-CHANNEL\", \"ACL2-OUTPUT-CHANNEL\", or
\"KEYWORD\". To avoid that restriction, see [intern$].
In ACL2 intern is actually implemented as a macro that expands to a
call of a similar function whose second argument is a symbol.
Invoke :pe intern to see the definition, or see
[intern-in-package-of-symbol].
To see why is intern so restricted consider (intern \"X\" \"P\"). In
particular, is it a symbol and if so, what is its
[symbol-package-name]? One is tempted to say ``yes, it is a symbol
in the package \"P\".'' But if package \"P\" has not yet been defined,
that would be premature because the imports to the package are
unknown. For example, if \"P\" were introduced with
(defpkg \"P\" '(LISP::X))
then in Common Lisp (symbol-package-name (intern \"X\" \"P\")) returns
\"LISP\".
The obvious restriction on intern is that its second argument be the
name of a package known to ACL2. We cannot express such a
restriction (except, for example, by limiting it to those packages
known at some fixed time, as we do). Instead, we provide
[intern-in-package-of-symbol] which requires a ``witness symbol''
for the package instead of the package. The witness symbol is any
symbol (expressible in ACL2) and uniquely specifies a package
necessarily known to ACL2.")
(INTERN$
(SYMBOLP PACKAGES ACL2-BUILT-INS)
"Create a new symbol in a given package
Intern$ is a macro that behaves the same as the macro [intern],
except for weakening the restriction to a fixed set of package
names so that any package name other than \"\" is legal. See
[intern]. Note that if you evaluate a call (intern$ x y) for which
there is no package with name y that is known to ACL2, you will get
an error.
(Intern$ x y) expands to:
(intern-in-package-of-symbol x (pkg-witness y))
See [intern-in-package-of-symbol] and see [pkg-witness].")
(INTERN-IN-PACKAGE-OF-SYMBOL
(SYMBOLP PACKAGES ACL2-BUILT-INS)
"Create a symbol with a given name
Completion Axiom (completion-of-intern-in-package-of-symbol):
(equal (intern-in-package-of-symbol x y)
(if (and (stringp x)
(symbolp y))
(intern-in-package-of-symbol x y)
nil))
[Guard] for (intern-in-package-of-symbol x y):
(and (stringp x) (symbolp y))
Intuitively, (intern-in-package-of-symbol x y) creates a symbol with
[symbol-name] x [intern]ed in the package containing y. More
precisely, suppose x is a string, y is a symbol with
[symbol-package-name] pkg and that the [defpkg] event creating pkg
had the list of symbols imports as the value of its second
argument. Then (intern-in-package-of-symbol x y) returns a symbol,
ans, the [symbol-name] of ans is x, and the [symbol-package-name]
of ans is pkg, unless x is the [symbol-name] of some member of
imports with [symbol-package-name] ipkg, in which case the
[symbol-package-name] of ans is ipkg. Because [defpkg] requires
that there be no duplications among the [symbol-name]s of the
imports, intern-in-package-of-symbol is uniquely defined.
For example, suppose \"MY-PKG\" was created by
(defpkg \"MY-PKG\" '(ACL2::ABC LISP::CAR)).
Let w be 'my-pkg::witness. Observe that
(symbolp w) is t ; w is a symbol
(symbol-name w) is \"WITNESS\" ; w's name is \"WITNESS\"
(symbol-package-name w) is \"MY-PKG\" ; w is in the package \"MY-PKG\"
The construction of w illustrates one way to obtain a symbol in a
given package: write it down as a constant using the double-colon
notation.
But another way to obtain a symbol in a given package is to create it
with intern-in-package-of-symbol.
(intern-in-package-of-symbol \"XYZ\" w) is MY-PKG::XYZ
(intern-in-package-of-symbol \"ABC\" w) is ACL2::ABC
(intern-in-package-of-symbol \"CAR\" w) is LISP::CAR
(intern-in-package-of-symbol \"car\" w) is MY-PKG::|car|")
(INTERSECTION$
(LISTS ACL2-BUILT-INS)
"Elements of one list that are not elements of another
General Forms:
(intersection$ l1 l2 ... lk)
(intersection$ l1 l2 ... lk :test 'eql) ; same as above
(intersection$ l1 l2 ... lk :test 'eq) ; same, but eq is equality test
(intersection$ l1 l2 ... lk :test 'equal) ; same, but equal is equality test
(Intersection$ x y) equals a list that contains the members of x that
are also members of y. More precisely, the resulting list is the
result of deleting from x those members that that are not members
of y. The optional keyword, :TEST, has no effect logically, but
provides the test (default [eql]) used for comparing members of the
two lists.
Intersection$ need not take exactly two arguments, though it must
take at least one argument: (intersection$ x) is x, (intersection$
x y z ... :test test) is (intersection$ x (intersection$ y z ...
:test test) :test test), and if :TEST is not supplied, then
(intersection$ x y z ...) is (intersection$ x (intersection$ y z
...)). For the discussion below we restrict ourselves, then, to the
cases (intersection$ x y) and (intersection$ x y :test test).
The [guard] for a call of intersection$ (in the two cases just above)
depends on the test. In all cases, both arguments must satisfy
[true-listp]. If the test is [eql], then one of the arguments must
satisfy [eqlable-listp]. If the test is [eq], then one of the
arguments must satisfy [symbol-listp].
See [equality-variants] for a discussion of the relation between
intersection$ and its variants:
(intersection-eq x lst) is equivalent to (intersection$ x lst :test
'eq);
(intersection-equal x lst) is equivalent to (intersection$ x lst
:test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function intersection-equal.
Note that intersection-eq can take any positive number of arguments,
in analogy to intersection$; indeed, (intersection-eq ...) expands
to (intersection$ ... :test 'eq). However, intersection-equal is a
function, not a macro, and takes exactly two arguments.
Intersection$ is similar to the Common Lisp primitive intersection.
However, Common Lisp does not specify the order of elements in the
result of a call of intersection.
Function: <intersection-equal>
(defun
intersection-equal (l1 l2)
(declare (xargs :guard (and (true-listp l1) (true-listp l2))))
(cond ((endp l1) nil)
((member-equal (car l1) l2)
(cons (car l1)
(intersection-equal (cdr l1) l2)))
(t (intersection-equal (cdr l1) l2))))")
(INTERSECTION-EQ (POINTERS)
"See [intersection$].")
(INTERSECTION-EQUAL (POINTERS)
"See [intersection$].")
(INTERSECTION-THEORIES
(THEORIES THEORY-FUNCTIONS)
"Intersect two [theories]
Example:
(intersection-theories (current-theory :here)
(theory 'arith-patch))
General Form:
(intersection-theories th1 th2)
where th1 and th2 are theories (see [theories]). To each of the
arguments there corresponds a runic theory. This function returns
the intersection of those two runic [theories], represented as a
list and ordered chronologically.
This ``function'' is actually a macro that expands to a term
mentioning the single free variable [world]. When theory
expressions are evaluated by [in-theory] or the :[in-theory] hint,
[world] is bound to the current ACL2 [world].")
(INTERSECTP
(LISTS ACL2-BUILT-INS)
"Test whether two lists intersect
General Forms:
(intersectp l1 l2)
(intersectp l1 l2 :test 'eql) ; same as above (eql as equality test)
(intersectp l1 l2 :test 'eq) ; same, but eq is equality test
(intersectp l1 l2 :test 'equal) ; same, but equal is equality test
(Intersectp l1 l2) returns t if l1 and l2 have a [member] in common,
else it returns nil. The optional keyword, :TEST, has no effect
logically, but provides the test (default [eql]) used for comparing
members of the two lists.
The [guard] for a call of intersectp depends on the test. In all
cases, both arguments must satisfy [true-listp]. If the test is
[eql], then one of the arguments must satisfy [eqlable-listp]. If
the test is [eq], then one of the arguments must satisfy
[symbol-listp].
See [equality-variants] for a discussion of the relation between
intersectp and its variants:
(intersectp-eq x lst) is equivalent to (intersectp x lst :test 'eq);
(intersectp-equal x lst) is equivalent to (intersectp x lst :test
'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function intersectp-equal.
Function: <intersectp-equal>
(defun intersectp-equal (x y)
(declare (xargs :guard (and (true-listp x) (true-listp y))))
(cond ((endp x) nil)
((member-equal (car x) y) t)
(t (intersectp-equal (cdr x) y))))")
(INTERSECTP-EQ (POINTERS)
"See [intersectp].")
(INTERSECTP-EQUAL (POINTERS)
"See [intersectp].")
(INTRODUCTION-TO-A-FEW-SYSTEM-CONSIDERATIONS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"The mechanics of interaction with the theorem prover
ACL2 is implemented in Common Lisp. There are many different Common
Lisps and they differ in details relating to interacting with the
system. We sometimes refer to the host Common Lisp as ``raw Lisp.''
The new user is advised not to operate in raw Lisp as it is
possible to, say, redefine ACL2 system faclities like defthm.
Most people use Emacs (see [Emacs] [{ICON}]) or the ACL2 Sedan
(Eclipse) interface (see [ACL2-Sedan] [{ICON}]). They provide
protection against certain common mistakes, e.g., trying to edit a
block of input text after the operating system has buffered it up
and sent it to the Lisp reader which is parsing it as you type.
More on this below. In addition, the Sedan provides helpful syntax
checking and a disciplined approach to the stack of lemmas
generated by The Method. But the variety of interfaces to the
variety of Lisps mean that there is great variation in what one
must type to interact with ACL2.
The best example is perhaps trying to interrupt a running proof. If
your host Common Lisp is GCL or Allegro and you are typing directly
to the Common Lisp process, then you can interrupt a computation by
typing ``ctrl-c'' (hold down the Control key and hit the ``c'' key
once). But other Lisps may require some other control sequence. If
you are typing to an Emacs process which is running the GCL or
Allegro Common Lisp process in a shell buffer, you should type
ctrl-c ctrl-c. If you are running the ACL2 Sedan, you can use the
Interrupt Session button on the tool bar. The environment you enter
when you interrupt depends on various factors and basically you
should endeavor to get back to the top level ACL2 command loop,
perhaps by typing some kind of Lisp depenent ``abort'' command like
A or :q, or :abort!. You can usually determine what environment
you're in by paying attention to the prompt, which we discuss
below.
The ACL2 ``interactive loop'' is called [lp] ([{ICON}]) and is
generally invoked automatically from your Common Lisp when you
start up the ACL2 process. LP is just a special case of an ACL2
function called [ld] [{ICON}], which the user can call from within
the ACL2 interactive loop to enter the loop recursively. New users
don't have to know this except that it helps explain why some
commands have the string ``-ld-'' in their names!
ACL2 presents itself as a ``read-eval-print'' loop: you're repeatedly
prompted for some type-in, which is read, evaluated, and may cause
some printing. The prompt tells you something about ACL2's state.
In the standard environment, the prompt is
ACL2 !>
The ``ACL2'' tells you that the symbols you use in your command are
those defined in the standard ACL2 namespace (or, in the jargon of
Lisp, the ``current package,'' see [current-package] [{ICON}]). You
could create a new namespace (see [defpkg] [{ICON}]) and set the
current package to it (see [in-package] [{ICON}]). The next part of
the prompt above (``!''), the exclamation mark) tells you that
before ACL2 evaluates your type-in it will check to see whether
[guard]s ([{ICON}]) are respected, i.e., whether the functions used
in your command are being supplied arguments in their ``expected
domains.'' If evaluation is allowed by the guards, it proceeds
exactly according to the ACL2 axioms; if evaluation is not allowed,
an error is signaled. ACL2 event commands check their arguments
thoroughly at run-time, regardless of Lisp's notion of ``expected
domains.''
If the exclamation mark is missing from the prompt,
ACL2 >
then evaluation occurs strictly according to the ACL2 axioms, without
regard for any declared guards.
You can switch between these two prompts by typing
ACL2 !>:set-guard-checking nil
to turn guard checking off and
ACL2 >:set-guard-checking t
to turn it on. Try typing (car 7) to each prompt.
If there is a ``p'' in the prompt,
ACL2 p!>
with or without the exclamation mark:
ACL2 p>
it means you are in :[program] ([{ICON}]) mode rather than :[logic]
([{ICON}]) mode. In :program mode, defun just defines Common Lisp
programs that you can evaluation but it adds no axioms and you
cannot use such defined functions in theorems or invoke defthm.
:Program mode is often used to prototype a model.
Most commands are just typical parenthesized Lisp expressions, like
ACL2 !>(defthm rev-rev
(implies (true-listp x)
(equal (rev (rev x)) x)))
but some are typed as keywords followed by a certain number of
arguments.
For example, to undo the last event you may type
ACL2 !>:u
or to undo back through the introduction of rev you may type
ACL2 !>:ubt rev
The first is equivalent to evaluating (u) and the second is
equivalent to evaluating (ubt 'rev). See [keyword-commands]
[{ICON}]. So if you see a sentence like ``to turn on the break
rewrite facility, execute :brr t,'' we mean type
ACL2 !>:brr t
or equivalently
ACL2 !>(brr t)
If you see a prompt that doesn't look like those above you are
probably not typing commands to the standard ACL2 read-eval-print
loop! If you've somehow called LD recursively, the prompt ``gets
deeper,'' e.g.,
ACL2 !>>
and you can pop out one level with :[q] [{ICON}] (for ``quit'') or
pop to the outermost ACL2 loop with :abort! [{ICON}]. If you are in
the outermost call of the ACL2 interactive loop and you type :q,
you pop out into raw lisp. The prompt there is generally different
from the ACL2 prompt but that is outside our our control and varies
from Lisp to Lisp. We have arranged for many (but not all) Lisps to
use a raw lisp prompt involving the string \"[RAW LISP]\". To get
back into the ACL2 interactive loop from raw lisp, evaluate (LP).
If you see a prompt that looks like an ACL2 prompt but has a number
in front of it, e.g.,
1 ACL2 >
then you're talking to the break rewrite facility (and you are 1
level deep in the example above). Presumably at earlier time in
this session you enabled that facility, with :brr t, installed a
monitor on some rule, invoked the prover, entered the break, and
forgot. Everything you have done (e.g., lemmas you might have
proved with defthm) inside that break will be lost when you exit
the break.
Since the break rewrite facility is ``ours'' we can tell you how to
exit it! To exit our breaks and return to the top-level ACL2 loop,
execute :abort!.
If you discover you've been working in a brr break, exit, turn off
the break facility wih :brr nil, and redo whatever defuns and
defthms you did while in that break.
Users of the Emacs interface may occasionally type commands directly
in the *shell* buffer running ACL2. This can be ``dangerous'' for
two reasons. One is that if you type an event, like a defun or
defthm, directly to the shell, it will not be recorded in your
``script'' buffer and you may forget it in your final script. The
other is that if you attempt to edit a multi-line command on any
but the most recent line, e.g., to correct the spelling of defthm
below after you've typed the ``(implies (true-listp x)'' you will
confuse the Lisp parser because it has already read ``(defth
rev-rev''.
ACL2 !>(defth rev-rev
(implies (true-listp x)
This usually provokes the raw Lisp to enter a low level error break
from which you must abort, possibly reenter the ACL2 loop, and
re-type the corrected command from scratch.
Another common mistake when using interfaces other than the ACL2
Sedan is to type an ill-formed ACL2 expression containing dots or
commas, which also often provokes a break into the raw Lisp's error
handler.
The fundamental lesson is that you should pay attention to the prompt
and learn what the different prompts mean -- or use the ACL2 Sedan.
If you have been working your way through the tutorial introduction
to the theorem prover, use your browser's Back Button now to return
to [introduction-to-the-theorem-prover].")
(INTRODUCTION-TO-HINTS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"How to provide hints to the theorem prover
We assume you've read [introduction-to-rewrite-rules-part-1],
[introduction-to-key-checkpoints], and
[introduction-to-the-database].
You may give the theorem prover a hint that is specific to a
particular subgoal generated during a proof attempt. Of course, you
learn the name of the subgoal by inspecting the key checkpoints or
other proof output. You are not expected to anticipate the need for
hints at specific subgoals; instead, you usually deduce that a hint
is required because the subgoals is not proved but you see that
existing rules and context make it provable.
The most common hint is to enable and/or disable a particular rule on
some particular subgoal.
(defthm name
formula
:hints ((\"Subgoal *1/3.2''\" :in-theory (disable nth-nthcdr))))
The hint above tells the rewriter that just before it begins to work
on Subgoal *1/3.2'' it should switch to a local theory in which all
of the rules generated from the event nth-nthcdr are disabled. That
local theory remains the one in use for all descendent subgoals
generated from the one named, until and unless one of those
descendent subgoals has an :in-theory hint associated with it.
There are many kinds of hints besides :in-theory and in general,
after each subgoal name, you can give various forms of advice and
list various adjustments you wish to make to the context in which
the prover is operating when it begins addressing the subgoal
named.
The top-level goal is always named Goal. Thus
(defthm name
formula
:hints ((\"Goal\" ...hints1...)
(\"Subgoal *1/3.2''\" ...hints2...)))
has the effect of using hints1 for the top-level goal and all of its
children throughout the entire proof, except for Subgoal *1/3.2''
and its children, where hints2 is used instead.
There are a few hints which ``take effect'' exactly on the subgoal to
which they are attached and are not inherited by their descendents.
Here is an incomplete list of some of the more common hints; we note
the ones that do not pass on their effects to their descendents. We
recommend that you not follow the advanced links (marked
``[{ICON}]'') below until you have read the entire tutorial.
See [in-theory] [{ICON}] for how to enable and/or disable rules. The
new theory is computed by a ``theory expression'' (see [theories]
[{ICON}]) such as (disable nth-nthcdr) and typically makes
adjustments such as additions or deletions to the global current
theory. All the relevant new theories are computed before the proof
begins. Thus, in
(defthm name
formula
:hints ((\"Goal\" :in-theory (disable rule1))
(\"Subgoal *1/3.2''\" (disable rule2))))
the theory mentioned for Goal is the global current theory minus
rule1, while the theory mentioned for its descendent, Subgoal
*1/3.2'', is the global current theory minus rule2. In particular,
if both rule1 and rule2 are enabled in the global current theory,
then rule1 is enabled during the processing of Subgoal *1/3.2''
because it was not removed explicitly there.
See [use] [{ICON}] for how to force the theorem prover to take note
of particular instances of particular theorems; in particular, the
instances are created and added as hypotheses to the subgoal in
question. The hint is not inherited by the descendents of the
subgoal (since the formula being proved has been modified by the
hint). If the rule you are using (with a :use hint) is an enabled
rewrite rule, it might interfere with the added hypothesis -- by
rewriting itself to T -- and thus often you will both :use ... and
:in-theory (disable ...).
See [expand] [{ICON}] for how to tell the theorem prover to expand
one or more function calls whenever encountered.
See [cases] [{ICON}] for how to force the theorem prover to do a case
split to prove the subgoal under each of an exhaustive list of
cases given in the hint. This hint takes action specifically at the
named subgoal and is not passed down to its children.
See [induct] [{ICON}] for how to tell the theorem prover to go
immediately into induction for the subgoal in question, and to use
the induction scheme suggested by the hint rather than the one
suggested by the terms in the subgoal itself. This hint is not
inherited by its descendents.
See [hints] [{ICON}] for a complete list of all hints, and see
[hints-and-the-waterfall] [{ICON}] for a more thorough description
of how the effects of hints at a subgoal are inherited by the
descendents.
If you are reading this as part of the tutorial introduction to the
theorem prover, use your browser's Back Button now to return to
[introduction-to-the-theorem-prover].")
(INTRODUCTION-TO-KEY-CHECKPOINTS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"What questions to ask at key checkpoints
We assume you've read about rewrite rules; see
[introduction-to-rewrite-rules-part-1].
When a proof attempt fails, ACL2 prints some key checkpoints. These
are formulas that we think you should look at. There are two kinds
printed: key checkpoints before an induction, and key checkpoints
under a top-level induction. (Key checkpoints under deeper
inductions and checkpoints that aren't considered ``key'' may exist
in the proof attempt, but ACL2 doesn't print them at the end of
failed proofs because you shouldn't be distracted by them.)
Below is a list of questions to ask yourself about the key
checkpoints. Initially, we recommend just picking one key
checkpoint before an induction (perhaps the simplest looking one)
and asking these questions. These questions may lead you to look at
other key checkpoints. As you gain more experience you'll elaborate
and generalize this advice.
(1) Do you believe this formula is a theorem? If you don't think it
is, it's pointless to try to prove it! You should reconsider your
top-level formula in light of the special case suggested by this
key checkpoint.
(2) Can it be simplified? Is there some combination of function
symbols in it that could be eliminated or simplified by exploiting
some simpler fact? By a ``simpler fact'' we mean a theorem about a
few of the symbols in this formula. For an example of this see
[dealing-with-key-combinations-of-function-symbols]. Don't think
about the deep question ``how can I prove the checkpoint?'' until
you've got it into its simplest form.
(3) Is the simpler fact already in the database? If there is some
simpler fact that would help clean up the checkpoint but you
believe the simpler fact is already in the database, you can use
:[pl] [{ICON}], :[pc] [{ICON}], :[pbt] [{ICON}], and other history
commands to inspect the database; (see [history] [{ICON}]). But if
you find the allegedly relevant simpler fact in the database, you
must ask: why wasn't it used? There are four principal reasons:
(3a) it is disabled -- so enable it; you'll learn how when you read
the coming sections on [introduction-to-the-database] and
[introduction-to-hints].
(3b) its left-hand side doesn't match the target -- so improve the
rule by generalizing its left-hand side or prove a new rule for
this situation; if you decide to remove the old rule from the
database, see undo commands in [history] [{ICON}].
(3c) it is an IFF rule but the target doesn't occur propositionally
-- so see if you you can strengthen the rule to an EQUAL rule or
weaken the context of the target by changing the conjecture to use
the target propositionally; if you decide to remove the old rule
from the database, see undo commands in [history] [{ICON}].
(3d) the hypotheses of the rule cannot be relieved for this
occurrence of the target; this can be caused by the rule's
hypotheses being too strong (requiring more than they should), or
by the hypotheses of the current conjecture being too weak (you
forgot some key hypothesis), or by ACL2 not having the rules it
needs to prove that the conjecture's hypotheses really do imply the
rule's. Tools are available (:see [brr] [{ICON}]) help you figure
out why the rule failed, so use them and improve the rule, or the
current conjecture, or the database as appropriate.
(4) If the simpler fact is not already known, prove it. This means
you must create a new defthm event with appropriate rule-classes to
store your new theorem so that it will be used. See
[dealing-with-key-combinations-of-function-symbols]. Then you must
start using The Method recursively to prove your new lemma.
(5) Otherwise, is this formula something you'd prove by induction? If
you can't simplify it, it may be because you ``need this fact to
prove this fact,'' in which case, induction is the right thing to
do. But first, remember that in order for a formulas to be provable
by induction, it must be very general. Why must it be general?
Because in an inductive proof, the main thing you have to work with
is the induction hypothesis, which is an instance of the theorem
you're proving. If the theorem is not general enough, you won't be
able to assume an instance that will help you. ACL2 may try
induction even on formulas that are not general enough. Don't
assume that the formula is ripe for induction just because ACL2
found an induction to do! Before you ``approve'' a formula for
induction, ask whether it is perhaps a special case of some more
general theorem. See [generalizing-key-checkpoints] now and then
come back here. If you found a generalization, you should probably
be proving that formula instead of this one. So formulate the
appropriate defthm and use The Method recursively to prove it.
(6) If the formula is right for induction, did ACL2 do an induction
for it? You can answer that without looking at the proof. Just see
if there are any key checkpoints after induction. If not, why
didn't ACL2 induct? Perhaps you told ACL2 not to induct! Perhaps no
term in the conjecture suggests an appropriate induction? You could
remedy this by extending ACL2's induction analysis by adding to the
database. Or you could just tell ACL2 what induction to do for this
formula. You'll learn about both later (when you read coming
sections of the tutorial).
(7) If ACL2 did do an induction, was it the right one? You can find
the induction scheme used by reading the first induction message in
the output log after you submitted the conjecture to ACL2. But most
often you will realize the ``wrong'' induction was done just by
looking at the post-induction key checkpoints, keeping in mind that
each is supposed to be a natural special case of the theorem you're
proving. Is the case analysis inappropriate? Are induction
hypotheses missing? If so, you should look at the induction scheme.
If you determine the wrong induction was done, extend ACL2's
induction analysis or tell it which induction to do, which you'll
learn about in the coming sections of the tutorial. For more advice
about looking at post-induction key checkpoints, see
[post-induction-key-checkpoints] now and then come back here.
(8) If the post-induction key checkpoints seems plausible, then
repeat the questions above for each one of them, perhaps starting
with the simplest.
In any case, after successfully taking whatever action you've decided
on, e.g., proving some new lemma and adding it as a rule:
Start over trying to prove your main conjecture. This is important!
Do not just scroll back to the key checkpoints generated the last
time you tried to prove it. Instead, re-generate them in the
context of your new, improved database and hints.
You will be following this general outline almost all of the time
that you're interacting with ACL2. You will not often be asking
``Why is ACL2 making me think about this subgoal? What did ACL2 do
to get here? How does ACL2 work?''
Two other ideas are helpful to keep in mind.
Is a key checkpoint unexpectedly complicated? Pay special attention
to the case where the complication seems to be the introduction of
low-level details you thought you'd dealt with or by the
introduction of symbols you didn't expect to see in this proof.
These can be signs that you ought to disable some rules in the
database (e.g., a definition of a complicated function about which
you've proved all the necessary lemmas or some lemma that
transforms the problem as was appropriate for some other proof).
Does the theorem prover just hang up, printing nothing? If this
happens, you must interrupt it. How you interrupt the prover is
dependent on which Common Lisp and which interface you're using.
But most Common Lisps treat control-c as a console interrupt. If
you're in Emacs running ACL2 as a shell process, you must type
control-c control-c. If you're in ACL2s, hit the Interrupt Session
button. Interrupting ACL2 can leave you in an interactive loop
similar in appearance but different from ACL2's top-level! So pay
careful attention to the prompt and see [breaks] [{ICON}].
Once you've regained control from the ``runaway'' theorem prover,
there are several tools you can use to find out what it is doing in
real-time. Generally speaking, when the theorem prover goes silent
for a very long time it is either in some kind of rewrite loop
caused by rules that cause it to flip back and forth between
various supposedly normal forms, or else it has split the problem
into a huge number of cases and suffering a combinatoric explosion.
See [dmr] [{ICON}] and, perhaps, see [accumulated-persistence]
[{ICON}].
If you are reading this as part of the tutorial introduction to the
theorem prover, use your browser's Back Button now to return to
[introduction-to-the-theorem-prover].")
(INTRODUCTION-TO-REWRITE-RULES-PART-1
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Introduction to ACL2's notion of rewrite rules
Rewrite rules make ACL2 replace one term by another. This is done by
the rewriter, which is part of ACL2's simplifier. The rewriter
sweeps through the goal formula trying all the rewrite rules it
knows. Here's an example. Just pretend that you have made a rewrite
rule from the formula below.
(implies (and (natp i)
(< i (len a)))
(equal (put i v (append a b))
(append (put i v a) b)))
Then every time the rewriter sees a target term that matches
(put i v (append a b))
it considers the rule, with the variables i, v, a, and b of the rule
bound to whatever terms matched them in the target, say the terms
i, v, a, and b. To consider the rule, the rewriter first tries to
establish (``relieve'') the hypotheses. In particular, it rewrites:
(natp i) ; hyp 1
and
(< i (len a)). ; hyp 2
If both hyptheses rewrite to true, then the rule fires and replaces
the target by:
(append (put i v a) b).
In short, rewrite rules direct ACL2 to rearrange the terms in the
goal formulas.
We are more precise later, but for now we turn to the question of how
do you make a rewrite rule from a formula? The answer is, you prove
the formula with the defthm command. Recall that
(defthm name
formula
...)
commands ACL2 to try to prove formula and, if successful, build it
into the database as a rule according to your specification in the
rule-classes argument of the ... part of the command.
To make it easy for you to generate rewrite rules, defthm has a
simple heuristic: if you don't tell it what kind of rule to
generate from formula, it generates a rewrite rule! Thus, if this
command
(defthm name
formula)
is successful, ACL2 will have a new rewrite rule in the database,
even though you did not explicitly tell it to add a rule.
A common mistake for new users is to forget that the above command
adds a rewrite rule. This often results in a tangle of rules that
lead nowhere or to infinite rewriting that you will have to
interrupt. It is also good to remember that the command only adds a
rule. It does not magically make ACL2 aware of all the mathematical
consequences of the formula: it just makes a rewrite rule.
When you prove a theorem with defthm you are programming ACL2. Being
careless in your statement of lemmas is tantamount to being
careless in your programming.
ACL2 can generate rewrite rules from formulas that look like this:
(IMPLIES (AND hyp1 ... hypk)
(eqv lhs rhs))
where eqv is either EQUAL or IFF, and lhs is not a variable symbol,
not a constant, and not a call of the function IF, and not a call
of an abbreviation (``macro'') that expands to any of these. So
illegal lhs include X, 0, (IF X Y Y), and (OR p q). The last is
illegal because OR is just an abbreviation for a certain
IF-expression.
Technical Note: This tutorial introduction to the theorem prover
takes liberties with the truth! We are trying to give you a useful
predictive model of the system without burdening you with all the
details, which are discussed in the ACL2 User's Manual. For
example, using directives in the rule-classes you can rearrange the
proved formula into the form you want your rule to take, and you
can make ACL2 take advantage of equivalence relations eqv other
than just EQUAL and IFF. But we'll ignore these fine points for
now.
We call the hyp terms the hypotheses of the rule. We call lhs the
left-hand side of the rule, and we call rhs the right-hand side of
the rule. If the conclusion of the rule is an EQUAL term we call it
an equality rule. Otherwise, it is a propositional equivalence
rule. If there are no hypotheses, k=0, we say the rule is an
unconditional rewrite rule; otherwise it is conditional.
ACL2 allows several special cases of the shapes above. See
[special-cases-for-rewrite-rules], but come back here and continue.
A rewrite rule makes ACL2 seek out occurrences of terms that match
the left-hand side of the rule and replace those occurrences using
the right-hand side, provided all the hypotheses rewrite to true in
the context of the application of the rule.
That is, the left-hand side is treated as a pattern that triggers the
rule. The hypotheses are conditions that have to be proved in order
for the rule to fire. The right-hand side is the replacement and is
put into the formula where the pattern occurred.
Now for some clarifications. ACL2 only considers enabled rules. And
ACL2 will use a propositional rule to replace a target only if the
target occurs in a propositional place in the formula. Generally
that means it occurs in the argument of a propositional connective,
like AND, OR, NOT, IMPLIES, and IFF, or in the test of an IF. When
we say that the left-hand side of the rule must match the target we
mean that we can instantiate the variables in the rule to make the
left-hand side identical to the target. To relieve or establish the
hypotheses of the rule, ACL2 just applies other rewrite rules to
try to prove the instantiated hypotheses from the assumptions
governing the occurrence of the target. When ACL2 replaces the
target, it replaces it with the instantiated right-hand side of the
rule and then applies rewrite rules to that.
If a hypothesis has variables that do not occur in the left-hand side
of the rule, then the pattern matching process won't find values
for those variables. We call those free variables. They must be
instantiated before ACL2 can relieve that hypothesis. To
instantiate them, ACL2 has to guess values that would make the
hypothesis true in this context, i.e., true given the assumptions
of the goal theorem. So if you're trying to prove
(IMPLIES (AND (TRUE-LISTP A)
(MEMBER (CAR P) A)
(MEMBER (CDR P) A))
...)
and the target you're rewriting is in the ``...'' part of the
formula, the rewriter knows that (TRUE-LISTP A) (MEMBER (CAR P) A)
and (MEMBER (CDR P) A) are true. So if a rewrite rule is considered
and the rule has (member e x) as a hypothesis, where e is a free
variable but x was bound to A in the pattern matching, then it will
guess that e must be (CAR P) or (CDR P), even though there are many
other possibilities that would make (MEMBER e A) true. Of course,
whatever guess it makes must also satisfy all the other hypotheses
that mention e in the rule. It simply isn't very imaginative at
guessing!
The most predictable rewrite rules have no free variables. You can
add pragmatic advice to help ACL2 with free variables, telling it
to try all the possibilities it finds, to try just the first, or
even to compute a ``creative'' guess.
It is possible to make the rewriting process loop forever, e.g., by
rewriting alpha to beta with one set of rules and rewriting beta to
alpha with another. Even a single rule can make the process loop;
we'll show you an example of that later in the tutorial. ACL2 can
handle commutativity rules without looping. It uses (equal (+ x y)
(+ y x)) to replace (+ B A) by (+ A B), but not vice versa. (It is
sensitive to alphabetic ordering when dealing with permutative
rules.)
Logically equivalent formulas can generate radically different
rewrite rules! Rearranging the propositional structure of the
formula or swapping the left and right sides of an equality --
while having no effect on the mathematical meaning of a formula --
can have a drastic impact on the pragmatic meaning as a rule. To
see an illustration of this, see
[equivalent-formulas-different-rewrite-rules].
Developing an effective set of rewrite rules is key to success at
using ACL2. We'll look more at this later in the tutorial.
If you are working your way through the tutorial for the theorem
prover, use your browser's Back Button now to return to
[introduction-to-the-theorem-prover]. If you are reading just about
how to make effective rewrite rules, go on to
[introduction-to-rewrite-rules-part-2].")
(INTRODUCTION-TO-REWRITE-RULES-PART-2
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"How to arrange rewrite rules
You should design your rewrite rules to canonicalize the terms in
your problem, that is, your rules should drive terms into some
normal form so that different but equivalent terms are rewritten
into the preferred shape, making equivalent terms identical. You
are very familiar with this idea from algebra, where you learned to
normalize polynomials. Thus, when you see (2x + 6)(3x - 9) you
automaticaly normalize it, by ``multiplying out and collecting like
terms,'' to get (6x^2 - 54). This normalization strategy allows you
to recognize equivalent terms presented differently, such as 6(x^2
- 9).
The ACL2 user is responsible for making up the rules. (Standard
``books'' -- files of ACL2 definitions and theorems -- can often
provide rules for some sets of functions, e.g., arithmetic.) This
is a heavy burden on you but it means you are in charge of your own
normal forms. For example, if you use the function nthcdr, which
returns the nth cdr of a list, you might see both (cdr (nthcdr i
x)) and (nthcdr i (cdr x)). These two expressions are equivalent
but not identical. You will want to decide which you want to see
and prove the rewrite rule that converts the other to that
preferred form.
Most good users develop an implicit ordering on terms and rewrite
``heavy'' terms to ``lighter'' ones. This insures that there are no
loops in their rewrite rules. But this ordering changes according
to the user and the problem.
Generally, the lightest terms are primitives such as IF, EQUAL,
arithmetic, etc. Functions defined without explicit recursion tend
to be ignored because they are just expanded away (but see below).
Recursively defined functions tend to be heavier than any other
recursive function used in their definitions, so, for example, if
rev is defined in terms of append, rev is heavier than append. But
the size and subtlety of recursively defined functions also affects
their place in the ordering.
But rewrite rules are surprisingly subtle. Recall that a rewrite rule
can be made from a formula of this form:
(IMPLIES (AND hyp1 ... hypk)
(eqv lhs rhs))
where eqv is either EQUAL or IFF, and lhs is a call of a function
other than IF. In such a rule, lhs is the pattern responsible for
triggering the rule, the hypi are conditions which must be
satisfied by the context of the target being rewritten, and rhs is
the replacement. The replacement only happens if the rule is
enabled, the pattern matches, the conditions are satisfied, and (in
the case of an IFF rule) the target occurs propositionally. There
are other heuristic restrictions that we won't discuss here.
So how should you phrase a theorem in order to make it an effective
rule?
General Principles:
* Strengthen the Formula: The fewer hypotheses a formula has the
better the rewrite rule formed from it. The more general the
left-hand side the better the rule. The fewer free variables in the
hypothesis, the better. The idea is to form a rule that fires
predictably. Later in this tutorial you'll get some practice
formulating strong rules.
* Choosing the Conclusion: If a lemma is an implication, you have to
choose what the conclusion will be. (You'll also have to ``orient''
that conclusion by choosing a left-hand side and a right-hand side,
but we discuss that below). You can swap the conclusion and any
hypothesis by negating both, producing a different conclusion.
There are generally two (possibly conflicting) heuristics for
deciding which part of the formula should be the conclusion:
Choosing the Conclusion Heuristic 1: Can you make the conclusion be
an EQUAL or IFF expression that has a ``heavy term'' on one side?
That will make a rule that replaces the heavy term with a lighter
one. We discuss this situation more below.
Choosing the Conclusion Heuristic 2: Can you make the conclusion be a
non-propositional term that contains all the variables mentioned in
the hypotheses? By ``non-propositional'' we mean a term that is not
just the propositional combination (e.g., with AND or OR) of other
terms but instead some call of some ``heavy'' function? If your
conclusion contains all the variables mentioned in the hypotheses,
matching it will instantiate all the variables in the hypotheses.
That way ACL2 will not have to guess instantiations of unbound
variables when it tries to relieve the hypotheses. It is not very
good at guessing.
* Orienting the Conclusion: If the conclusion is an EQUAL or an IFF,
you have to decide which is the left-hand side and which is the
right. If the conclusion is (NOT lhs), then the left-hand side is
lhs and the right-hand side is NIL. If the conclusion is not an
EQUAL, an IFF, or a NOT then the conclusion itself will be the
left-hand side and the right-hand side will be T. If your lemma was
created by looking at Key Checkpoints while using The Method, the
left-hand side should match some term in that checkpoint.
Remember, the left-hand side is the ``trigger'' that will make the
rule fire. It is the pattern that ACL2 will be looking for.
* Pay attention to the free variables: Look at the variables that
occur in the pattern (the left-hand side) and compare them to the
variables that occur in the hypotheses. Does some hypothesis
contain a variable, say v, that is not in the pattern? We call v a
free variable because it will not be assigned a value (``bound'')
by the process of pattern matching. ACL2 will have to guess a value
for v. If some hypothesis contains v as a free variable, ask
whether more than one hypothesis contains v? ACL2 uses the first
hypothesis containing a free v to guide its guess for v. To
``guess'' a value for v, ACL2 uses that hypothesis as a pattern and
tries to match it against the assumptions in the checkpoint formula
being proved. This means that key hypothesis must be in normal
form, to match the rewritten assumptions of the goal. It also means
that you should reorder the hypotheses to put the most unusual
hypothesis containing a free v first in the list of conjuncts. For
example, if v is free in two hypotheses, (natp v) and (member
(nthcdr v a) b), then we recommend putting the member term first.
There are likely to be many terms in the goal satisfying the natp
hypothesis -- or none if natp has expanded to an integer inequality
-- while there are likely to be few terms satisfying the member
hypothesis, especially if a and b are bound by the left-hand side
of the rule.
Here are some (possibly conflicting) heuristics for choosing the
left-hand side:
Choose a Left-Hand Side that Occurs in a Key Checkpoint: If you use
the Method you will tend to do this anyway, because you'll see
terms in the Key Checkpoints that you want to get rid of. But many
moderately experienced users ``look ahead'' to how the proof will
go and formulate a few anticipatory rules with the idea of guiding
ACL2 down the preferred path to the proof. When you do that, you
risk choosing left-hand sides that won't actually arise in the
problem. So when you formulate anticipatory rules, pay special
attention to the functions and terms you put in the left-hand
sides. The next few paragraphs deal with specific cases.
Avoid Non-Recursive Functions in the Left-Hand Side: If the left-hand
side contains a call of a defined function whose definition is not
recursive, then it will almost never match any target in the
formula being rewritten unless the function is disabled. Suppose
for example you have defined SQ so that (SQ x) is (* x x). Suppose
you considered choosing a left-hand side like (+ (SQ x) (SQ y)).
Suppose you hoped it would hit the target (+ (SQ A) (SQ B)) in some
formula. But when ACL2 simplifies the formula, it will first
rewrite that target to
(+ (* A A) (* B B))
by expanding the definition of SQ, since it could do so without
introducing any recursive calls. But now the target won't match
your rule. By choosing a left-hand side that occurs in a Key
Checkpoint (and is not one of a handful of abbreviations ACL2 uses
in its output like AND, NOT), you'll avoid this problem since SQ
will have already been expanded before the Key Checkpoint is
printed.
Disable Non-Recursive Functions: If you insist on a left-hand side
that contains calls of non-recursive functions, remember to disable
those non-recursive functions after you've proved all the rules you
want about them. By disabling SQ you can prevent ACL2 from
expanding the definition as it did above. Sometimes you will define
a function non-recursively to formalize some concept that is common
in your application and you will want to create a sort of algebra
of rules about the function. By all means do so, so you can conduct
your formal reasoning in terms of the concepts you're informally
manipulating. But after proving the required laws, disable the
non-recursive concept so that ACL2 just uses your laws and not the
messy definition.
Choose a Left-Hand Side Already in Simplest Form: This is a
generalization of the advice above. If any rule will rewrite your
left-hand side, it will prevent your rule from matching any target.
For example, if you write a left-hand side like (foo (car (cons x
y))) then it would never match any target! The reason is that even
if (FOO (CAR (CONS A B))) did occur in some goal formula, before
ACL2 would try your rule about foo it will use the obvious rule
about CAR and CONS to transform your imagined target to (FOO A).
Thus, your rule would not match. So you have to keep in mind all
your other rules when you choose a left-hand side (and when you
choose the hypotheses to guide free variable selection). If you
always choose a pattern that matches a term in a Key Checkpoint,
you avoid this problem. Also see [community-books] example
books/demos/knuth-bendix-problem-1.lisp.
Make Sure the Left-Hand Side is ``Heavier'' than the Right: Sometimes
this is obvious, as when you choose (REV (REV x)) for the left-hand
side and x for the right. But what do you about (REV (APPEND x y))
versus (APPEND (REV y) (REV x))? Most of the time we choose to
drive the heaviest function (in this case REV) down toward the
variables, lifting the lighter function (APPEND) up so that we can
reason about the lighter function's interaction with the
surrounding ``matrix'' of the formula. So we'd rewrite (REV (APPEND
x y)) to (APPEND (REV y) (REV x)), not vice versa.
Alternative Ways to Talk About the Same Thing: If your problem and
specification use two different ways to talk about the same thing,
choose one form and rewrite the other into that form. For example,
the ACL2 built-in nth returns the nth element of a list, and the
built-in function nthcdr returns the nth cdr of a list. They are
defined independently. But (nth n x) is the same thing as (car
(nthcdr n x)). Since nth can be expressed in terms of nthcdr but
not vice versa, it is clear we should prove (equal (nth n x) (car
(nthcdr n x))) as a rewrite rule if both nth and nthcdr are
involved in the problem.
Don't Let Computational Efficiency Dictate the Terms: If you have two
functions that are equivalent (perhaps one was defined to be
computationally more efficient), prove their equivalence as a
rewrite rule that eliminates the more complicated function. An
extreme example would be a model that uses a sophisticated data
structure (like a balanced binary tree, red-black tree, ordered
array, or hash table) to implement something simple like an
association of keys to values. By proving the equivalence as stated
you can eliminate the messy function early and do the bulk of your
reasoning in terms of its simple specification.
The best ACL2 users become very good at keeping all these things in
mind when designing their rewrite rules. Practice makes perfect.
Don't be afraid during your learning of ACL2 to undo the rules you
first invented and try to make better ones.
Finally, be patient! There will be times when you think to yourself
``Why should I spend my time thinking of rules that guide ACL2? I
know the proof!'' There are two reasons. First, you may ``know''
the proof but you may well be wrong and part-way through this whole
exercise you may realize that you're missing a major hypothesis or
special case that breaks your whole conception of the problem. The
proof is in the details. Second, most of the time the library of
rules you develop in this process will be used over and over again
on variants of the main problem in the months and years ahead. This
is sometimes called the proof maintenance problem. Theorems don't
suffer bit rot! But the artifacts you're modeling change and you
will need to prove new versions of old theorems. A good general
purpose library makes this much easier.
We now recommend that you practice inventing strong rules; see
[strong-rewrite-rules].
For advice on handling specific kinds of formulas and definitions,
see [specific-kinds-of-formulas-as-rewrite-rules].
For more information about the rewriter works and how rules are
created, see [further-information-on-rewriting].
If you are working your way through the tutorial introduction to the
theorem prover, use your browser's Back Button to return to
[introduction-to-the-theorem-prover].")
(INTRODUCTION-TO-THE-DATABASE
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"How to update the database
We assume you've read [introduction-to-rewrite-rules-part-1] and
[introduction-to-key-checkpoints].
The theorem prover's heuristics are influenced by the database of
rules and the enabled/disabled status of the rules. You can think
of the database as a global hint, potentially affecting all parts
of a proof attempt.
However, in addition to the ``global hint,'' it is possible to give
local hints that affect the theorem prover's behavior on specific
subgoals. We discuss the database here and discuss local hints
later in the tutorial.
The theorem prover's ``database'' is called the ACL2 world. You
change the world by issuing commands called events. The most common
events are defun for defining new functions (and predicates) and
defthm for proving new theorems. Both add rules to the database.
Here are some commonly used events.
We recommend that upon the first reading of this tutorial you do not
follow the links shown below! The links take you into the hypertext
reference manual, where it is easy to get lost unless you're
looking for detail about one specific feature.
See [defun] [{ICON}] to define a new function or predicate symbol.
Definitional axioms are just a kind of rewrite rule, but defun may
also add rules affecting the determination of the type of a term
and rules affecting the induction analysis. When you issue a defun
command you will always supply the name of the function or
predicate, the list of formal parameters, v1,...vn, and the body:
(defun name (v1 ... vn)
body)
If the event is accepted, a definitional axiom is added to the world,
(name v1...vn)=body, stored as a special kind of unconditional
rewrite rule. However, the defun event may require theorems to be
proved. Specifically, measure theorems must be proved to establish
that recursively defined functions always terminate, by proving
that an ordinal measure of the formal parameters decreases in a
well-founded way in every recursive call. In addition, if guards
are being used to declare the expected domain of the newly defined
function, guard theorems might be proved to establish that all
functions stay within their expected domains. In any case, you may
provide additional information to the defun event, coded as part of
the declaration that Common Lisp allows:
(defun name (v1 ... vn)
(declare (xargs ...))
body)
The xargs (``extra arguments to defun'') entry may specify, among
other things, the measure to use in the termination proof, hints
for use by the prover during the termination proof, the guard of
the new function, and hints for use by the prover during the guard
verification step.
See [defthm] [{ICON}] to prove a theorem and to add it as a rule of
one or more specified rule-classes. When you issue a defthm command
you always specify a name for the theorem you're trying to prove
and a formula stating the theorem. You may optionally supply some
local hints as we describe later in the tutorial. You may also
optionally supply some rule classes indicating how you want your
formula stored as a rule, after it is proved. We discuss the defthm
rule classes below.
See [in-theory] [{ICON}] to enable or disable rules. Rules have names
derived from the names you give to functions and theorems, e.g.,
(:REWRITE LEFT-IDENTITY-OF-FOO . 2) for the second rewrite rule you
created from the theorem named LEFT-IDENTITY-OF-FOO. Rule names are
called runes. A theory is just a set (list) of runes. The current
theory is the list of enabled runes and the in-theory event can add
runes to or delete runes from the current theory.
See [include-book] [{ICON}] to change the world by loading a
certified file of other events. The most common use of include-book
is to load ``community books'' -- books written by other ACL2 users
who have released them for distribution to the community. The most
common books loaded are probably the arithmetic books:
; * for the most elementary arithmetic, needed for any problem
; that involves even simple addition and multiplication like
; (+ x (* 2 y) -3):
(include-book \"arithmetic/top-with-meta\" :dir :system)
; * for more complicated arithmetic involving non-linear terms like
; (* x y), (expt x (+ i j)), and floor and mod
(include-book \"arithmetic-5/top\" :dir :system)
But for a complete list of system books, see [books] [{ICON}].
See [certify-book] [{ICON}] to certify a file of events for reuse
later.
See [defconst] [{ICON}] to define a new constant, allowing you to
write a symbol, e.g., *weekdays* in place of some object, e.g.,
'(MON TUE WED THU FRI) in formulas.
See [defmacro] [{ICON}] to define a new syntactic abbreviation. The
macro facility in Lisp is quite powerful, allowing you to compute
the form to which some type-in expands. For example, the primitive
macro COND is defined so that (COND ((P X) 1)((Q X) 2)(T 3))
expands to (IF (P X) 1 (IF (Q X) 2 3)).
See [defstobj] [{ICON}] to introduce a single-threaded object that
your functions may modify ``destructively'' provided they follow
strict syntactic rules.
See [events] [{ICON}] for a complete list of the ACL2 events. There
are events to allow mutually recursive definitions, to introduce
some new function symbols constrained to satisfy given axioms, to
allow the temporary introduction of a ``local'' event to help prove
some goal theorem and then disappear, to provide the power of
first-order quantification and a choice operator, and many other
features.
There are also commands that allow you to inspect the world, e.g., to
print the command that introduced a given name, to show all the
commands back to a certain one, undo the last command or more
generally roll-back to an earlier command. See [history] [{ICON}].
The Defthm Rule-Classes
We've already discussed the key role that rules play in controlling
the behavior of the system. New rules are introduced primiarily
with the defthm event, though defun and other events may introduce
rules.
To prove formula and generate, say a :rewrite rule and a :generalize
rule from it, you would write
(defthm name
formula
:rule-classes (:rewrite :generalize))
If you wanted to rearrange the shape of the formula before generating
the :rewrite rule you could provide a :corollary modifier to the
:rewrite rule class:
(defthm name
formula
:rule-classes ((:rewrite :corollary ...)
:generalize)).
There are many classes of rules, affecting different parts of the
system. Each class is denoted by a keyword, e.g., :REWRITE,
:LINEAR, etc. You are responsible for specifying the class(es) of
rules to be generated from a given formula and several different
rules (possibly of different classes) may be derived from a single
formula. Each class admits optional modifiers that allow you finer
control over each rule. Each class admits the :corollary modifier
with which you can rearrange the formula before a rule of that
class is generated. This allows you to state a theorem in its most
elegant form for publication purposes but store it as a rule with
the most appropriate hypotheses and conclusion. Other modifiers
tend to be specific to certain rule classes, but for example,
:rewrite rule modifiers include an optional limit on the depth of
backchaining and options for handling free variables.
We give some links below to other classes of rules. However, we
recommend that you not follow these links upon your first reading
of this tutorial!
See [rewrite] [{ICON}] for a description of how to create a rewrite
rule.
See [linear] [{ICON}] for a description of how to store theorems
concluding with arithmetic inequalities. The trouble with storing
(<= (len (delete e x)) (len x))
as a rewrite rule is that it only matches instances of that
inequality and thus fails to match
(<= (LEN (DELETE E X)) (+ 1 (LEN X)))
ACL2 contains an extensible linear arithmetic decision procedure and
by storing inequalities as :linear rules you can make that decision
procedure aware of the basic inequalities between non-primitive
numerically valued terms.
See [equivalence] [{ICON}], see [congruence] [{ICON}], and see
[refinement] [{ICON}] to learn how to introduce a new equivalence
relation to the rewriter. For example, suppose you define set-equal
so that it returns t precisely if its two arguments are lists
containing the same elements, regardless of order or number of
occurrences. Note that under this sense of ``equivalence'', (rev x)
is the identity function and append is commutative, for example.
(set-equal (rev x) x)
(set-equal (append x y) (append y x))
You can make ACL2 use these two theorems as :rewrite rules to replace
instances of (REV x) and (APPEND x y) by set-equal terms, even
though the results are not actually EQUAL. This is possible
provided the target occurs in a context admitting set-equal as a
congruence relation. For example, the :congruence rule:
(implies (set-equal a b)
(iff (member e a)
(member e b)))
gives the rewriter permission to use the above set-equal rules as
rewrite rules in the second argument of any member expression being
used in a propositional way.
See [elim] [{ICON}] for a description of how to make the system adopt
a ``change of variable'' tactic that can trade in destructor
functions for constructor functions. In analogy with how ACL2
eliminates (CAR X) and (CDR X) by replacing X with (CONS A B), you
can make it eliminate other destructors. For example, the community
book \"arithmetic-5/top\" provides an elim rule that eliminates
(floor x y) and (mod x y) by replacing x by (+ r (* y q)), so that
the floor expression becomes q and the mod expression becomes r.
When introducing your own elim rules you will probably also need to
introduce generalize rules (see below) so that the new variables
are appropriately constrained.
See [generalize] [{ICON}] for a description of how you can make ACL2
restrict the new variables it introduces when generalizing. ACL2
will sometimes replace a term by a new variable and with generalize
rules you can insure that the new variable symbol has certain
properties of the term it replaces.
See [induction] [{ICON}] for a description of how to tailor the
inductions suggested by a term. Most of the time when ACL2 chooses
the ``wrong'' induction, the easiest fix is with a local :induct
hint (see below). But if the same problem arises repeatedly in
several theorems, you might want to ``educate'' ACL2's induction
heuristic.
For a complete list of rule-classes, See [rule-classes] [{ICON}].
If you are reading this as part of the tutorial introduction to the
theorem prover, use your browser's Back Button now to return to
[introduction-to-the-theorem-prover].")
(INTRODUCTION-TO-THE-TAU-SYSTEM
(TAU-SYSTEM)
"A decision procedure for runtime types
This doc topic is the main source of information about the tau system
and discusses the general idea behind the procedure and how to
exploit it.
A ``Type-Checker'' for an Untyped Language
Because ACL2 is an untyped language it is impossible to type check
it. All functions are total. An n-ary function may be applied to
any combination of n ACL2 objects. The syntax of ACL2 stipulates
that (fn a1...an) is a well-formed term if fn is a function symbol
of n arguments and the ai are well-formed terms. No mention is made
of the ``types'' of terms. That is what is meant by saying ACL2 is
an untyped language.
Nevertheless, the system provides a variety of monadic Boolean
function symbols, like [natp], [integerp], [alistp], etc., that
recognize different ``types'' of objects at runtime. Users
typically define many more such recognizers for domain-specific
``types.'' Because of the prevalence of such ``types,'' ACL2 must
frequently reason about the inclusion of one ``type'' in another.
It must also reason about the consequences of functions being
defined so as to produce objects of certain ``types'' when given
arguments of certain other ``types.''
Because the word ``type'' in computer science tends to imply
syntactic or semantic restrictions on functions, we avoid using
that word henceforth. Instead, we just reason about monadic Boolean
predicates. You may wish to think of ``tau'' as synonymous with
``type'' but without any suggestion of syntactic or semantic
restrictions.
Design Philosophy
The following basic principles were kept in mind when developing tau
checker and may help you exploit it.
(1) The tau system is supposed to be a lightweight, fast, and helpful
decision procedure for an elementary subset of the logic focused on
monadic predicates and function signatures.
(2) Most subgoals produced by the theorem prover are not in any
decidable subset of the logic! Thus, decision procedures fail to
prove the vast majority of the formulas they see and will be net
time-sinks if tried too often no matter how fast they are.
Tau reasoning is used by the prover as part of preprocess-clause, one
of the first proof techniques the system tries. The tau system
filters out ``obvious'' subgoals. The tau system is only tried when
subgoals first enter the waterfall and when they are stable under
simplification.
(3) The tau system is ``benign'' in the sense that the only way it
contributes to a proof is to eliminate (prove!) subgoals. It does
not rewrite, simplify, or change formulas. Tau reasoning is not
used by the rewriter. The tau system either eliminates a subgoal by
proving it or leaves it unchanged.
(4) It is impossible to infer automatically the relations between
arbitrary recursively defined predicates and functions. Thus, the
tau system's knowledge of tau relationships and function signatures
is gleaned from theorems stated by the user and proved by the
system.
(5) Users wishing to build effective ``type-checkers'' for their
models must learn how rules affect the tau system's behavior. There
are two main forms of tau rules: those that reveal
inclusion/exclusion relations between named tau predicates, e.g.,
that 16-bit naturals are also 32-bit naturals,
(implies (n16p x) (n32p x)),
and signatures for all relevant functions, e.g., writing a 32-bit
natural to a legal slot in a register file produces a register
file:
(implies (and (natp n)
(< n 16)
(n32p val)
(register-filep regs))
(register-filep (update-nth n val regs))).
For a complete description of acceptable forms see :[tau-system].
(6) The tau system is ``greedy'' in its efforts to augment its
database. Its database is potentially augmented when rules of any
:rule-class (see :[rule-classes]) are proved. For example, if you
make a :[rewrite] or :[type-prescription] rule which expresses a
relationship between one tau and another (e.g., that (P x) implies
(Q x)), ACL2 will build it into the tau database. The rule-class
:[tau-system] can be used to add a rule to the tau database without
adding any other kind of rule.
(7) Greediness is forced into the design by benignity: the tau system
may ``know'' some fact that the rewriter does not, and because tau
reasoning is not used in rewriting, that missing fact must be
conveyed to the rewriter through some other class of rule, e.g., a
:[rewrite] or :[type-prescription] or :[forward-chaining] rule. By
making the tau system greedy, we allow the user to program the
rewriter and the tau system simultaneously while keeping them
separate. However, this means you must keep in mind the effects of
a rule on both the rewriter and the tau system and use
:[tau-system] rules explicitly when you want to ``talk'' just to
the tau system.
(8) Tau rules are built into the database with as much preprocessing
as possible (e.g., the system transitively closes
inclusion/exclusion relationships at rule-storage time) so the
checker can be fast.
(9) For speed, tau does not track dependencies and is not sensitive
to the enabled/disabled status (see [enable] and [disable]) of
rules, other than [executable-counterpart] rules. Once a fact has
been built into the tau database, the only way to prevent that fact
from being used is by disabling the entire tau system, by disabling
(:[executable-counterpart] tau-system). If any tau reasoning is
used in a proof, the rune (:[executable-counterpart] tau-system) is
reported in the summary. For a complete list of all the runes in
the tau database, evaluate (global-val 'tau-runes (w state)). Any
of these associated theorems could have been used.
These design criteria are not always achieved! For example, the tau
system's ``greediness'' can be turned off (see
[set-tau-auto-mode]), the tau database can be regenerated from
scratch to ignore disabled rules (see [regenerate-tau-database]),
and disabling the [executable-counterpart] of a tau predicate
symbol will prevent the tau system from trying to run the predicate
on constants. The tau system's benignity can be frustrating since
it might ``know'' something the rewriter does not. More
problematically, the tau system is not always ``fast'' and not
always ``benign!'' The typical way tau reasoning can slow a proof
down is by evaulating expensive tau predicates on constants. The
typical way tau reasoning can hurt a previously successful proof is
by proving some subgoals (!) and thus causing the remaining
subgoals to have different [clause-identifier]s, thus making
explicit hints no longer applicable. We deal with such problems in
[dealing-with-tau-problems].
Technical Details
The tau system consists of both a database and an algorithm for using
the database. The database contains theorems that match certain
schemas allowing them to be stored in the tau database. Roughly
speaking the schemas encode ``inclusion'' and ``exclusion''
relations, e.g., that natp implies integerp and that integerp
implies not consp, and they encode ``signatures'' of functions,
e.g., theorems that relate the output of a function to the input,
provided only tau predicates are involved.
By ``tau predicates'' we mean the application of a monadic
Boolean-valued function symbol, the equality of something to a
quoted constant, an arithmetic ordering relation between something
and a rational constant, or the logical negation of such a term.
Here are some examples of tau predicates:
(natp i)
(not (consp x))
(equal y 'MONDAY)
(not (eql 23 k))
(< 8 max)
(<= max 24)
Synonyms for [equal] include [=], [eq], and [eql]. Note that negated
equalites are also allowed. The arithmetic ordering relations that
may be used are [<], [<=], [>=], and [>]. One of the arguments to
every arithmetic ordering relation must be an integer or rational
constant for the term to be treated as a tau predicate.
A ``tau'' is a data object representing a set of signed (positive or
negative) tau predicates whose meaning is the conjunction of the
literals in the set.
When we say that a term ``has'' a given tau we mean the term
satisfies all of the recognizers in that tau.
The tau algorithm is a decision procedure for the logical theory
described (only) by the rules in the database. The algorithm takes
a term and a list of assumptions mapping subterms (typically
variable symbols) to tau, and returns the tau of the given term.
When the system is called upon to decide whether a term satisfies a
given monadic predicate, it computes the tau of the term and asks
whether the predicate is in that set. More generally, to determine
if a term satisfies a tau, s, we compute a tau, r, for the term and
ask whether s is a subset of r. To determine whether a constant, c,
satisfies tau s we apply each of the literals in s to c. Evaluation
might, of course, be time-consuming for complex user-defined
predicates.
The tau database contains rules derived from definitions and theorems
stated by the user. See :[tau-system] for a description of the
acceptable forms of tau rules.
To shut off the greedy augmentation of the tau database, see
[set-tau-auto-mode]. This may be of use to users who wish to
tightly control the rules in the tau database. To add a rule to the
tau database without adding any other kind of rule, use the rule
class :[tau-system].
There are some slight complexities in the design related to how we
handle events with both :tau-system corollaries and corollaries of
other :rule-classes, see [set-tau-auto-mode].
To prevent tau reasoning from being used, disable the
:[executable-counterpart] of tau-system, i.e., execute
(in-theory (disable (:executable-counterpart tau-system)))
or, equivalently,
(in-theory (disable (tau-system)))
To prevent tau from being used in the proof of a particular subgoal,
locally disable the :[executable-counterpart] of tau-system with a
local :in-theory hint (see [hints]).
The event command [tau-status] is a macro that can be used to toggle
both whether tau reasoning is globally enabled and whether the tau
database is augmented greedily. For example, the event
(tau-status :system nil :auto-mode nil)
prevents the tau system from being used in proofs and prevents the
augmentation of the tau database by rules other than those
explicitly labeled :[tau-system].
To see what the tau system ``knows'' about a given function symbol
see [tau-data]. To see the entire tau database, see [tau-database].
To regenerate the tau database using only the runes listed in the
current enabled theory, see [regenerate-tau-database].
Subtopics
[Dealing-with-tau-problems]
Some advice on dealing with problems caused by the tau system
[Future-work-related-to-the-tau-system]
Some tau system problems that we hope someone will address
[Regenerate-tau-database]
Regenerate the tau database relative to the current enabled theory")
(INTRODUCTION-TO-THE-THEOREM-PROVER
(ACL2-TUTORIAL)
"How the theorem prover works -- level 0
Software is complex, and ACL2 is a piece of software that is used to
analyze software -- adding another layer of complexity.
Furthermore, instead of being limited to static analysis for
certain fixed properties, ACL2 allows you -- indeed, forces you --
to formalize the problem and the questions. It ``knows'' nothing
inherent about your problem before you start to interact with it.
But it can be used to help answer the most complicated questions
you can ask about software.
All this is to say that it is not the kind of tool that you just
install and then start to use effectively. So OK, you've installed
it or confirmed that you can invoke it. Good for you. Now you have
to learn how to use it! Your success ultimately comes down to your
understanding of your problem domain and your appropriate
exploitation of ACL2's strengths and avoidance of its weaknesses.
So put aside the idea of sitting down and interacting with it.
Instead, learn about it.
We assume you know some of the [industrial applications] of ACL2.
Realizing that such things can be done may sustain you during the
long learning curve! We also assume you have taken both the [Flying
Tour] and the [Walking Tour]. The tours give you a good overview of
the whole system where this tutorial focuses on how to use the
prover itself.
If you haven't visited these links, please do so now.
This tutorial will take you several hours -- maybe several days -- to
work through. Do not breeze through it as you might a blog. Think
your way through it. Remember what you read. Do not take short
cuts. If you start to use ACL2 before you really know how, it will
only frustrate you.
We recommend that you read this tutorial with an HTML browser so that
you can see which links you've followed and which you have not. To
give you a sense of what is in store, here is a map of this
document. But don't navigate through it from here! Read it
linearly, following the links when the text directs you to.
[introduction-to-the-theorem-prover]
[introduction-to-rewrite-rules-part-1]
[special-cases-for-rewrite-rules]
[equivalent-formulas-different-rewrite-rules]
[introduction-to-key-checkpoints]
[dealing-with-key-combinations-of-function-symbols]
[generalizing-key-checkpoints]
[post-induction-key-checkpoints]
[introduction-to-rewrite-rules-part-2]
[strong-rewrite-rules]
[practice-formulating-strong-rules]
[practice-formulating-strong-rules-1]
[practice-formulating-strong-rules-2]
[practice-formulating-strong-rules-3]
[practice-formulating-strong-rules-4]
[practice-formulating-strong-rules-5]
[practice-formulating-strong-rules-6]
[specific-kinds-of-formulas-as-rewrite-rules]
[further-information-on-rewriting]
[introduction-to-the-database]
[introduction-to-hints]
[introduction-to-a-few-system-considerations]
[introductory-challenges]
[introductory-challenge-problem-1]
[introductory-challenge-problem-2]
[introductory-challenge-problem-3]
(there are others but at least do a few)
[frequently-asked-questions-by-newcomers]
If any of the links above are marked as ``visited'' by your browser,
use your browser's tools menu to mark all links as unvisited. As
you can see, we really think you'll get the most out of this
document if you take it seriously. As you read, you will see some
links to ``advanced'' topics. These are marked with a tiny warning
sign, ``[{ICON}]''. They lead out of this linear tutorial and into
ACL2's hypertext reference manual. We recommend that you not visit
any of these advanced links until you have read the entire tutorial
at least once.
After you finish this tutorial material, we recommend that you look
at the ACL2 Demos, at the ``Demos'' link of the {ACL2 home page |
http://www.cs.utexas.edu/users/moore/acl2}.
Most users of ACL2 have bought the book
Computer-Aided Reasoning: An Approach, Kaufmann, Manolios, and Moore,
Kluwer Academic Publishers, June, 2000
which is available {in paperback |
http://www.lulu.com/content/1746161} from Lulu for approximately
$20 (as of 2010). That book contains hundreds of exercises in
programming, proof, and using The Method described here to prove
theorems. Solutions to the exercises are online, as are {appendices
|
http://link.springer.com/content/pdf/bbm%3A978-1-4615-4449-4%2F1.pdf}
that focus on some practical usage aspects. See this { web page
about the book |
http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books},
which also includes information about its companion (also available
on Lulu) describing applications of ACL2, some of which are from
industry.
Using ACL2 is akin to having a partner in the theorem proving
enterprise. It will do some of the work and you will do some of the
work. It can't really be any other way because theorem proving is
undecidable. You bring a quirkly, error-prone, creative insight to
the problem, and ACL2 brings accuracy, logic, and perserverance.
Here we describe a ``model'' of how the system works and introduce
some of the ideas and terminology you'll use repeatedly when
interacting with it.
This article is about the theorem prover itself, not the programming
language and not the logic. We assume you know enough about the
ACL2 programming language that you can define simple functions, run
them, and read and write ACL2 constants and terms. For some
examples of what we'll take for granted about ACL2 programming, see
[programming-knowledge-taken-for-granted].
We also assume you know enough about logic to understand, for
example, the words we use to talk about formulas and proofs. To see
some examples of what we'll take for granted about your knowledge
of logic terminology, see [logic-knowledge-taken-for-granted].
When you give the theorem prover a goal formula to prove, it tries to
prove it by breaking it down into subgoals, each of which must be
proved in order to prove the original goal. This breaking apart of
the goal is done by various proof techniques built into ACL2.
Different proof techniques break the formula apart in different
ways. For example, the simplifier rips apart the propositional
structure to isolate the various cases and applies rewrite rules to
simplify the subterms of the formula, while the induction engine
will attempt to break the goal into some base cases and some
induction steps.
The theorem prover's behavior is affected by a database of rules
derived from axioms, definitions, and previously proved theorems.
The database also records the enabled status of each rule; only
enabled rules are seen by the prover and you can set the status of
a rule. There are many other user-settable switches and parameters
affecting the behavior of the prover; you'll learn about some of
them later.
You guide the theorem prover most of the time simply by identifying
lemmas for it to prove. (A lemma is just a theorem that you think
is useful in the proofs of other theorems.)
Why does this guide the theorem prover? Because every time you get
the system to prove a theorem, it turns the theorem into a rule
(unless you tell it not to) and stores the rule in the database.
That changes how the prover behaves subsequently. But you determine
the kind of rule ACL2 stores.
To learn to ``drive'' the theorem prover you have to learn how
various rules affect the system's behavior and how it turns proved
formulas into rules. But before we discuss this, we discuss a more
mathematical activity: how do you figure out the lemmas ACL2 will
need in order for it to prove interesting theorems? ACL2 can often
help you in this activity, if you use it in the right way.
Here is the way we recommend you use ACL2.
The Method.
(1) you present ACL2 with the goal conjecture to prove
(2) typically, it fails to prove it (or you abort its attempt), but
it prints some Key Checkpoints
(3) you look at the Key Checkpoints and decide that you know a fact
that will help; this tutorial will present some helpful questions
to keep in mind
(4) you formalize your knowledge as a formula, along with directions
for how ACL2 should turn the formula into a rule; this tutorial
will tell you about the most commonly used rule, the rewrite rule
(5) you recursively apply The Method to get ACL2 to prove your
formula and to store it as the kind of rule you specified
(6) go to step (1)
Caveat: This approach simply won't work on some theorems! Basically,
this is a ``troubleshooting'' approach, where you're letting ACL2
determine the basic strategy and you're just helping with the
subgoals. But for some theorems, ACL2's approach will be misguided
and no amount of troubleshooting will salvage its strategy. You'll
have a sense that this is happening when it happens because the
formulas ACL2 presents to you will raise issues that feel
irrelevant to you. The basic truth is that if you think a formula
is always true there are usually strong intuitive reasons behind
your belief. If you were asked to defend your belief, you'd start
to explain your reasons and with training you can turn that into a
proof. So when ACL2's formulas present you with things you haven't
thought of either (a) you'll have an ``Ah ha!'' moment when you
realize you hadn't considered that case or (b) you'll realize that
ACL2's approach is different from your intuitive ``proof.''
But, surprisingly often, the troubleshooting approach to finding
proofs works quite well, especially as you rein in your
expectations and develop a sense of what ACL2 can handle on its
own. Of course, if you can decompose the proof into a couple of
main lemmas before you start, so much the better: write down your
sequence of lemmas, thinking about the rules you want them to
generate, and get ACL2 to prove each of them before giving it the
main theorem. This proof planning approach will gradually become an
integral part of your use of The Method.
The only mechanized help we can offer with The Method, aside from the
theorem prover itself, are tools to help you manage the stack of
subgoals it generates when, in step (5) you recursively apply The
Method to a lemma. There are both Emacs and Eclipse tools
available.
To use The Method you have to read the Key Checkpoints printed at the
very end of failed proof attempts, just after the line that reads:
The key checkpoint goals, below, may help you to debug this failure.
Most users do not read the output from successful proofs and do not
read the output during a proof -- they just let it stream by as a
sort of gestalt meter on the theorem prover's progress or lack
thereof. For example, you'll be able to tell it is in a loop and
needs to be interrupted.
You will respond to most Key Checkpoints by formulating new lemmas
for the system to prove and store as rules designed by you to alter
ACL2's behavior so that it proves the Key Checkpoints. You will
give each lemma a name and write some formula to express the
mathematical idea. You'll command ACL2 to prove it by typing:
(defthm name
formula
...)
In the ``...'' you may provide two other kinds of information: hints
for how to prove formula and directives, called rule-classes, for
how to convert formula into a rule after it has proved formula.
Note that you are in charge of determining what kind of rule ACL2
generates! There are over a dozen different types of rules with
many opportunities to specialize each type. But the most common
kind of rule you'll want to generate is a rewrite rule.
We recommend that you read the following topics in the following
order, without skipping anything except links into the ACL2 User's
Manual, which are marked by the little warning sign, ``[{ICON}]''.
(1) See [introduction-to-rewrite-rules-part-1] to read about the use
and design of rewrite rules.
(2) See [introduction-to-key-checkpoints] to see how to use The
Method to help you design rules.
(3) See [introduction-to-rewrite-rules-part-2] for general guidance
on how to turn formulas into effective rules.
(4) See [introduction-to-the-database] to see how to issue commands
that build different kinds of rules and that affect the enabled
status of existing rules.
(5) See [introduction-to-hints] to see how to give the prover hints
for how to prove specific theorems or even subgoals of specific
proof attempts.
(6) See [introduction-to-a-few-system-considerations] for a few words
about system aspects of interacting with ACL2.
(7) See [introductory-challenges] for a graduated sequence of good
challenge problems for the new user to tackle. Do not skip this
section! It is here that you really learn how to use ACL2 -- by
using it.
(8) See [frequently-asked-questions-by-newcomers] for a list of
questions that new users frequently ask, answered mainly by
providing links into the ACL2 User's Manual. We recommend that you
skim through these questions and remember that you can find the
answers here later. We are very interested in receiving suggestions
for how to improve this FAQ and this tutorial. See the ACL2 home
page, specifically the link ``Mailing Lists''.
Please read all of the material cited above (skipping only the ACL2
User's Manual links (``[{ICON}]'')) before you try to use ACL2 on
problems of your own.
By this point you should have read, at least, the following topics
from this tutorial introduction to the theorem prover:
[introduction-to-the-theorem-prover]
[introduction-to-rewrite-rules-part-1]
[special-cases-for-rewrite-rules]
[equivalent-formulas-different-rewrite-rules]
[introduction-to-key-checkpoints]
[dealing-with-key-combinations-of-function-symbols]
[generalizing-key-checkpoints]
[post-induction-key-checkpoints]
[introduction-to-rewrite-rules-part-2]
[strong-rewrite-rules]
[practice-formulating-strong-rules]
[practice-formulating-strong-rules-1]
[practice-formulating-strong-rules-2]
[practice-formulating-strong-rules-3]
[practice-formulating-strong-rules-4]
[practice-formulating-strong-rules-5]
[practice-formulating-strong-rules-6]
[specific-kinds-of-formulas-as-rewrite-rules]
[further-information-on-rewriting]
[introduction-to-the-database]
[introduction-to-hints]
[introduction-to-a-few-system-considerations]
[introductory-challenges]
[introductory-challenge-problem-1]
[introductory-challenge-problem-2]
[introductory-challenge-problem-3]
(there are others but at least do a few)
[frequently-asked-questions-by-newcomers]
We also recommend that you look at the ACL2 Demos mentioned in the
[ACL2-tutorial].
Most users of ACL2 have bought the book
Computer-Aided Reasoning: An Approach, Kaufmann, Manolios, and Moore,
Kluwer Academic Publishers, June, 2000
which is {available in paperback from Lulu |
http://www.lulu.com/content/1746161} for approximately $20 (as of
2010). That book contains hundreds of exercises in programming,
proof, and using The Method to prove theorems. Solutions to the
exercises are online. See also this { web page about the book |
http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books},
which also includes information about its companion (also available
on Lulu) describing applications of ACL2, some of which are from
industry.
Thank you for spending the time to get acquainted with the basics of
the ACL2 theorem prover. Don't hesitate to send further questions
to the ACL2 Help address on the ``Mailing Lists'' link of the ACL2
home page.
End of Tutorial Introduction to the Theorem Prover
Below is a list of all of the topics cited on this page.
Subtopics
[Architecture-of-the-prover]
A simple overview of how the prover works
[Dealing-with-key-combinations-of-function-symbols]
How to get rid of key combinations of function symbols
[Equivalent-formulas-different-rewrite-rules]
Logically equivalent formulas can generate radically different rules
[Example-induction-scheme-binary-trees]
Induction on binary trees
[Example-induction-scheme-down-by-2]
Induction downwards 2 steps at a time
[Example-induction-scheme-nat-recursion]
Induction on natural numbers
[Example-induction-scheme-on-lists]
Induction on lists
[Example-induction-scheme-on-several-variables]
Induction on several variables
[Example-induction-scheme-upwards]
Induction upwards
[Example-induction-scheme-with-accumulators]
Induction scheme with accumulators
[Example-induction-scheme-with-multiple-induction-steps]
Induction scheme with more than one induction step
[Example-inductions]
Some examples of induction schemes in ACL2
[Frequently-asked-questions-by-newcomers]
Some questions newcomers frequently ask
[Further-information-on-rewriting]
A grab bag of advice and information on rewriting
[Generalizing-key-checkpoints]
Getting rid of unnecessary specificity
[Introduction-to-a-few-system-considerations]
The mechanics of interaction with the theorem prover
[Introduction-to-hints]
How to provide hints to the theorem prover
[Introduction-to-key-checkpoints]
What questions to ask at key checkpoints
[Introduction-to-rewrite-rules-part-1]
Introduction to ACL2's notion of rewrite rules
[Introduction-to-rewrite-rules-part-2]
How to arrange rewrite rules
[Introduction-to-the-database]
How to update the database
[Introductory-challenge-problem-1]
Challenge problem 1 for the new user of ACL2
[Introductory-challenge-problem-1-answer]
Answer to challenge problem 1 for the new user of ACL2
[Introductory-challenge-problem-2]
Challenge problem 2 for the new user of ACL2
[Introductory-challenge-problem-2-answer]
Answer to challenge problem 2 for the new user of ACL2
[Introductory-challenge-problem-3]
Challenge problem 3 for the new user of ACL2
[Introductory-challenge-problem-3-answer]
Answer to challenge problem 3 for the new user of ACL2
[Introductory-challenge-problem-4]
Challenge problem 4 for the new user of ACL2
[Introductory-challenge-problem-4-answer]
Answer to challenge problem 4 for the new user of ACL2
[Introductory-challenges]
Challenge problems for the new ACL2 user
[Logic-knowledge-taken-for-granted]
Background knowledge in ACL2 logic for theorem prover tutorial
[Logic-knowledge-taken-for-granted-base-case]
A brief explanation of base cases
[Logic-knowledge-taken-for-granted-equals-for-equals]
Substitution of equals for equals
[Logic-knowledge-taken-for-granted-evaluation]
Evaluation during proofs
[Logic-knowledge-taken-for-granted-inductive-proof]
A brief explanation of induction
[Logic-knowledge-taken-for-granted-instance]
A brief explanation of substitution instances
[Logic-knowledge-taken-for-granted-propositional-calculus]
A brief explanation of propositional calculus
[Logic-knowledge-taken-for-granted-q1-answer]
The inductive step of the rev-rev proof -- Answer to Question 1
[Logic-knowledge-taken-for-granted-q2-answer]
The inductive step of the rev-rev proof -- Answer to Question 2
[Logic-knowledge-taken-for-granted-q3-answer]
The inductive step of the rev-rev proof -- Answer to Question 2
[Logic-knowledge-taken-for-granted-rewriting]
A brief explanation of rewriting from the logical perspective
[Logic-knowledge-taken-for-granted-rewriting-repeatedly]
Further information on expanding definitions via rewriting
[Post-induction-key-checkpoints]
Reading post-induction key checkpoints
[Practice-formulating-strong-rules]
A few simple checkpoints suggesting strong rules
[Practice-formulating-strong-rules-1]
Rules suggested by ([TRUE-LISTP] ([APPEND] (FOO A) (BAR B)))
[Practice-formulating-strong-rules-2]
Rules suggested by ([TRUE-LISTP] (REV (FOO A)))
[Practice-formulating-strong-rules-3]
Rules suggested by ([MEMBER] (FOO A) ([APPEND] (BAR B) (MUM C)))
[Practice-formulating-strong-rules-4]
Rules suggested by ([SUBSETP] ([APPEND] (FOO A) (BAR B)) (MUM C))
[Practice-formulating-strong-rules-5]
Rules suggested by ([SUBSETP] (FOO A) ([APPEND] (BAR B) (MUM C)))
[Practice-formulating-strong-rules-6]
Rules suggested by ([MEMBER] (FOO A) (NATS-BELOW (BAR B)))
[Programming-knowledge-taken-for-granted]
Background knowledge in ACL2 programming for theorem prover tutorial
[Special-cases-for-rewrite-rules]
Convenient short forms for rewrite rule formulas
[Specific-kinds-of-formulas-as-rewrite-rules]
Advice about how to handle commonly occurring formulas as rewrite
rules
[Strong-rewrite-rules]
Formulating good rewrite rules")
(INTRODUCTORY-CHALLENGE-PROBLEM-1
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Challenge problem 1 for the new user of ACL2
Start in a fresh ACL2, either by restarting your ACL2 image from
scratch or executing
:ubt! 1
which will undo everything since the first user event.
Then define this function:
(defun rev (x)
(if (endp x)
nil
(append (rev (cdr x)) (list (car x)))))
Then use The Method to prove:
(defthm triple-rev
(equal (rev (rev (rev x))) (rev x)))
When you've solved this problem, compare your answer to ours; see
[introductory-challenge-problem-1-answer].
Then, use your browser's Back Button to return to
[introductory-challenges].")
(INTRODUCTORY-CHALLENGE-PROBLEM-1-ANSWER
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Answer to challenge problem 1 for the new user of ACL2
This answer is in the form of an ACL2 script sufficient to lead ACL2
to a proof.
(defun rev (x)
(if (endp x)
nil
(append (rev (cdr x)) (list (car x)))))
; Trying triple-rev at this point produces a key checkpoint containing
; (REV (APPEND (REV (CDR X)) (LIST (CAR X)))), which suggests:
(defthm rev-append
(equal (rev (append a b))
(append (rev b) (rev a))))
; And now triple-rev succeeds.
(defthm triple-rev
(equal (rev (rev (rev x))) (rev x)))
; An alternative, and more elegant, solution is to prove the rev-rev
; instead of rev-append:
; (defthm rev-rev
; (implies (true-listp x)
; (equal (rev (rev x)) x)))
; Rev-rev is also discoverable by The Method because it is
; suggested by the statement of triple-rev itself: rev-rev
; simplifies a simpler composition of the functions in triple-rev.
; Both solutions produce lemmas likely to be of use in future proofs
; about rev.
Use your browser's Back Button now to return to
[introductory-challenge-problem-1].")
(INTRODUCTORY-CHALLENGE-PROBLEM-2
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Challenge problem 2 for the new user of ACL2
Start in a fresh ACL2, either by restarting your ACL2 image from
scratch or executing :ubt! 1.
Use The Method to prove
(defthm subsetp-reflexive
(subsetp x x))
When you've solved this problem, compare your answer to ours; see
[introductory-challenge-problem-2-answer].
Then, use your browser's Back Button to return to
[introductory-challenges].")
(INTRODUCTORY-CHALLENGE-PROBLEM-2-ANSWER
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Answer to challenge problem 2 for the new user of ACL2
This answer is in the form of a script sufficient to lead ACL2 to a
proof.
; Trying subsetp-reflexive at this point produces the key checkpoint:
; (IMPLIES (AND (CONSP X)
; (SUBSETP (CDR X) (CDR X)))
; (SUBSETP (CDR X) X))
; which suggests the generalization:
(defthm subsetp-cdr
(implies (subsetp a (cdr b))
(subsetp a b)))
; And now subsetp-reflexive succeeds.
(defthm subsetp-reflexive
(subsetp x x))
; A weaker version of the lemma, namely the one in which we
; add the hypothesis that b is a cons, is also sufficient.
; (defthm subsetp-cdr-weak
; (implies (and (consp b)
; (subsetp a (cdr b)))
; (subsetp a b)))
; But the (consp b) hypothesis is not really necessary in
; ACL2's type-free logic because (cdr b) is nil if b is
; not a cons. For the reasons explained in the tutorial, we
; prefer the strong version.
Use your browser's Back Button now to return to
[introductory-challenge-problem-2].")
(INTRODUCTORY-CHALLENGE-PROBLEM-3
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Challenge problem 3 for the new user of ACL2
Start in a fresh ACL2, either by restarting your ACL2 image from
scratch or executing :ubt! 1.
Define the following functions and use The Method to prove the
theorem at the bottom:
(defun rev (x)
(if (endp x)
nil
(append (rev (cdr x)) (list (car x)))))
(defun dupsp (x) ; does x contain duplicate elements?
(if (endp x)
nil
(if (member (car x) (cdr x))
t
(dupsp (cdr x)))))
(defthm dupsp-rev
(equal (dupsp (rev x)) (dupsp x)))
When you've solved this problem, compare your answer to ours; see
[introductory-challenge-problem-3-answer].
Then, use your browser's Back Button to return to
[introductory-challenges].")
(INTRODUCTORY-CHALLENGE-PROBLEM-3-ANSWER
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Answer to challenge problem 3 for the new user of ACL2
This answer is in the form of a script sufficient to lead ACL2 to a
proof.
; Trying dupsp-rev at this point produces the key checkpoint:
; (IMPLIES (AND (CONSP X)
; (NOT (MEMBER (CAR X) (CDR X)))
; (EQUAL (DUPSP (REV (CDR X)))
; (DUPSP (CDR X))))
; (EQUAL (DUPSP (APPEND (REV (CDR X)) (LIST (CAR X))))
; (DUPSP (CDR X))))
; which suggests the lemma
; (defthm dupsp-append
; (implies (not (member e x))
; (equal (dupsp (append x (list e)))
; (dupsp x))))
; However, attempting to prove that, produces a key checkpoint
; containing (MEMBER (CAR X) (APPEND (CDR X) (LIST E))).
; So we prove the lemma:
(defthm member-append
(iff (member e (append a b))
(or (member e a)
(member e b))))
; Note that we had to use iff instead of equal since
; member is not a Boolean function.
; Having proved this lemma, we return to dupsp-append and succeed:
(defthm dupsp-append
(implies (not (member e x))
(equal (dupsp (append x (list e)))
(dupsp x))))
; So now we return to dups-rev, expecting success. But it fails
; with the same key checkpoint:
; (IMPLIES (AND (CONSP X)
; (NOT (MEMBER (CAR X) (CDR X)))
; (EQUAL (DUPSP (REV (CDR X)))
; (DUPSP (CDR X))))
; (EQUAL (DUPSP (APPEND (REV (CDR X)) (LIST (CAR X))))
; (DUPSP (CDR X))))
; Why wasn't our dupsp-append lemma applied? We have two choices here:
; (1) Think. (2) Use tools.
; Think: When an enabled rewrite rule doesn't fire even though the
; left-hand side matches the target, the hypothesis couldn't be
; relieved. The dups-append rule has the hypothesis (not
; (member e x)) and after the match with the left-hand side, e
; is (CAR X) and x is (REV (CDR X)). So the system
; couldn't rewrite (NOT (MEMBER (CAR X) (REV (CDR X)))) to true,
; even though it knows that (NOT (MEMBER (CAR X) (CDR X))) from
; the second hypothesis of the checkpoint. Obviously, we need to
; prove member-rev below.
; Use tools: We could enable the ``break rewrite'' facility, with
; ACL2 !>:brr t
; and then install an unconditional monitor on the rewrite rule
; dupsp-append, whose rune is (:REWRITE DUPSP-APPEND), with:
; :monitor (:rewrite dupsp-append) t
; Then we could re-try our main theorem, dupsp-rev. At the resulting
; interactive break we type :eval to evaluate the attempt to relieve the
; hypotheses of the rule.
; (1 Breaking (:REWRITE DUPSP-APPEND) on
; (DUPSP (BINARY-APPEND (REV #) (CONS # #))):
; 1 ACL2 >:eval
; 1x (:REWRITE DUPSP-APPEND) failed because :HYP 1 rewrote to
; (NOT (MEMBER (CAR X) (REV #))).
; Note that the report above shows that hypothesis 1 of the rule
; did not rewrite to T but instead rewrote to an expression
; involving (member ... (rev ...)). Thus, we're led to the
; same conclusion that Thinking produced. To get out of the
; interactive break we type:
; 1 ACL2 >:a!
; Abort to ACL2 top-level
; and then turn off the break rewrite tool since we won't need it
; again right now, with:
; ACL2 !>:brr nil
; In either case, by thinking or using tools, we decide to prove:
(defthm member-rev
(iff (member e (rev x))
(member e x)))
; which succeeds. Now when we try to prove dups-rev, it succeeds.
(defthm dupsp-rev
(equal (dupsp (rev x))
(dupsp x)))
Use your browser's Back Button now to return to
[introductory-challenge-problem-3].")
(INTRODUCTORY-CHALLENGE-PROBLEM-4
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Challenge problem 4 for the new user of ACL2
Start in a fresh ACL2, either by restarting your ACL2 image from
scratch or executing :ubt! 1.
This problem is much more open ended than the preceding ones. The
challenge is to define a function that collects exactly one copy of
each element of a list and to prove that it returns a subset of the
list with no duplications.
Hint: We recommend that you read this hint to align your function
names with our solution, to make comparisons easier. Our answer is
shown in see [introductory-challenge-problem-4-answer]. In that
page you'll see a definition of a function collect-once and the
proofs of two theorems:
(defthm main-theorem-1-about-collect-once
(subsetp (collect-once x) x))
(defthm main-theorem-2-about-collect-once
(not (dupsp (collect-once x))))
The function dupsp is as defined in see
[introductory-challenge-problem-3]. This is quite easy.
Then, we define a tail-recursive version of the method based on the
pseudo-code:
a = nil;
while (x not empty) {
a = if (member (car x) a) then a else (cons (car x) a);
x = (cdr x);
}
return a;
We formalize this with the function while-loop-version, where
(while-loop-version x nil) is the ``semantics'' of the code above.
I.e., the function while-loop-version captures the while loop in
the pseudo-code above and returns the final value of a, and it
should be invoked with the initial value of a being nil.
We prove (while-loop-version x nil) returns a subset of x that
contains no duplications. Furthermore, we do it two ways: first
``indirectly'' by relating while-loop-version to collect-once, and
second (``directly'') without using collect-once. Both of these
proofs are much harder than the collect-once approach, involving
about a dozen lemmas each.
Compare your solutions to ours at see
[introductory-challenge-problem-4-answer].
Then, use your browser's Back Button to return to
[introductory-challenges].")
(INTRODUCTORY-CHALLENGE-PROBLEM-4-ANSWER
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Answer to challenge problem 4 for the new user of ACL2
This answer is in the form of a script sufficient to lead ACL2 to a
proof, with a brief prologue.
We wish to collect one copy of each element in x. We'll actually
define the method two ways, primitive recursively and
tail-recursively, the latter method being analogous to the program:
a = nil;
while (x not empty) {
a = if (member (car x) a) then a else (cons (car x) a);
x = (cdr x);
}
return a;
We'll prove the two ``equivalent'' and we'll prove that they return a
subset of x that contains no duplications.
This page is organized into four sections. (A) We will start by
proving that the primitive recursive version correct: it returns a
subset of its argument that is duplication free. This will be
straightforward. (B) Then we'll define the while-loop version and
we will prove it ``equivalent'' to the primitive recursive version.
This will be challenging primarily because the two methods collect
their answers in different orders; even stating the relationship
between the two is interesting. Proving it will involve a few
lemmas. But once we prove their ``equivalence'' the correctness of
the while-loop version will be straightforward from the correctness
of the primitive recursive version. (C) We will disable the rules
we prove about the while-loop version and prove it correct
directly, without exploiting the primitive recursive version. This
requires leading the theorem prover more carefully because
reasoning about tail-recursive functions that accumulate results is
sometimes delicate. (D) Lessons learned -- a narrative that
summarizes what we learn from these examples.
We follow The Method, which, recall, involves us in recursive
attempts to prove lemmas. We use a notation to indicate our
sequence of proof attempts. Here is an example (although in actual
use we print things across multiple lines). The number in bracket
indicates our ``stack depth''. The ``key term'' is some term from a
Key Checkpoint in the failed proof which is responsible for our
subsequent action. Sometimes instead of a Key Term we just give an
English explanation of what we're thinking.
[0] (defthm main ...) Failed! Key Term: ...
[1] (defthm lemma-1 ...) Succeeded!
[0] (defthm main ...) Failed! Key Term: ...
[1] (defthm lemma-2 ...) Failed! Key Term: ...
[2] (defthm lemma-2a ...) Succeeded!
[2] (defthm lemma-2b ...) Succeeded!
[1] (defthm lemma-2 ...) Succeeded!
[0] (defthm main ...) Succeeded!
The rest of this page is just a re-playable script.
; -----------------------------------------------------------------
; Section A: The Primitive Recursive Version and Its Correctness
; The property of having duplications is defined as:
(defun dupsp (x)
(if (endp x)
nil
(if (member (car x) (cdr x))
t
(dupsp (cdr x)))))
; The primitive recursive method of collecting one copy of each element is:
(defun collect-once (x)
(if (endp x)
nil
(if (member (car x) (cdr x))
(collect-once (cdr x))
(cons (car x) (collect-once (cdr x))))))
; [0]
(defthm main-theorem-1-about-collect-once
(subsetp (collect-once x) x))
; Succeeded!
; [0]
; (defthm main-theorem-2-about-collect-once
; (not (dupsp (collect-once x))))
; Failed!
; Key Term: (MEMBER (CAR X) (COLLECT-ONCE (CDR X)))
; [1]
(defthm member-collect-once
(iff (member e (collect-once a))
(member e a)))
; Succeeded!
; [0]
(defthm main-theorem-2-about-collect-once
(not (dupsp (collect-once x))))
; Succeeded!
; That was really easy!
;-----------------------------------------------------------------
; Section B: The While-Loop Version and Its Correctness --
; presented in two parts: its equivalence to the primitive recursive
; version and then its correctness proved via that equivalence
; The tail-recursive, or while-loop version, is defined as follows. The
; function below is the loop itself and it ought to be called with a = nil to
; implement the initialization of a in the pseudo-code above.
(defun while-loop-version (x a)
(if (endp x)
a
(while-loop-version (cdr x)
(if (member (car x) a)
a
(cons (car x) a)))))
; We wish to prove that the two are equivalent. But they are actually
; very different. For example,
; (collect-once '(2 4 1 3 1 2 3 4)) = (1 2 3 4)
; (while-loop-version '(2 4 1 3 1 2 3 4) nil) = (3 1 4 2)
; Things get a little more complicated if a is non-nil:
; (while-loop-version '(2 4 1 3 1 2 3 4) '(2 2 4 4)) = (3 1 2 2 4 4)
; Several observations help explain what is happening. (1) Collect-once
; collects the last occurrence of each element, in the order of their last
; occurrences. So, for example, since the last occurrence of 2 preceeds the
; last occurrence of 3 in '(2 4 1 3 1 2 3 4)), then the collected 2 preceeds
; the collected 3 in the answer. But while-loop-version collects the first
; occurrence of each element, in the reverse order of that occurrence. So it
; adds 2 to its accumulator first and adds 3 last, making 3 preceed 2 in the
; answer.
; (2) The while-loop-version does not collect anything already in a and indeed
; just adds stuff to the front of a, returning everything initially in a plus
; one occurrence of everything in x not in a.
; To state the relationship that holds between these two we have to define two
; other functions.
; This is our familiar list reverse function...
(defun rev (x)
(if (endp x)
nil
(append (rev (cdr x))
(list (car x)))))
; And this function ``removes'' from x all the elements in y, i.e., copies x
; while dropping the elements of y.
(defun list-minus (x y)
(if (endp x)
nil
(if (member (car x) y)
(list-minus (cdr x) y)
(cons (car x) (list-minus (cdr x) y)))))
; The specific equivalence we're really interested in is
; (equal (while-loop-version x nil)
; (collect-once (rev x)))
; But we will not be able to prove that by induction because it has the
; constant nil where we need a variable, a, in order to admit an appropriate
; inductive instance. So we will attack the most general problem. What is
; (while-loop-version x a) equal to, in terms of collect-once?
; The most general relationship between the two collection functions is:
; (equal (while-loop-version x a)
; (append (collect-once (list-minus (rev x) a)) a))
; This formula bears thinking about! If you're like us, you won't believe it
; until it is proved!
; [0]
; (defthm general-equivalence
; (equal (while-loop-version x a)
; (append (collect-once (list-minus (rev x) a)) a)))
; Failed!
; Key term in checkpoint:
; (LIST-MINUS (APPEND (REV (CDR X)) (LIST (CAR X))) A)
; [1]
(defthm list-minus-append
(equal (list-minus (append a b) c)
(append (list-minus a c)
(list-minus b c))))
; Succeeded!
; [0]
; (defthm general-equivalence
; (equal (while-loop-version x a)
; (append (collect-once (list-minus (rev x) a)) a)))
; Failed!
; Key term in checkpoint:
; (COLLECT-ONCE (APPEND (LIST-MINUS (REV (CDR X)) A) (LIST (CAR X))))
; [1]
; (defthm collect-once-append
; (equal (collect-once (append a b))
; (append (list-minus (collect-once a) b)
; (collect-once b))))
; Failed!
; Key term:
; (MEMBER (CAR A) (APPEND (CDR A) B))
; [2]
(defthm member-append
(iff (member e (append a b))
(or (member e a)
(member e b))))
; Succeeded!
; [1]
(defthm collect-once-append
(equal (collect-once (append a b))
(append (list-minus (collect-once a)
b)
(collect-once b))))
; Succeeded!
; [0]
; (defthm general-equivalence
; (equal (while-loop-version x a)
; (append (collect-once (list-minus (rev x) a)) a)))
; Failed!
; Key term:
; (APPEND (APPEND (LIST-MINUS (COLLECT-ONCE (LIST-MINUS (REV (CDR X)) A))
; [1]
(defthm assoc-append
(equal (append (append a b) c)
(append a (append b c))))
; Succeeded!
; [0]
; (defthm general-equivalence
; (equal (while-loop-version x a)
; (append (collect-once (list-minus (rev x) a)) a)))
; Failed!
; Key term:
; (LIST-MINUS (COLLECT-ONCE (LIST-MINUS (REV (CDR X)) A)) ...)
; This key term makes us think of the lemma to move the LIST-MINUS inside the
; COLLECT-ONCE. But when that's done, we will have two LIST-MINUS terms
; nestled together and we will want to combine them into one. Call these two
; lemmas (a) and (b).
; [1] (a)
; (defthm list-minus-collect-once
; (equal (list-minus (collect-once x) a)
; (collect-once (list-minus x a))))
; Failed!
; Key term:
; (MEMBER (CAR X) (LIST-MINUS (CDR X) A))
; [2] (A pretty fact)
(defthm member-list-minus
(iff (member e (list-minus x a))
(and (member e x)
(not (member e a)))))
; Succeeded!
; [1] (a)
(defthm list-minus-collect-once
(equal (list-minus (collect-once x) a)
(collect-once (list-minus x a))))
; Succeeded!
; [1] (b)
(defthm list-minus-list-minus
(equal (list-minus (list-minus x a) b)
(list-minus x (append b a))))
; Succeeded!
; [0]
(defthm general-equivalence
(equal (while-loop-version x a)
(append (collect-once (list-minus (rev x) a)) a)))
; Succeeded!
; That completes the proof of the ``equivalence'' of the two methods.
; Now we prove (1) that the result of while-loop-version is a subset, and (2)
; that it contains no duplications. We prove the two conjuncts separately.
; [0]
(defthm main-theorem-1-about-while-loop
(subsetp (while-loop-version x nil) x))
; Succeeded!
; But the theorem prover works harder to do the proof above than one might have
; expected because it doesn't turn into an instance of
; main-theorem-1-about-collect-once because of the presence of the rev term.
; However, we're content that ACL2 managed to do the proof on its own.
; [0]
(defthm main-theorem-2-about-while-loop
(not (dupsp (while-loop-version x nil))))
; So we see that the proof of correctness of while-loop-version isn't hard,
; after we establish the relationship with the primitive recursive version.
; But finding and proving the relationship is fairly challenging.
; -----------------------------------------------------------------
; Section C: A Direct Proof of the Correctness of the While-Loop Version
; Some would consider the proof in Section B ``indirect'' because we first showed
; how while-loop-version could be expressed as a collect-once and then proved
; our main theorems about while-loop-version, which means those main proofs
; were conducted in terms of collect-once, not while-loop-version.
; It is interesting to compare this proof with the ``direct'' one in which
; we don't use collect-once at all and reason only about while-loop-version.
; So to do that comparison, let's disable all the lemmas we've proved about
; while-loop-version and try to prove the two main theorems above about
; while-loop-version.
(in-theory (disable general-equivalence
main-theorem-1-about-while-loop
main-theorem-2-about-while-loop))
; [0]
; (defthm main-theorem-1-about-while-loop-redux
; (subsetp (while-loop-version x nil) x))
; Failed! [Well, the truth is below...]
; We don't even submit this event above because we recognize that it is not
; general enough to permit proof by induction. We need to deal with the nil in
; the second argument of while-loop-version. Experience with induction tells
; us this should be a variable, so we can assume an appropriate inductive
; instance. Therefore, we adopt this subgoal immediately:
; [1]
; (defthm main-lemma-1-about-while-loop-version
; (subsetp (while-loop-version x a) (append x a)))
; Failed!
; Key Term: Does the wrong induction.
; [1]
; (defthm main-lemma-1-about-while-loop-version
; (subsetp (while-loop-version x a) (append x a))
; :hints ((\"Goal\" :induct (while-loop-version x a))))
; Failed! Two key terms are suggested
; Key term: (IMPLIES (AND ... (SUBSETP (WHILE-LOOP-VERSION (CDR X) A) (APPEND (CDR X) A)))
; (SUBSETP (WHILE-LOOP-VERSION (CDR X) A) (CONS ... (APPEND (CDR X) A))))
; Key term: (SUBSETP A A)
; So we'll prove both before trying again.
; [2]
(defthm subsetp-cons
(implies (subsetp a b)
(subsetp a (cons e b))))
; Succeeded!
; [2]
(defthm subsetp-reflexive
(subsetp a a))
; Succeeded!
; [1]
; (defthm main-lemma-1-about-while-loop-version
; (subsetp (while-loop-version x a) (append x a))
; :hints ((\"Goal\" :induct (while-loop-version x a))))
; Failed!
; Key Term:
; (IMPLIES (AND ...
; (SUBSETP (WHILE-LOOP-VERSION (CDR X) (CONS (CAR X) A))
; (APPEND (CDR X) (CONS (CAR X) A))))
; (SUBSETP (WHILE-LOOP-VERSION (CDR X) (CONS (CAR X) A))
; (CONS (CAR X) (APPEND (CDR X) A))))
; We'd be done if we could rewrite the
; (APPEND (CDR X) (CONS (CAR X) A))
; to
; (CONS (CAR X) (APPEND (CDR X) A))
; These two terms are not equal! But they are ``set-equal'' and this kind of
; rewriting is possible using user-defined equivalences and congruence rules.
; But the new user should not dive into congruences yet. So we will do this
; with ordinary lemmas:
; The plan then is to prove
; (iff (subsetp a (append b (cons e c)))
; (subsetp a (cons e (append b c))))
; Consider the first half of this bi-implication:
; (implies (subsetp a (append b (cons e c))) ; hyp1
; (subsetp a (cons e (append b c)))) ; concl
; Notice that if we knew
; (subsetp (append b (cons e c)) (cons e (append b c))) ; hyp2
; then we could use hyp1 and hyp2 together with the transitivity of
; subsetp to get concl.
; The proof in the other direction is comparable but requires the
; (subsetp (cons e (append b c)) (append b (cons e c)))
; Thus, our plan is prove
; (a) transitivity of subsetp
; (b) (subsetp (append b (cons e c)) (cons e (append b c)))
; (c) (subsetp (cons e (append b c)) (append b (cons e c)))
; in order to prove
; (d) (iff (subsetp a (append b (cons e c)))
; (subsetp a (cons e (append b c))))
; [2] (a)
(defthm trans-subsetp
(implies (and (subsetp a b)
(subsetp b c))
(subsetp a c)))
; Succeeded!
; [2] (b)
(defthm append-cons-v-cons-append-1
(subsetp (append b (cons e c))
(cons e (append b c))))
; Succeeded!
; [2] (c)
(defthm append-cons-v-cons-append-2
(subsetp (cons e (append b c))
(append b (cons e c))))
; Succeeded!
; [2] (d)
(defthm subsetp-append-cons-cons-append
(iff (subsetp a (append b (cons e c)))
(subsetp a (cons e (append b c)))))
; Succeeded!
; [1]
(defthm main-lemma-1-about-while-loop-version
(subsetp (while-loop-version x a) (append x a))
:hints ((\"Goal\" :induct (while-loop-version x a))))
; Succeeded!
; [0]
; (defthm main-theorem-1-about-while-loop-version
; (subsetp (while-loop-version x nil) x))
; Failed! [But the truth is below...]
; But we don't submit this because we don't expect it to be proved
; from the main lemma just proved: they don't match! But
; note that if we instantiated the main lemma, replacing a by nil,
; we get:
; (subsetp (while-loop-version x nil) (append x nil))
; and we could simplify the (append x nil) to x in this context, with
; another congruence rule -- if we were using them. So let's prove
; first that we can simplify (append x nil) inside a subsetp:
; [1]
(defthm subsetp-append-nil
(iff (subsetp x (append y nil))
(subsetp x y)))
; Succeeded!
; and then just tell ACL2 how to use the lemma to get the main theorem. Note
; that we give a hint to instantiate main-lemma-1... but we also disable
; main-lemma-1... because otherwise it will rewrite itself away! Once the
; instance of main-lemma-1... is sitting around as a hypothesis,
; subsetp-append-nil will rewrite the (append x nil) to x for us and finish the
; proof.
; [0]
(defthm main-theorem-1-about-while-loop-version
(subsetp (while-loop-version x nil) x)
:hints ((\"Goal\"
:use (:instance main-lemma-1-about-while-loop-version
(x x)
(a nil))
:in-theory (disable main-lemma-1-about-while-loop-version))))
; Succeeded!
; Recall that the main-theorem-1... just proved is just half of what we want.
; We also want:
; [0]
; (defthm main-theorem-2-about-while-loop-version
; (not (dupsp (while-loop-version x nil))))
; Failed! [But the truth is below...]
; But, again, we don't submit that because the nil makes it not general enough for
; induction. Instead we go immediately to:
; [1]
(defthm main-lemma-2-about-while-loop-version
(implies (not (dupsp a))
(not (dupsp (while-loop-version x a)))))
; Succeeded!
; This time we know our main-lemma-2... will match (there's no (append x nil)
; in there to mess things up) and so we can complete the proof with:
; [0]
(defthm main-theorem-2-about-while-loop-version
(not (dupsp (while-loop-version x nil))))
; Succeeded!
;-----------------------------------------------------------------
; Section D: Lessons Learned
; The most obvious lesson is that it is easier to reason about the primitive
; recursive collect-once than about the while-loop-version. Thus, if your only
; need is for a function that collects one occurrence of each element of a list
; and you don't care about the order in which you collect them and you don't
; need it to be very sparing of stack space when it executes, then use the
; primitive recursive definition and don't even think about while loops!
; So why might you be driven to while-loop-version? One possibility is that
; the list you wish to process is very long and the primitive recursive version
; would produce a stack overflow. In ACL2, that would mean the list would have
; to be several thousand long. Is your application really so demanding?
; Another possibility is that you are modeling in Lisp a while loop expressed
; in some other programming language. In that case, the fidelity of your model to
; the artifact being modeled is important and you should use while-loop-version.
; Another possibility is that for some reason order matters and you really are
; interested in collecting the first occurrence rather than the last. Of
; course this is most likely to be relevant in more interesting applications
; where the occurrences are somehow distinguishable.
; If you are forced to deal with the while-loop-version the question is do you
; do an indirect proof as in Section B or a direct proof as in Section C?
; The indirect proof involved 10 theorems and the direct proof involved 11.
; That is not a significant difference.
; But our sense is that the indirect proof is easier to find, once you figure
; out the basic shape of the relation between while-loop-version collect-once.
; In particular, we had to give the theorem prover two hints in the direct
; proof (versus no hints in the indirect proof). One of our hints was about
; what induction to do and the other was about how to use a previously proved
; instance of a lemma involving an accumulator. Furthermore, we had to think
; carefully about the use of the transitivity of subsetp and we had to hack our
; way around rewriting (append a (cons e b)) to (cons e (append a b)) in a
; subsetp-expression.
; Some of these ``set'' problems could have been handled a lot more elegantly by
; defining set-equal as an equivalence relation and proving the congruence
; rules to allow the rewriting of set-equal terms to set-equal terms inside
; certain expressions like subsetp and member. However, that involves a lot of
; overhead in the form of congruence rules showing that set-equality is
; maintained by replacement of set-equals by set-equals in various argument
; positions of the various functions. See :doc congruence. In general, we
; find congruence-based reasoning extremely neat and powerful when the
; appropriate infrastructure has been built up. But because the infrastructure
; is ``heavy'' we tend not to invest in it for small projects.
; In summary, different users might take home different lessons about whether a
; direct or indirect proof is better here. This is in part due to the
; complexity of the functional relationship between collect-once and
; while-loop-version, which additionall involved append, list-minus, and rev.
; Had the relationship been simpler, the indirect proof would have been
; preferred.
; An undeniable lesson, however, is that it is helpful to know both styles of
; proof and to be able to explore both as needed in your applications.
Use your browser's Back Button now to return to
[introductory-challenge-problem-4].")
(INTRODUCTORY-CHALLENGES
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Challenge problems for the new ACL2 user
Do each of the problems. In each case, start with a fresh ACL2 (or
undo all effects of previous events with :ubt! 1). This may require
that you ``re-discover'' the same lemma more than once in different
problems, but recognizing the need for something you used in some
previous project is part of the training.
We recommend that you follow The Method and consult the documentation
as needed -- but that you not look at our answers until you're well
and truly baffled!
See [introductory-challenge-problem-1] (Answer:
[introductory-challenge-problem-1-answer])
See [introductory-challenge-problem-2] (Answer:
[introductory-challenge-problem-2-answer])
See [introductory-challenge-problem-3] (Answer:
[introductory-challenge-problem-3-answer])
See [introductory-challenge-problem-4] (Answer:
[introductory-challenge-problem-4-answer])
In addition to these explicit challenge problems designed for
beginners, the ACL2 documentation has many example solutions to
problems (not always phrased in the question/answer format here).
If you are looking for other examples, you should consider
[annotated-ACL2-scripts] (Answer: the answers are given in the
examples)
When you've done the problems and compared your solutions to ours,
use your browser's Back Button now to return to
[introduction-to-the-theorem-prover].")
(INVARIANT-RISK
(SET-CHECK-INVARIANT-RISK)
"Potential slowdown for [program]-mode updates to [stobj]s or [arrays]
You may see a warning like this:
ACL2 Warning [Invariant-risk] in MY-FUNCTION: Invariant-risk has been
detected for a call of function MY-FUNCTION (as possibly leading to
an ill-guarded call of UPDATE-FLD); see :DOC invariant-risk.
Such warnings are harmless, except that they may indicate some
slowdown (probably very slight) that you might not have expected.
For an explanation, see [program-wrapper]. If you simply want to
avoid such warnings, evaluate either one of the following forms.
(set-check-invariant-risk t)
(set-inhibit-warnings \"invariant-risk\")
Evaluate (get-check-invariant-risk state) to see the current setting
for invariant-risk checking. For details, including more options
for modifying this setting, see [set-check-invariant-risk].")
(INVISIBLE-FNS-TABLE
(LOOP-STOPPER)
"Functions that are invisible to the [loop-stopper] algorithm
Examples:
ACL2 !>(invisible-fns-table (w state))
((binary-+ unary--)
(binary-* unary-/)
(unary-- unary--)
(unary-/ unary-/))
Among other things, the setting above has the effect of making
[unary--] ``invisible'' for the purposes of applying permutative
:[rewrite] rules to [binary-+] trees. Also see [add-invisible-fns]
and see [remove-invisible-fns], which manage macro aliases (see
[macro-aliases-table]), as well as see [set-invisible-fns-table].
See [table] for a general discussion of tables.
The ``invisible functions [table]'' is an alist with elements of the
following form, where fn is a function symbol and the ufni are
unary function symbols in the current ACL2 [world], and k is at
least 1.
(fn ufn1 ufn2 ... ufnk)
This [table] thus associates with certain function symbols, e.g., fn
above, a set of unary functions, e.g., the ufni above. The ufni
associated with fn in the invisible functions table are said to be
``invisible with respect to fn.'' If fn is not the [car] of any
pair in the alist, then no function is invisible for it. Thus for
example, setting the invisible functions alist to nil completely
eliminates the consideration of invisibility.
The notion of invisibility is involved in the use of the
:[loop-stopper] field of :[rewrite] rules to prevent the indefinite
application of permutative rewrite rules. Roughly speaking, if
rewrite rules are being used to permute arg and (ufni arg) inside
of a nest of fn calls, and ufni is invisible with respect to fn,
then arg and (ufni arg) are considered to have the same ``weight''
and will be permuted so as to end up as adjacent tips in the fn
nest. See [loop-stopper].")
(IO
(INTERFACING-TOOLS STATE PROGRAMMING)
"Input/output facilities in ACL2
Example:
(mv-let
(channel state)
(open-input-channel \"foo.lisp\" :object state)
(mv-let (eofp obj state)
(read-object channel state)
(.
.
(let ((state (close-input-channel channel state)))
(mv final-ans state))..)))
Also see [std/io] and [file-reading-example].
For advanced ways to control printing, see [print-control].
For a discussion of formatted printing, see [fmt].
To control ACL2 abbreviation (``evisceration'') of objects before
printing them, see [set-evisc-tuple], see [without-evisc], and see
[set-iprint].
To redirect output to a file, see [output-to-file].
ACL2 supports input and output facilities equivalent to a subset of
those found in Common Lisp. ACL2 does not support random access to
files or bidirectional streams. In Common Lisp, input and output
are to or from objects of type stream. In ACL2, input and output
are to or from objects called ``channels,'' which are actually
symbols. Although a channel is a symbol, one may think of it
intuitively as corresponding to a Common Lisp stream. Channels are
in one of two ACL2 packages, \"ACL2-INPUT-CHANNEL\" and
\"ACL2-OUTPUT-CHANNEL\". When one ``opens'' a file one gets back a
channel whose [symbol-name] is the file name passed to ``open,''
postfixed with -n, where n is a counter that is incremented every
time an open or close occurs.
There are three channels which are open from the beginning and which
cannot be closed:
acl2-input-channel::standard-character-input-0
acl2-input-channel::standard-object-input-0
acl2-input-channel::standard-character-output-0
All three of these are really Common Lisp's *standard-input* or
*standard-output*, appropriately.
For convenience, three global variables are bound to these rather
tedious channel names:
*standard-ci*
*standard-oi*
*standard-co*
Common Lisp permits one to open a stream for several different kinds
of io, e.g. character or byte. ACL2 permits an additional type
called ``object''. In ACL2 an ``io-type'' is a keyword, either
:character, :byte, or :object. When one opens a file, one specifies
a type, which determines the kind of io operations that can be done
on the channel returned. The types :character and :byte are
familiar. Type :object is an abstraction not found in Common Lisp.
An :object file is a file of Lisp objects. One uses read-object to
read from :object files and print-object$ (or print-object$-ser) to
print to :object files. (The reading and printing are really done
with the Common Lisp read and print functions. For those familiar
with read, we note that the recursive-p argument is nil.) The
function read-object-suppress is logically the same as read-object
except that read-object-suppress throws away the second returned
value, i.e. the value that would normally be read, simply returning
(mv eof state); under the hood, read-object-suppress avoids errors,
for example those caused by encountering symbols in packages
unknown to ACL2.
File-names are strings. ACL2 does not support the Common Lisp type
[pathname]. However, for the file-name argument of the
output-related functions listed below, ACL2 supports a special
value, :STRING. For this value, the channel connects (by way of a
Common Lisp output string stream) to a string rather than to a
file: as characters are written to the channel they can be
retrieved by using get-output-stream-string$.
Here are the names, formals and output descriptions of the ACL2 io
functions.
Input Functions:
(open-input-channel (file-name io-type state) (mv channel state))
(open-input-channel-p (channel io-type state) boolean)
(close-input-channel (channel state) state)
(read-char$ (channel state) (mv char/nil state)) ; nil for EOF
(peek-char$ (channel state) boolean)
(read-byte$ (channel state) (mv byte/nil state)) ; nil for EOF
(read-object (channel state) (mv eof-read-flg obj-read state))
(read-object-suppress (channel state) (mv eof-read-flg state))
(read-file-into-string (filename state) string/nil)
Output Functions:
(open-output-channel (file-name io-type state) (mv channel state))
(open-output-channel! (file-name io-type state) (mv channel state))
(open-output-channel-p (channel io-type state) boolean)
(close-output-channel (channel state) state)
(princ$ (obj channel state) state)
(write-byte$ (byte channel state) state)
(print-object$ (obj channel state) state)
(print-object$-ser (obj serialize-character channel state) state)
(fms (string alist channel state evisc-tuple) state)
(fms! (string alist channel state evisc-tuple) state)
(fmt (string alist channel state evisc-tuple) (mv col state))
(fmt! (string alist channel state evisc-tuple) (mv col state))
(fmt1 (string alist col channel state evisc-tuple) (mv col state))
(fmt1! (string alist col channel state evisc-tuple) (mv col state))
(cw (string arg0 arg1 ... argn) nil)
(get-output-stream-string$ (channel state
&optional (close-p 't)
(ctx ''get-output-stream-string$))
(mv erp string state))
Note that open-output-channel and open-output-channel! will attempt
to create directories as needed. For example, the following can
succeed in writing to the indicated file by creating subdirectory
\"dir4\" if that directory does not already exist.
(mv-let
(channel state)
(open-output-channel \"dir4/foo4\" :object state)
(pprogn (fms \"Here: ~x0\"
(list (cons #\\0 (make-list 10)))
channel state nil)
(close-output-channel channel state)))
The ``formatting'' functions are particularly useful; see [fmt] and
see [cw]. In particular, [cw] prints to a ``comment window'' and
does not involve the ACL2 [state], so many may find it easier to
use than [fmt] and its variants. The functions [fms!], [fmt!], and
[fmt1!] are the same as their respective functions without the
``!,'' except that the ``!'' functions are guaranteed to print
forms that can be read back in (at a slight readability cost).
When one enters ACL2 with (lp), input and output are taken from
[*standard-oi*] to [*standard-co*]. Because these are synonyms for
*standard-input* and *standard-output*, one can drive ACL2 io off
of arbitrary Common Lisp streams, bound to *standard-input* and
*standard-output* before entry to ACL2.
The macro get-output-stream-string$ returns the string accumulated
into the given channel. By default, a call of this macro closes the
supplied output channel. However, a third argument is optional
(default t), and if it evaluates to nil then the channel remains
open. The fourth argument is an optional context, which generally
evaluates to a symbol, for error reporting. The following example
illustrates.
ACL2 !>
(mv-let
(channel state)
(open-output-channel :string :object state)
(pprogn (print-object$-ser 17 nil channel state)
(print-object$-ser '(a b (c d)) nil channel state)
(er-let*
((str1 (get-output-stream-string$
channel state
nil))) ; keep the channel open
(pprogn (print-object$-ser 23 nil channel state)
(print-object$-ser '((e f)) nil channel state)
(er-let* ; close the channel
((str2 (get-output-stream-string$ channel state)))
(value (cons str1 str2)))))))
(\"
17
(A B (C D))\" . \"
23
((E F))\")
ACL2 !>
Also see [printing-to-strings] for a discussion of formatted printing
functions such as fmt-to-string that do not take a channel or
[state] argument and return a string.
By default, symbols are printed in upper case when vertical bars are
not required, as specified by Common Lisp. See [set-print-case] for
how to get ACL2 to print symbols in lower case.
By default, numbers are printed in radix 10 (base 10). See
[set-print-base-radix] for how to get ACL2 to print numbers in
radix 2, 8, or 16.
To see the [guard] of an IO function, or indeed any function, see
[args] or call the function guard; but some built-in functions
(including some IO functions) will print the result using the
variable STATE-STATE. While that is logically correct, if you want
to execute the guard then you should replace that variable by STATE
and also replace each built-in function symbol of the form xxx-p1
by corresponding function symbol xxx-p. Consider the following
example.
ACL2 !>:args princ$
Function PRINC$
Formals: (X CHANNEL STATE-STATE)
Signature: (PRINC$ * * STATE)
=> STATE
Guard: (AND (OR (ACL2-NUMBERP X)
(CHARACTERP X)
(STRINGP X)
(SYMBOLP X))
(STATE-P1 STATE-STATE)
(SYMBOLP CHANNEL)
(OPEN-OUTPUT-CHANNEL-P1 CHANNEL
:CHARACTER STATE-STATE))
Guards Verified: T
Defun-Mode: :logic
Type: (CONSP (PRINC$ X CHANNEL STATE-STATE))
Documentation available via :DOC
PRINC$
ACL2 !>(untranslate (guard 'princ$ nil (w state)) t (w state))
(AND (OR (ACL2-NUMBERP X)
(CHARACTERP X)
(STRINGP X)
(SYMBOLP X))
(STATE-P1 STATE-STATE)
(SYMBOLP CHANNEL)
(OPEN-OUTPUT-CHANNEL-P1 CHANNEL
:CHARACTER STATE-STATE))
ACL2 !>
If you want to execute the guard for [princ$], then according to the
suggestion above, you should consider the guard for (princ$ x
channel state) to be as follows.
(AND (OR (ACL2-NUMBERP X)
(CHARACTERP X)
(STRINGP X)
(SYMBOLP X))
(STATE-P STATE)
(SYMBOLP CHANNEL)
(OPEN-OUTPUT-CHANNEL-P CHANNEL :CHARACTER STATE))
For example, we can check the guard for a given value and channel as
follows.
ACL2 !>(let ((x 3) (channel *standard-co*))
(AND (OR (ACL2-NUMBERP X)
(CHARACTERP X)
(STRINGP X)
(SYMBOLP X))
(STATE-P STATE)
(SYMBOLP CHANNEL)
(OPEN-OUTPUT-CHANNEL-P CHANNEL :CHARACTER STATE)))
T
ACL2 !>
Comment for advanced users: Function [open-output-channel!] is
identical as a function to open-output-channel, except that the
former may be called even during [make-event] expansion and
[clause-processor] [hints], but requires that there is an active
trust tag (see [defttag]).
Finally, we note that the [std/io] library contains useful file io
functions whose definitions illustrate some of the features
described above.
Subtopics
[*standard-ci*]
An ACL2 character-based analogue of CLTL's *standard-input*
[*standard-co*]
The ACL2 analogue of CLTL's *standard-output*
[*standard-oi*]
An ACL2 object-based analogue of CLTL's *standard-input*
[Character-encoding]
How bytes are parsed into characters
[Cw]
Print to the comment window
[Cw!]
Print to the comment window
[Evisc-tuple]
Control suppression of details when printing
[Eviscerate-hide-terms]
To print ([hide] ...) as <hidden>
[Fms]
([fms] str alist co-channel state evisc) => state
[Fms!]
([fms!] str alist co-channel state evisc) => state
[Fmt]
Formatted printing
[Fmt!]
([fmt!] str alist co-channel state evisc) => state
[Fmt-to-comment-window]
Print to the comment window
[Fmt1]
([fmt1] str alist col co-channel state evisc) => ([mv] col state)
[Fmt1!]
([fmt1!] str alist col channel state evisc) => ([mv] col state)
[Msg]
Construct a ``message'' suitable for the ~@ directive of [fmt]
[Observation]
Print an observation
[Open-output-channel!]
When trust tags are needed to open output channels
[Output-to-file]
Redirecting output to a file
[Princ$]
Print an atom
[Print-base-p]
Recognizer for print bases that are understood by functions such as
[explode-nonnegative-integer] and [explode-atom].
[Print-control]
Advanced controls of ACL2 printing
[Printing-to-strings]
Printing to strings instead of files or standard output
[Proofs-co]
The proofs character output channel
[Read-file-into-string]
The contents of a file as a string
[Serialize]
Routines for saving ACL2 objects to files, and later restoring them
[Set-evisc-tuple]
Control suppression of details when printing
[Set-fmt-hard-right-margin]
Set the right margin for formatted output
[Set-fmt-soft-right-margin]
Set the soft right margin for formatted output
[Set-iprint]
Control whether abbreviated output can be read back in
[Set-print-base]
Control radix in which numbers are printed
[Set-print-base-radix]
Control radix in which numbers are printed and printing of the radix
[Set-print-case]
Control whether symbols are printed in upper case or in lower case
[Set-print-radix]
Control printing of the radix for numbers
[Standard-co]
The character output channel to which [ld] prints
[Standard-oi]
The standard object input ``channel''
[Without-evisc]
Print output in full
[Wof]
Direct standard output and proofs output to a file")
(IPRINT (POINTERS) "See [set-iprint].")
(IPRINTING (POINTERS)
"See [set-iprint].")
(IRRELEVANT-FORMALS
(PROGRAMMING)
"Formals that are used but only insignificantly
Let fn be a function of n arguments. Let x be the ith formal of fn.
We say x is ``irrelevant in fn'' if x does not occur in either the
[guard] or the measure for fn, and the value of (fn a1...ai...an)
is independent of ai.
The easiest way to define a function with an irrelevant formal is
simply not to use the formal in the body of the function. Such
formals are said to be ``ignored'' by Common Lisp and a special
declaration is provided to allow ignored formals. ACL2 makes a
distinction between ignored and irrelevant formals. Note however
that if a variable is [declare]d ignored or ignorable, then it will
not be reported as irrelevant.
An example of an irrelevant formal is x in the definition of fact
below.
(defun fact (i x)
(declare (xargs :guard (and (integerp i) (<= 0 i))))
(if (zerop i) 1 (* i (fact (1- i) (cons i x))))).
Observe that x is only used in recursive calls of fact; it never
``gets out'' into the result. ACL2 can detect some irrelevant
formals by a closure analysis on how the formals are used. For
example, if the ith formal is only used in the ith argument
position of recursive calls, then it is irrelevant. This is how x
is used above.
It is possible for a formal to appear only in recursive calls but
still be relevant. For example, x is not irrelevant below, even
though it only appears in the recursive call.
(defun fn (i x) (if (zerop i) 0 (fn x (1- i))))
The key observation above is that while x only appears in a recursive
call, it appears in an argument position, namely i's, that is
relevant. (The function above can be admitted with a :measure of (+
(nfix i) (nfix x)).)
Establishing that a formal is irrelevant, in the sense defined above,
can be an arbitrarily hard problem because it requires theorem
proving. For example, is x irrelevant below?
(defun test (i j k x) (if (p i j k) 0 x))
Note that the value of (test i j k x) is independent of x --- thus
making x irrelevant --- precisely if (p i j k) is a theorem. ACL2's
syntactic analysis of a definition does not guarantee to notice all
irrelevant formals.
We regard the presence of irrelevant formals as an indication that
something is wrong with the definition. We cause an error on such
definitions and suggest that you recode the definition so as to
eliminate the irrelevant formals. If you must have an irrelevant
formal, one way to ``trick'' ACL2 into accepting the definition,
without slowing down the execution of your function, is to use the
formal in an irrelevant way in the [guard]. For example, to admit
fact, above, with its irrelevant x one might use
(defun fact (i x)
(declare (xargs :guard (and (integerp i) (<= 0 i) (equal x x))))
(if (zerop i) 0 (* i (fact (1- i) (cons i x)))))
For those who really want to turn off this feature, we have provided
a way to use the [ACL2-defaults-table] for this purpose; see
[set-irrelevant-formals-ok].")
(KEEP
(BOOKS-TOUR)
"How we know if [include-book] read the correct files
The certificate (see [certificate] for general information) of a
certified file is divided into two parts, a [portcullis] and a
keep. These names come from castle lore. The keep is the strongest
and usually tallest tower of a castle from which the entire
courtyard can be surveyed by the defenders. The keep of a book is a
list of file names and check sums used after the book has been
included, to determine if the files read were (up to check sum)
those certified.
Once the [portcullis] is open, [include-book] can enter the book and
read the event forms therein. The non-[local] event forms are in
fact executed, extending the host theory. That may read in other
[books]. When that has been finished, the keep of the [certificate]
is inspected. The keep is a list of the book names which are
included (hereditarily through all sub-books) in the certified book
(including the certified book itself) together with the check sums
of the objects in those [books] at the time of certification. We
compare the check sums of the [books] just included to the check
sums of the [books] stored in the keep. If differences are found
then we know that the book or one of its sub-books has been changed
since certification.
See [include-book] to continue the guided tour through [books].")
(KEYWORD (POINTERS) "See [keywordp].")
(KEYWORD-COMMANDS
(LD)
"How keyword commands like :u and :pbt are processed
Examples:
user type-in form evaluated
:pc 5 (ACL2::PC '5)
:pcs app rev (ACL2::PCS 'app 'rev)
:length (1 2 3) (ACL2::LENGTH '(1 2 3))
:quit (ACL2::QUIT) ; Note: avoid optional argument
When a keyword, :key, is read as a command, ACL2 determines whether
the symbol with the same name in the \"ACL2\" package, acl2::key, is
a function or simple macro of n arguments. If so, ACL2 reads n more
objects, obj1, ..., objn, and then acts as though it had read the
following form (for a given key):
(ACL2::key 'obj1 ... 'objn)
Thus, by using the keyword command hack you avoid typing the
parentheses, the \"ACL2\" package name, and the quotation marks.
See [ld-keyword-aliases] for how to customize this behavior.
Note the generality of this hack. Any function or macro in the \"ACL2\"
package can be so invoked, not just ``commands.'' Indeed, there is
no such thing as a distinguished class of commands. Users may take
advantage of the keyword command hack by defining functions and
macros in the \"ACL2\" package.
The one caveat is that when the keyword hack is used to invoke a
macro, only the required arguments for that macro are read before
calling that macro: none of the &optional, &rest, &body, or &key
arguments are read for that call. The macro is thus called with
only its required arguments. The following log illustrates this
caveat.
ACL2 !>:set-iprint t
ACL2 Query (:SET-IPRINT): Action (T, NIL, RESET, RESET-ENABLE, SAME,
Q or ?):
ACL2 Observation in SET-IPRINT: Iprinting has been enabled.
ACL2 !>
What happened? First, the command :set-iprint was read. Since the
macro [set-iprint] has no required arguments, the ACL2 evaluator
was then called on the form (set-iprint), that is, calling the
macro on no arguments. Set-iprint is defined to query the ACL2 user
when its first argument is omitted. The log shows that query, which
is set up to read the next form from the input stream. That form
was available immediately: the form t that had been supplied by the
user. So the query returned immediately and the set-iprint call was
completed.")
(KEYWORD-VALUE-LISTP
(KEYWORDP LISTS ACL2-BUILT-INS)
"Recognizer for true lists whose even-position elements are keywords
(keyword-value-listp l) is true if and only if l is a list of even
length of the form (k1 a1 k2 a2 ... kn an), where each ki is a
keyword.
Function: <keyword-value-listp>
(defun keyword-value-listp (l)
(declare (xargs :guard t))
(cond ((atom l) (null l))
(t (and (keywordp (car l))
(consp (cdr l))
(keyword-value-listp (cddr l))))))
Subtopics
[Assoc-keyword]
Look up key in a [keyword-value-listp]")
(KEYWORDP
(SYMBOLS ACL2-BUILT-INS)
"Recognizer for keywords
(Keywordp x) is true if and only if x is a keyword, i.e., a symbol in
the \"KEYWORD\" package. Such symbols are typically printed using a
colon (:) followed by the [symbol-name] of the symbol.
Keywordp has a [guard] of t.
Keywordp is a Common Lisp function. See any Common Lisp documentation
for more information. The following log may be illuminating.
ACL2 !>(intern \"ABC\" \"KEYWORD\")
:ABC
ACL2 !>(symbol-name ':ABC)
\"ABC\"
ACL2 !>(symbol-package-name ':ABC)
\"KEYWORD\"
ACL2 !>
Function: <keywordp>
(defun keywordp (x)
(declare (xargs :guard t))
(and (symbolp x)
(equal (symbol-package-name x)
\"KEYWORD\")))
Subtopics
[Keyword-value-listp]
Recognizer for true lists whose even-position elements are keywords")
(KWOTE
(TERM ACL2-BUILT-INS)
"Quote an arbitrary object
For any object x, (kwote x) returns the two-element list whose
elements are the symbol quote and the given x, respectively. The
guard of (kwote x) is t.
Function: <kwote>
(defun kwote (x)
(declare (xargs :guard t))
(mbe :logic (list 'quote x)
:exec (cond ((eq x nil) *nil*)
((eq x t) *t*)
((eql x 0) *0*)
((eql x 1) *1*)
((eql x -1) *-1*)
(t (list 'quote x)))))")
(KWOTE-LST
(TERM ACL2-BUILT-INS)
"Quote an arbitrary true list of objects
The function kwote-lst applies the function kwote to each element of
a given list. The guard of (kwote-lst lst) is (true-listp lst).
Function: <kwote-lst>
(defun kwote-lst (lst)
(declare (xargs :guard (true-listp lst)))
(cond ((endp lst) nil)
(t (cons (kwote (car lst))
(kwote-lst (cdr lst))))))")
(LAMBDA (POINTERS) "See [term].")
(LAST
(LISTS ACL2-BUILT-INS)
"The last [cons] (not element) of a list
(Last l) is the last [cons] of a list. Here are examples.
ACL2 !>(last '(a b . c))
(B . C)
ACL2 !>(last '(a b c))
(C)
(Last l) has a [guard] of (listp l); thus, l need not be a
[true-listp].
Last is a Common Lisp function. See any Common Lisp documentation for
more information. Unlike Common Lisp, we do not allow an optional
second argument for last.
Function: <last>
(defun last (l)
(declare (xargs :guard (listp l)))
(if (atom (cdr l)) l (last (cdr l))))")
(LAST-PROVER-STEPS
(SET-PROVER-STEP-LIMIT WITH-PROVER-STEP-LIMIT
PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"The number of prover steps most recently taken
For discussions of prover step limits, See [set-prover-step-limit]
and see [with-prover-step-limit]. The value of the form
(last-prover-steps state) indicates the number of prover steps
taken, in the sense described below, for the most recent context in
which an event summary would normally be printed. Note that the
value of (last-prover-steps state) is updated for all [events], and
for all other forms such as calls of [thm] or [certify-book], that
would print a summary --- regardless of whether or not such output
is inhibited (see [set-inhibit-output-lst] and see
[set-inhibited-summary-types]). In particular, the value is updated
(typically to nil) for [table] [events], even when no summary is
printed; for example, the value is updated to nil for table events
such as ([logic]), ([program]), and even calls of
[set-prover-step-limit].
The value of (last-prover-steps state) is determined as follows,
based on the most recent summary context (as described above):
nil, if no prover steps were taken; else,
the (positive) number of steps taken, if the number of steps did not
exceed the starting limit; else,
the negative of the starting limit.
We conclude with a remark for advanced users who wish to invoke
last-prover-steps in the development of utilities that track prover
steps. Suppose that you want to write a utility that takes some
action based on the number of prover steps performed by the first
defun event that is generated, among others, for example the number
of prover steps taken to admit f1 in the following example.
(progn (defun f1 ...)
(defun f2 ...))
A solution is to record the steps taken by the first [defun] before
executing subsequent events, as follows (see [make-event]).
(progn (defun f1 ...)
(make-event (pprogn (f-put-global 'my-step-count
(last-prover-steps state)
state)
(value '(value-triple nil))))
(defun f2 ...))")
(LD
(MISCELLANEOUS)
"The ACL2 read-eval-print loop, file loader, and [command] processor
Examples:
(LD \"foo.lisp\") ; read and evaluate each form in file
; \"foo.lisp\", in order
(LD \"foo.lisp\" :ld-pre-eval-print t)
; as above, but print each form to standard
; character output just before it is evaluated
General Form:
(LD standard-oi ; open obj in channel, stringp file name
; to open and close, or list of forms
; Optional keyword arguments:
:dir ... ; use this add-include-book-dir directory
:standard-co ... ; open char out or file to open and close
:proofs-co ... ; open char out or file to open and close
:current-package ... ; known package name
:ld-skip-proofsp ... ; nil, 'include-book, or t
; (see [ld-skip-proofsp])
:ld-redefinition-action ... ; nil or '(:a . :b)
:ld-prompt ... ; nil, t, or some prompt printer fn
:ld-missing-input-ok ... ; nil, t, :warn, or warning message
:ld-pre-eval-filter ... ; :all, :query, or some new name
:ld-pre-eval-print ... ; nil, t, or :never
:ld-post-eval-print ... ; nil, t, or :command-conventions
:ld-evisc-tuple ... ; nil or '(alist nil nil level length)
:ld-error-triples ... ; nil or t
:ld-error-action ... ; :return!, :return, :continue, :error,
; or (:exit N)
:ld-query-control-alist ... ; alist supplying default responses
:ld-verbose ...) ; nil or t
Ld is the top-level ACL2 read-eval-print loop. (When you call [lp], a
little initialization is done in raw Common Lisp and then ld is
called.) Ld is also a general-purpose ACL2 file loader and a
[command] interpreter. Ld is actually a macro that expands to a
function call involving [state]. Ld returns an ``error triple'' (mv
erp val state) as explained below. (For much more on error triples,
see [programming-with-state].)
See [rebuild] for a variant of ld that skips proofs. See
[output-to-file] for examples showing how to redirect output to a
file.
The arguments to ld, except for :dir, all happen to be global
variables in [state] (see [state] and see
[programming-with-state]). For example, '[current-package] and
'[ld-verbose] are global variables, which may be accessed via (@
current-package) and (@ ld-verbose). When ld is called, it
``binds'' these variables. By ``binds'' we actually mean the
variables are globally set but restored to their old values on
exit. Because ld provides the illusion of [state] global variables
being bound, they are called ``ld specials'' (after the Lisp
convention of calling a variable ``special'' if it is referenced
freely after having been bound).
Note that all arguments but the first are passed via keyword. Any
variable not explicitly given a value in a call retains its
pre-call value, with the exception of :[ld-error-action], which
generally defaults to :return! if not explicitly specified.
Just as an example to drive the point home: If [current-package] is
\"ACL2\" and you typed
(ld *standard-oi* :current-package \"MY-PKG\")
you would find yourself in (an inner) read-eval-print loop in which
the [current-package] was \"MY-PKG\". You could operate there as long
as you wished, changing the current package at will. But when you
typed :[q] you would return to the outer read-eval-print loop where
the current package would still be \"ACL2\".
Roughly speaking, ld repeatedly reads a form from [standard-oi],
evaluates it, and prints its result to [standard-co]. It does this
until the form is :[q] or evaluates to an error triple whose value
component is :[q], or until the input channel or list is emptied.
However, ld has many bells and whistles controlled by the ld
specials. Each such special is documented individually. For
example, see the documentation for [standard-oi],
[current-package], [ld-pre-eval-print], etc.
A more precise description of ld is as follows. In the description
below we use the ld specials as variables, e.g., we say ``a form is
read from [standard-oi].'' By this usage we refer to the current
value of the named [state] global variable, e.g., we mean ``a form
is read from the current value of '[standard-oi].'' This
technicality has an important implication: If while interacting
with ld you change the value of one of the ld specials, e.g.,
'[standard-oi], you will change the behavior of ld, e.g.,
subsequent input will be taken from the new value.
Three ld specials are treated as channels: [standard-oi] is treated
as an object input channel and is the source of forms evaluated by
ld; [standard-co] and [proofs-co] are treated as character output
channels and various flavors of output are printed to them.
However, the supplied values of these specials need not actually be
channels; several special cases are recognized.
If the supplied value of one of these is in fact an open channel of
the appropriate type, that channel is used and is not closed by ld.
If the supplied value of one of these specials is a string, the
string is treated as a file name in (essentially) Unix syntax (see
[pathname]) and a channel of the appropriate type is opened to/from
that file. Any channel opened by ld during the binding of the ld
specials is automatically closed by ld upon termination. If
[standard-co] and [proofs-co] are equal strings, only one channel
to that file is opened and is used for both.
As a special convenience, when [standard-oi] is a string and the :dir
argument provided and not nil, we look up :dir in the table of
directories maintained by [add-include-book-dir], and prepend this
directory to [standard-oi] to create the filename. (In this case,
however, we require that standard-oi is a relative pathname, not an
absolute pathname.) For example, one can write (ld
\"arithmetic/top-with-meta.lisp\" :dir :system) to ld that particular
community books library. (Of course, you should almost always load
books like arithmetic/top-with-meta using [include-book] instead of
ld.) If :dir is not specified, then a relative pathname is resolved
using the connected book directory; see [cbd].
Several other alternatives are allowed for [standard-oi]. If
[standard-oi] is a true list then it is taken as the list of forms
to be processed. If [standard-oi] is a list ending in an open
channel, then ld processes the forms in the list and then reads and
processes the forms from the channel. Analogously, if [standard-oi]
is a list ending a string, an object input channel from the named
file is opened and ld processes the forms in the list followed by
the forms in the file. That channel is closed upon termination of
ld.
In the cases that a string is to be converted to an object input
channel --- that is, when [standard-oi] is a string or is a list
ending in a string --- an error occurs by default if the conversion
fails, presumably because the file named by the string does not
exist. However, if keyword argument :ld-missing-input-ok is t, then
ld immediately returns without error in this case, but without
reading or executing any forms, as though standard-oi is nil and
keyword arguments :ld-verbose and ld-prompt both have value nil.
The other legal values for :ld-missing-input-ok are nil, which
gives the default behavior, and :warn, which behaves the same as t
except that a warning is printed, which contains the same
information as would be printed for the default error described
above.
The remaining ld specials are handled more simply and generally have
to be bound to one of a finite number of tokens described in the
:[doc] entries for each ld special. Should any ld special be
supplied an inappropriate value, an error message is printed.
Next, if [ld-verbose] is t, ld prints the message ``ACL2 loading
name'' where name names the file or channel from which forms are
being read. At the conclusion of ld, it will print ``Finished
loading name'' if [ld-verbose] is t.
Finally, ld repeatedly executes the ACL2 read-eval-print step, which
may be described as follows. A [prompt] is printed to [standard-co]
if [ld-prompt] is non-nil. The format of the [prompt] is determined
by [ld-prompt]. If it is t, the default ACL2 [prompt] is used. If
it is any other non-nil value then it is treated as an ACL2
function that will print the desired [prompt]. See [ld-prompt]. In
the exceptional case where ld's input is coming from the terminal
(*standard-oi*) but its output is going to a different sink (i.e.,
[standard-co] is not [*standard-co*]), we also print the [prompt]
to the terminal.
Ld then reads a form from [standard-oi]. If the object read is a
keyword, ld constructs a ``keyword command form'' by possibly
reading several more objects. See [keyword-commands]. This
construction process is sensitive to the value of
[ld-keyword-aliases]. See [ld-keyword-aliases]. Otherwise, the
object read is treated as the command form.
Ld next decides whether to evaluate or skip this form, depending on
[ld-pre-eval-filter]. Initially, the filter must be either :all,
:query, or a new name. If it is :all, it means all forms are
evaluated. If it is :query, it means each form that is read is
displayed and the user is queried. Otherwise, the filter is a name
and each form that is read is evaluated as long as the name remains
new, but if the name is ever introduced then no more forms are read
and ld terminates. See [ld-pre-eval-filter].
If the form is to be evaluated, then ld first prints the form to
[standard-co], if [ld-pre-eval-print] is t. With this feature, ld
can process an input file or form list and construct a script of
the session that appears as though each form was typed in. See
[ld-pre-eval-print].
Ld then evaluates the form, with [state] bound to the current
[state]. The result is some list of (multiple) values. If a [state]
is among the values, then ld uses that [state] as the subsequent
current [state].
Depending on [ld-error-triples], ld may interpret the result as an
``error.'' See [ld-error-triples]. We first discuss ld's behavior
if no error signal is detected (either because none was sent or
because ld is ignoring them because [ld-error-triples] is nil).
In the case of a non-erroneous result, ld does two things: First, if
the logical [world] in the now current [state] is different than
the [world] before execution of the form, ld adds to the [world] a
``[command] landmark'' containing the form evaluated. See
[command-descriptor]. Second, ld prints the result to
[standard-co], but only if [ld-post-eval-print] is not nil. The
result is printed as a list of (multiple) values unless
[ld-post-eval-print] is :command-conventions, [ld-error-triples] is
t, and the result is an [error-triple], i.e., of the form (mv * *
state). In that case, only the non-erroneous ``value'' component of
the result is printed. See [ld-post-eval-print].
Whenever ld prints anything (whether the input form, a query, or some
results) it ``eviscerates'' it if ld-evisc-tuple is non-nil.
Essentially, evisceration is a generalization of Common Lisp's use
of *print-level* and *print-length* to hide large substructures.
See [evisc-tuple] and also see [set-iprint].
We now return to the case of a form whose evaluation signals an
error. In this case, ld first restores the ACL2 logical [world] to
what it was just before the erroneous form was evaluated. Thus, a
form that partially changes the [world] (i.e., begins to store
properties) and then signals an error, has no effect on the
[world]. You may see this happen on [command]s that execute several
[events] (e.g., an [encapsulate] or a [progn] of several [defuns]):
even though the output makes it appear that the initial [events]
were executed, if an error is signalled by a later event the entire
block of [events] is discarded.
After rolling back, ld takes an action determined by
[ld-error-action]. If the action is :continue, ld merely iterates
the read-eval-print step. Note that nothing suggestive of the value
of the ``erroneous'' form is printed. If the action is :return, ld
terminates normally; similarly if the action is :return!, but a
special value is returned that can cause superior ld commands to
terminate; see [ld-error-action] for details. If the action is
:error, ld terminates signalling an error to its caller. If its
caller is in fact another instance of ld and that instance is
watching out for error signals, the entire [world] created by the
inner ld will be discarded by the outer ld if the inner ld
terminates with an error. Note that if the action is (:exit N),
then there is no rolling back, because ACL2 quits immediately with
exit status N.
Ld returns an error triple, (mv erp val state). Erp is t or nil
indicating whether an error is being signalled. If no error is
signalled, val is the ``reason'' ld terminated and is one of :exit
(meaning :[q] was read), :eof (meaning the input source was
exhausted), :error (meaning an error occurred but has been
suppressed), :filter (meaning the [ld-pre-eval-filter] terminated
ld), or a cons pair whose first component is the symbol :STOP-LD,
which typically indicates that an error occurred while the value of
variable '[ld-error-action] was :RETURN!. See [ld-error-action] for
details of this last case.
Subtopics
[A!]
To return to the top-level of ACL2's command loop
[Abort!]
To return to the top-level of ACL2's command loop
[Calling-ld-in-bad-contexts]
Errors caused by calling [ld] in inappropriate contexts
[Current-package]
The package used for reading and printing
[Default-print-prompt]
The default [prompt] printed by [ld]
[I-am-here]
A convenient marker for use with [rebuild] or [ld]
[Keyword-commands]
How keyword commands like :u and :pbt are processed
[Ld-error-action]
Determines [ld]'s response to an error
[Ld-error-triples]
Determines whether a form caused an error during [ld]
[Ld-evisc-tuple]
Determines whether [ld] suppresses details when printing
[Ld-keyword-aliases]
Abbreviation of some keyword commands
[Ld-missing-input-ok]
Determines which forms [ld] evaluates
[Ld-post-eval-print]
Determines whether and how [ld] prints the result of evaluation
[Ld-pre-eval-filter]
Determines which forms [ld] evaluates
[Ld-pre-eval-print]
Determines whether [ld] prints the forms to be eval'd
[Ld-prompt]
Determines the [prompt] printed by [ld]
[Ld-query-control-alist]
How to default answers to queries
[Ld-redefinition-action]
To allow redefinition without undoing
[Ld-skip-proofsp]
How carefully ACL2 processes your [command]s
[Ld-verbose]
Determines whether [ld] prints ``ACL2 Loading ...''
[Lp]
The Common Lisp entry to ACL2
[P!]
To pop up (at least) one level of ACL2's command loop
[Prompt]
The prompt printed by [ld]
[Rebuild]
A convenient way to reconstruct your old [state]
[Redef]
A common way to set [ld-redefinition-action]
[Redef!]
A common way to set [ld-redefinition-action]
[Redef+]
System hacker's redefinition [command]
[Redef-]
Turn off system hacker's redefinition [command]
[Reset-ld-specials]
Restores initial settings of the [ld] specials
[Wormhole]
[ld] without [state] --- a short-cut to a parallel universe")
(LD-ERROR-ACTION
(LD)
"Determines [ld]'s response to an error
Ld-error-action is an [ld] special (see [ld]). The accessor is
(ld-error-action state) and the updater is (set-ld-error-action val
state). Ld-error-action must be :continue, :return, :return!,
:error, or (:exit N) for some natural number N. The initial value
of ld-error-action is :continue, which means that the top-level
ACL2 [command] loop (see [lp]) will not exit when an error is
caused by user-typein. But the default value for ld-error-action on
calls of [ld] is :return!, with one exception: in the case that the
value of [ld] special ld-error-action is (:exit N), the default
remains that value.
The general-purpose ACL2 read-eval-print loop, [ld], reads forms from
[standard-oi], evaluates them and prints the result to
[standard-co]. Note that the ACL2 top-level loop (see [lp]) results
from an invocation of [ld].
However, there are various flags that control [ld]'s behavior and
ld-error-action is one of them. Suppose that [ld-error-triples] is
t and a form evaluates to an [error-triple] (mv erp val state). If
the ``error component'', erp, is non-nil, then an error is said to
have occurred. If an error occurs, [ld]'s action depends on
ld-error-action. If it is :continue, [ld] just continues processing
the forms in [standard-oi]. If it is :return or :return!, [ld]
stops and returns as though it had emptied the channel. If it is
:error, [ld] stops and returns, signalling an error to its caller
by returning an error triple with non-nil error component, and
reverting the logical [world] to its value just before that call of
[ld]. If it is (:exit N), then ACL2 quits with exit status N.
To see this effect of :ERROR for ld-error-action, consider the
following example.
(ld '((defun f (x) x) (defun bad (x)) (defun g (x) x)))
When the [defun] of bad fails (because its body is missing),
evaluation of the ld call stops; thus, the [defun] of g is not
evaluated. The definition of f will be removed from the logical
[world] before the call of ld returns.
However, by default each user call of ld is made with a
ld-error-action of :RETURN! (not :ERROR). In the common case that
all nested calls of ld inside the ACL2 loop are made this way, an
error will not roll back the logical [world]. However, it will
still halt evaluation of forms for the current call of ld and any
parent calls of ld (other than the call made on behalf of lp that
entered the ACL2 loop in the first place), as though there were no
more forms to evaluate.
We have already discussed the behavior of ld when an error occurs.
But there is another case when ld can stop processing more forms:
when ld-error-action is not :CONTINUE, [ld-error-triples] is t, and
evaluation of a form returns an error triple (mv nil val state),
where nil is the error component and whose ``value component'', val
is a [cons] pair whose [car] is the symbol :STOP-LD. Let val be the
pair (:STOP-LD . x). Then the call of ld returns the error triple
(mv nil (:STOP-LD n . x) state), where n is the value of [state]
global variable 'ld-level at the time of termination. The following
example illustrates how this works.
(ld '((defun f1 (x) x)
(ld '((defun f2 (x) x)
(mv nil '(:STOP-LD my-error more-info) state)
(defun g2 (x) x)))
(defun g1 (x) x)))
The outer call of ld returns the value
(:STOP-LD 2 3 MY-ERROR MORE-INFO)
and leaves us in a world the includes definitions for f1 and f2, but
no definition for g1 or g2 since neither of their two defun forms
was evaluated. The value of [state] global 'ld-level is incremented
from 1 to 2 when the outer ld is entered and then again to 3 when
the inner ld is entered. When the inner ld escounters the error
triple (mv nil (:STOP-LD my-error more-info) state), it sees
:STOP-LD in the car of the value component and pushes the current
value of 'ld-level, 3, onto the [cdr] of that value, to return the
value triple (mv nil (:STOP-LD my-error 3 more-info) state). The
outer of ld then sees this value and returns (mv nil (:STOP-LD
my-error 2 3 more-info) state), since its current value of
'ld-level is 2 after the inner ld exits.
That concludes our discussion of how these special :STOP-LD values
are handled; but how are they created? While they can be created
directly by evaluation results as suggested in the example above,
that is not the standard way. Rather, ld returns an error triple
(mv nil (:STOP-LD n) state), where n is the value of variable
ld-level at the time of termination, when the following conditions
hold: an error occurs, ld-error-action is RETURN! (which is the
default), and [ld-error-triples] is t (the default). The following
example, which is a bit similar to the preceding one, illustrates
both creation and handling of the special :STOP-LD values.
(ld '((defun f1 (x) x)
(ld '((defun f2 (x) x)
(ld '((defun f3 (x) x)
(defun bad (x)) ; ERROR -- missing the body
(defun g3 (x) x)))
(defun g2 (x) x)))
(defun g1 (x) x)))
The result is that f1, f2, and f3 are defined, but none of g1, g2, or
g3 is defined. Let's see why. The innermost call of [ld] has a
default :ld-error-action of :RETURN! (as do the other calls). So
when the definition of bad fails, then the innermost ld returns (mv
nil (:STOP-LD 4) state). The middle ld sees this value, and since
its :ld-error-action is not :CONTINUE (because it has the default
value of :RETURN!), it returns before considering the definition of
g2, with value (mv nil (:STOP-LD 3 4) state). The topmost call of
ld similarly sees the :STOP-LD; stops evaluation of forms, without
defining g1; and returns (mv nil (:STOP-LD 2 3 4) state).")
(LD-ERROR-TRIPLES
(LD)
"Determines whether a form caused an error during [ld]
Ld-error-triples is an [ld] special (see [ld]). The accessor is
(ld-error-triples state) and the updater is (set-ld-error-triples
val state). Ld-error-triples must be either t or nil. The initial
value of ld-error-triples is t.
The general-purpose ACL2 read-eval-print loop, [ld], reads forms from
[standard-oi], evaluates them and prints the result to
[standard-co]. Note that the ACL2 top-level loop (see [lp]) results
from an invocation of [ld].
However, there are various flags that control [ld]'s behavior and
ld-error-triples is one of them. If this variable has the value t
then when a form evaluates to an [error-triple] (mv erp val state)
such that erp is non-nil, then an error is deemed to have occurred.
When an error occurs in evaluating a form, [ld] rolls back the ACL2
[world] to the configuration it had at the conclusion of the last
error-free form. Then [ld] takes the action determined by
[ld-error-action].")
(LD-EVISC-TUPLE
(LD)
"Determines whether [ld] suppresses details when printing
Ld-evisc-tuple is an [ld] special (see [ld]). The accessor is
(ld-evisc-tuple state) and an updater is (set-ld-evisc-tuple val
state), although the use of [set-evisc-tuple] is preferred for
updating. Ld-evisc-tuple must be either nil, which is its initial
value, or a legal evisc-tuple: see [set-evisc-tuple].
The general-purpose ACL2 read-eval-print loop, [ld], reads forms from
[standard-oi], evaluates them and prints the result to
[standard-co]. Note that the ACL2 top-level loop (see [lp]) results
from an invocation of [ld].
However, there are various flags that control [ld]'s behavior and
ld-evisc-tuple is one of them. [Ld] may print the forms it is
evaluating and/or the results of evaluation. Depending on the value
of ld-evisc-tuple [ld] may ``eviscerate'' objects before printing
them. See [set-evisc-tuple] for a discussion of evisceration and of
how other evisc-tuples affect the printing of error messages and
warnings, as well as other output not from ld.")
(LD-KEYWORD-ALIASES
(LD)
"Abbreviation of some keyword commands
Examples:
(set-ld-keyword-aliases '((:q 0 q-fn)
(:e 0 exit-acl2-macro))
state)
(ld-keyword-aliases state) ; current value of the ld-keyword-aliases table
Ld-keyword-aliases is the name of a ACL2 table (see [table]) and also
the name of a function of state that returns the value of this
table. That value must be an alist, each element of which is of the
form (:keyword n fn), where :keyword is a keyword, n is a
nonnegative integer, and fn is a function symbol of arity n, a
macro symbol, or a lambda expression of arity n. When keyword is
typed as an [ld] command, n more forms are read, x1, ..., xn, and
the form (fn 'x1 ... 'xn) is then evaluated. The initial value of
the ld-keyword-aliases [table] is nil.
ACL2 provides functions to modify the ld-keyword-aliases table, as
follows.
(Set-ld-keyword-aliases val state): sets the table to val, which must
be a legal alist as described above. This is an event that may
go into a book (see [events]), but its effect will be [local]
to that book.
Set-ld-keyword-aliases! is the same as set-ld-keyword-aliases, except
that its effect is not [local]. Indeed, the form
(set-ld-keyword-aliases val state) is equivalent to the form
(local (set-ld-keyword-aliases! val state).
(Add-ld-keyword-alias key val state): modifies the table by binding
the keyword key to val, which must be a legal value as
described above. This is an event that may go into a book (see
[events]), but its effect will be [local] to that book.
Add-ld-keyword-alias! is the same as add-ld-keyword-alias, except
that its effect is not [local]. Indeed, the form
(add-ld-keyword-alias key val state) is equivalent to the form
(local (add-ld-keyword-alias! key val state).
Consider the first example above:
(set-ld-keyword-aliases '((:q 0 q-fn)
(:e 0 exit-acl2-macro))
state)
With this event, :[q] is redefined to have the effect of executing
(q-fn), so for example if you have defined q-fn with
(defmacro q-fn ()
'(er soft 'q \"You un-bound :q and now we have a soft error.\"))
then :[q] will cause an error, and if you have defined
(defmacro exit-acl2-macro () '(exit-ld state))
then :e will cause the effect (it so happens) that :[q] normally has.
If you prefer :e to :[q] for exiting the ACL2 loop, you might even
want to put such definitions of q-fn and exit-acl2-macro together
with the set-ld-keyword-aliases form above into your
\"acl2-customization.lsp\" file; see [ACL2-customization].
The general-purpose ACL2 read-eval-print loop, [ld], reads forms from
[standard-oi], evaluates them and prints the result to
[standard-co]. Note that the ACL2 top-level loop (see [lp]) results
from an invocation of [ld].
However, there are various flags that control [ld]'s behavior and
ld-keyword-aliases is one of them. Ld-keyword-aliases affects how
keyword commands are parsed. Generally speaking, [ld]'s command
interpreter reads ``:fn x1 ... xn'' as ``(fn 'x1 ... 'xn)'' when
:fn is a keyword and fn is the name of an n-ary function; see
[keyword-commands]. But this parse is overridden, as described
above, for the keywords bound in the ld-keyword-aliases [table].")
(LD-MISSING-INPUT-OK
(LD)
"Determines which forms [ld] evaluates
ld-missing-input-ok is an [ld] special (see [ld]). The accessor is
(ld-missing-input-ok state) and the updater is
(set-ld-missing-input-ok val state). ld-missing-input-ok must be
either nil, t, or :warn. The initial value of ld-missing-input-ok
is nil.
The general-purpose ACL2 read-eval-print loop, [ld], is controlled by
various flags that control its behavior, and ld-missing-input-ok is
one of them. In brief, the first argument of ld can indicate a file
from which to read input. If the file does not exist, it is an
error by default, but ld becomes essentially a no-op if t or :warn
is supplied for :ld-missing-input-ok, where :warn prints a warning.
Also see [ld].")
(LD-POST-EVAL-PRINT
(LD)
"Determines whether and how [ld] prints the result of evaluation
Ld-post-eval-print is an [ld] special (see [ld]). The accessor is
(ld-post-eval-print state) and the updater is
(set-ld-post-eval-print val state). Ld-post-eval-print must be
either t, nil, or :command-conventions. The initial value of
ld-post-eval-print is :command-conventions.
The general-purpose ACL2 read-eval-print loop, [ld], reads forms from
[standard-oi], evaluates them and prints the result to
[standard-co]. Note that the ACL2 top-level loop (see [lp]) results
from an invocation of [ld].
However, there are various flags that control [ld]'s behavior and
ld-post-eval-print is one of them. If this global variable is t,
[ld] prints the result. In the case of a form that produces a
multiple value, [ld] prints the list containing all the values
(which, logically speaking, is what the form returned). If
ld-post-eval-print is nil, [ld] does not print the values. This is
most useful when [ld] is used to load a previously processed file.
Finally, if ld-post-eval-print is :command-conventions and also
ld-error-triples is t, then [ld] prints the result but treats
``error triples'' specially. An ``error triple'' (see
[error-triple]) is a result, (mv erp val state), that consists of
two ordinary values and [state]. Many ACL2 functions use such
triples to signal errors. The convention is that if erp (the first
value) is nil, then the function is returning val (the second
value) as its conventional single result and possibly
side-effecting [state] (as with some output). If erp is not nil,
then an error has been caused, val is irrelevant and the error
message has been printed in the returned [state]. Example ACL2
functions that follow this convention include [defun] and
[in-package]. If such ``error producing'' functions are evaluated
while ld-post-eval-print is set to t, then you would see them
producing lists of length 3. This is disconcerting to users
accustomed to Common Lisp (where these functions produce single
results but sometimes cause errors or side-effect [state]). For
more information about error triples, see [programming-with-state].
When ld-post-eval-print is :command-conventions and a form produces
an error triple (mv erp val state) as its value, [ld] prints
nothing if erp is non-nil and otherwise [ld] prints just val.
Because it is a misrepresentation to suggest that just one result
was returned, [ld] prints the value of the global variable
'triple-print-prefix before printing val. 'triple-print-prefix is
initially \" \", which means that when non-erroneous error triples
are being abbreviated to val, val appears one space off the left
margin instead of on the margin.
In addition, when ld-post-eval-print is :command-conventions and the
value component of an error triple is the keyword :invisible then
[ld] prints nothing. This is the way certain commands (e.g., :[pc])
appear to return no value.
By printing nothing when an error has been signalled, [ld] makes it
appear that the error (whose message has already appeared in
[state]) has ``thrown'' the computation back to load without
returning a value. By printing just val otherwise, we suppress the
fact that [state] has possibly been changed.")
(LD-PRE-EVAL-FILTER
(LD)
"Determines which forms [ld] evaluates
Ld-pre-eval-filter is an [ld] special (see [ld]). The accessor is
(ld-pre-eval-filter state) and the updater is
(set-ld-pre-eval-filter val state). Ld-pre-eval-filter must be
either :all, :query, or a new name that could be defined (e.g., by
[defun] or [defconst]). The initial value of ld-pre-eval-filter is
:all.
The general-purpose ACL2 read-eval-print loop, [ld], reads forms from
[standard-oi], evaluates them and prints the result to
[standard-co]. Note that the ACL2 top-level loop (see [lp]) results
from an invocation of [ld].
However, there are various flags that control [ld]'s behavior and
ld-pre-eval-filter is one of them. If the filter is :all, then
every form read is evaluated. If the filter is :query, then after a
form is read it is printed to [standard-co] and the user is asked
if the form is to be evaluated or skipped. If the filter is a new
name, then all forms are evaluated until that name is introduced,
at which time [ld] terminates normally.
The :all filter is, of course, the normal one. :Query is useful if
you want to replay selected the [command]s in some file. The new
name filter is used if you wish to replay all the [command]s in a
file up through the introduction of the given one.")
(LD-PRE-EVAL-PRINT
(LD)
"Determines whether [ld] prints the forms to be eval'd
Ld-pre-eval-print is an [ld] special (see [ld]). The accessor is
(ld-pre-eval-print state) and the updater is (set-ld-pre-eval-print
val state). Ld-pre-eval-print must be either t, nil, or :never. The
initial value of ld-pre-eval-print is nil.
The general-purpose ACL2 read-eval-print loop, [ld], reads forms from
[standard-oi], evaluates them and prints the result to
[standard-co]. Note that the ACL2 top-level loop (see [lp]) results
from an invocation of [ld].
However, there are various flags that control [ld]'s behavior and
ld-pre-eval-print is one of them. If this global variable is t,
then before evaluating the form just read from [standard-oi], [ld]
prints the form to [standard-co]. If the variable is nil, no such
printing occurs. The t option is useful if you are reading from a
file of [command]s and wish to assemble a complete script of the
session in [standard-co].
The value :never of ld-pre-eval-print is rarely used. During the
evaluation of [encapsulate] and of [certify-book] forms, subsidiary
events are normally printed, even if ld-pre-eval-print is nil. Thus
for example, when the user submits an [encapsulate] form, all
subsidiary events are generally printed even in the default
situation where ld-pre-eval-print is nil. But occasionally one may
want to suppress such printing. In that case, ld-pre-eval-print
should be set to :never. As described elsewhere (see
[set-inhibit-output-lst]), another way to suppress such printing is
to execute (set-inhibit-output-lst lst) where lst evaluates to a
list including 'prove and 'event.")
(LD-PROMPT
(LD)
"Determines the [prompt] printed by [ld]
Ld-prompt is an [ld] special (see [ld]). The accessor is (ld-prompt
state) and the updater is (set-ld-prompt val state). Ld-prompt must
be either nil, t, or a function symbol that, when given an open
output character channel and [state], prints the desired [prompt]
to the channel and returns two values: the number of [characters]
printed and the [state]. The initial value of ld-prompt is t.
The general-purpose ACL2 read-eval-print loop, [ld], reads forms from
[standard-oi], evaluates them and prints the result to
[standard-co]. Note that the ACL2 top-level loop (see [lp]) results
from an invocation of [ld].
However, there are various flags that control [ld]'s behavior and
ld-prompt is one of them. Ld-prompt determines whether [ld] prints
a [prompt] before reading the next form from [standard-oi]. If
ld-prompt is nil, [ld] prints no [prompt]. If ld-prompt is t, the
default [prompt] printer is used, which displays information that
includes the current package, default [defun-mode], [guard]
checking status (on or off), and [ld-skip-proofsp]; see
[default-print-prompt].
If ld-prompt is neither nil nor t, then it should be a function name,
fn, such that (fn channel state) will print the desired [prompt] to
channel in [state] and return (mv col state), where col is the
number of [characters] output (on the last line output). You may
define your own [prompt] printing function.
If you supply an inappropriate [prompt] function, i.e., one that
causes an error or does not return the correct number and type of
results, the following odd [prompt] will be printed instead:
Bad Prompt
See :DOC ld-prompt>
which will lead you to this message. You should either call [ld]
appropriately next time or assign an appropriate value to
ld-prompt.")
(LD-QUERY-CONTROL-ALIST
(LD)
"How to default answers to queries
Ld-query-control-alist is an [ld] special (see [ld]). The accessor is
(ld-query-control-alist state) and the updater is
(set-ld-query-control-alist val state). Roughly speaking,
ld-query-control-alist is either nil (meaning all queries should be
interactive), t (meaning all should default to the first accepted
response), or an alist that pairs query ids to keyword responses.
The alist may end in either t or nil, indicating the default value
for all ids not listed explicitly. Formally, the
ld-query-control-alist must satisfy ld-query-control-alistp. The
initial ld-query-control-alist is nil, which means all queries are
handled interactively.
When an ACL2 query is raised, a unique identifying symbol is printed
in parentheses after the word ``Query''. This symbol, called the
``query id,'' can be used in conjunction with
ld-query-control-alist to prevent the query from being handled
interactively. By ``handled interactively'' we mean that the query
is printed to [*standard-co*] and a response is read from
[*standard-oi*]. The alist can be used to obtain a ``default
value'' for each query id. If this value is nil, then the query is
handled interactively. In all other cases, the system handles the
query without interaction (although text may be printed to
[standard-co] to make it appear that an interaction has occurred;
see below). If the default value is t, the system acts as though
the user responded to the query by typing the first response listed
among the acceptable responses. If the default value is neither nil
nor t, then it must be a keyword and one of the acceptable
responses. In that case, the system acts as though the user
responded with the given keyword.
Next, we discuss how the ld-query-control-alist assigns a default
value to each query id. It assigns each id the first value paired
with the id in the alist, or, if no such pair appears in the alist,
it assigns the final [cdr] of the alist as the value. Thus, nil
assigns all ids nil. T assigns all ids t. '((:filter . nil)
(:sysdef . :n) . t) assigns nil to the :filter query, :n to the
:sysdef query, and t to all others.
It remains only to discuss how the system prints text when the
default value is not nil, i.e., when the query is handled without
interaction. In fact, it is allowed to pair a query id with a
singleton list containing a keyword, rather than a keyword, and
this indicates that no printing is to be done. Thus for the example
above, :sysdef queries would be handled noninteractively, with
printing done to simulate the interaction. But if we change the
example so that :sysdef is paired with (:n), i.e., if
ld-query-control-alist is '((:filter . nil) (:sysdef :n) . t), then
no such printing would take place for sysdef queries. Instead, the
default value of :n would be assigned ``quietly''.")
(LD-REDEFINITION-ACTION
(LD)
"To allow redefinition without undoing
Ld-redefinition-action is an [ld] special (see [ld]). The accessor is
(ld-redefinition-action state) and the updater is
(set-ld-redefinition-action val state).
WARNING! If ld-redefinition-action is non-nil then ACL2 is liable to
be made unsafe or unsound either by ill-considered definitions, or
because redefining a macro or inlined function called in the body
of a function, g, may not cause the new definition to be called by
g. The keyword command :[redef] will set ld-redefinition-action to
a convenient setting allowing unsound redefinition. See below.
When ld-redefinition-action is nil, redefinition is prohibited. In
that case, an error message is printed upon any attempt to
introduce a name that is already in use. There is one exception to
this rule. It is permitted to redefine a function symbol in
:[program] mode to be a function symbol in :[logic] mode provided
the formals and body remain the same. This is the standard way a
function ``comes into'' logical existence.
Throughout the rest of this discussion we exclude from our meaning of
``redefinition'' the case in which a function in :[program] mode is
identically redefined in :[logic] mode. At one time, ACL2 freely
permitted the [signature]-preserving redefinition of :[program]
mode functions but it no longer does. See [redefining-programs].
When ld-redefinition-action is non-nil, you are allowed to redefine a
name that is already in use. The system may be rendered unsound by
such an act. It is important to understand how dangerous
redefinition is. Suppose fn is a function symbol that is called
from within some other function, say g. Suppose fn is redefined so
that its arity changes. Then the definition of g is rendered
syntactically ill-formed by the redefinition. This can be
devastating since the entire ACL2 system assumes that terms in its
database are well-formed. For example, if ACL2 executes g by
running the corresponding function in raw Common Lisp the
redefinition of fn may cause raw lisp to break in irreparable ways.
As Lisp programmers we live with this all the time by following the
simple rule: after changing the syntax of a function don't run any
function that calls it via its old syntax. This rule also works in
the context of the evaluation of ACL2 functions, but it is harder
to follow in the context of ACL2 deductions, since it is hard to
know whether the database contains a path leading the theorem
prover from facts about one function to facts about another.
Finally, of course, even if the database is still syntactically
well-formed there is no assurance that all the rules stored in it
are valid. For example, theorems proved about g survive the
redefinition of fn but may have crucially depended on the
properties of the old fn. In summary, we repeat the warning: all
bets are off if you set ld-redefinition-action to non-nil.
ACL2 provides some enforcement of the concern above, by disabling
[certify-book] if any [world]-changing [events] exist in the
certification [world] that were executed with a non-nil value of
'ld-redefinition-action. (This value is checked at the end of each
top-level command, but the value does not change during evaluation
of embedded event forms; see [embedded-event-form].)
If at any point in a session you wish to see the list of all names
that have been redefined, see [redefined-names].
That said, we'll give you enough rope to hang yourself. When
ld-redefinition-action is non-nil, it must be a pair, (a . b). The
value of a determines how the system interacts with you when a
redefinition is submitted. The value of b allows you to specify how
the property list of the redefined name is to be ``renewed'' before
the redefinition.
There are several dimensions to the space of possibilities controlled
by part a: Do you want to be queried each time you redefine a name,
so you can confirm your intention? (We sometimes make typing
mistakes or simply forget we have used that name already.) Do you
want to see a warning stating that the name has been redefined? Do
you want ACL2 system functions given special protection from
possible redefinition? Below are the choices for part a:
:query --- every attempt to redefine a name will produce a query. The
query will allow you to abort the redefinition or proceed. It
will will also allow you to specify the part b for this
redefinition. :Query is the recommended setting for users who
wish to dabble in redefinition.
:warn --- any user-defined function may be redefined but a
post-redefinition warning is printed. The attempt to redefine a
system name produces a query. If you are prototyping and
testing a big system in ACL2 this is probably the desired
setting for part a.
:doit --- any user-defined function may be redefined silently
(without query or warning) but when an attempt is made to
redefine a system function, a query is made. This setting is
recommended when you start making massive changes to your
prototyped system (and tire of even the warning messages issued
by :warn).
In support of our own ACL2 systems [programming] there are two other
settings. We suggest ordinary users not use them.
:warn! --- every attempt to redefine a name produces a warning but no
query. Since ACL2 system functions can be redefined this way,
this setting should be used by the only-slightly-less-than
supremely confident ACL2 system hacker.
:doit! --- this setting allows any name to be redefined silently
(without query or warnings). ACL2 system functions are fair
game. This setting is reserved for the supremely confident ACL2
system hacker. (Actually, this setting is used when we are
loading massively modified versions of the ACL2 source files.)
Part b of ld-redefinition-action tells the system how to ``renew''
the property list of the name being redefined. There are two
choices:
:erase --- erase all properties stored under the name, or
:overwrite --- preserve existing properties and let the redefining
overwrite them.
It should be stressed that neither of these b settings is guaranteed
to result in an entirely satisfactory state of affairs after the
redefinition. Roughly speaking, :erase returns the property list of
the name to the state it was in when the name was first introduced.
Lemmas, type information, etc., stored under that name are lost. Is
that what you wanted? Sometimes it is, as when the old definition
is ``completely wrong.'' But other times the old definition was
``almost right'' in the sense that some of the work done with it is
still (intended to be) valid. In that case, :overwrite might be the
correct b setting. For example if fn was a function and is being
re-[defun]'d with the same [signature], then the properties stored
by the new [defun] should overwrite those stored by the old [defun]
but the properties stored by [defthm]s will be preserved.
In addition, neither setting will cause ACL2 to erase properties
stored under other symbols! Thus, if FOO names a rewrite rule which
rewrites a term beginning with the function symbol BAR and you then
redefine FOO to rewrite a term beginning with the function symbol
BAZ, then the old version of FOO is still available (because the
rule itself was added to the rewrite rules for BAR, whose property
list was not cleared by redefining FOO).
The b setting is only used as the default action when no query is
made. If you choose a setting for part a that produces a query then
you will have the opportunity, for each redefinition, to specify
whether the property list is to be erased or overwritten.
The keyword command :[redef] sets ld-redefinition-action to the pair
(:query . :overwrite). Since the resulting query will give you the
chance to specify :erase instead of :overwrite, this setting is
quite convenient. But when you are engaged in heavy-duty
prototyping, you may wish to use a setting such as :warn or even
:doit. For that you will have to invoke a form such as:
(set-ld-redefinition-action '(:doit . :overwrite) state) .
[Encapsulate] causes somewhat odd interaction with the user if
redefinition occurs within the encapsulation because the
[encapsulate]d event list is processed several times. For example,
if the redefinition action causes a query and a non-local
definition is actually a redefinition, then the query will be posed
twice, once during each pass. C'est la vie.
Finally, it should be stressed again that redefinition is dangerous
because not all of the rules about a name are stored on the
property list of the name. Thus, redefinition can render ill-formed
terms stored elsewhere in the database or can preserve now-invalid
rules. See [redundant-events], in particular the section ``Note
About Unfortunate Redundancies,'' for more discussion of potential
pitfalls of redefinition.")
(LD-SKIP-PROOFSP
(LD)
"How carefully ACL2 processes your [command]s
Examples:
ACL2 !>(set-ld-skip-proofsp t state)
T
ACL2 !s>(set-ld-skip-proofsp nil state)
NIL
ACL2 !>(set-ld-skip-proofsp 'include-book state)
INCLUDE-BOOK
ACL2 !s>
A global variable in the ACL2 [state], called 'ld-skip-proofsp,
determines the thoroughness with which ACL2 processes your
[command]s. This variable may take on one of three values: t, nil
or '[include-book]. When ld-skip-proofsp is non-nil, the system
assumes that which ought to be proved and is thus unsound. The form
(set-ld-skip-proofsp flg state) is the general-purpose way of
setting ld-skip-proofsp. This global variable is an ``[ld]
special,'' which is to say, you may call [ld] in such a way as to
``bind'' this variable for the dynamic extent of the [ld].
When ld-skip-proofsp is non-nil, the default [prompt] displays the
character s. Thus, the [prompt]
ACL2 !s>
means that the default [defun-mode] is :[logic] (otherwise the
character p, for :[program], would also be printed; see
[default-print-prompt]) but ``proofs are being skipped.''
Observe that there are two legal non-nil values, t and
'[include-book]. When ld-skip-proofsp is t, ACL2 skips all proof
obligations but otherwise performs all other required analysis of
input [events]. When ld-skip-proofsp is '[include-book], ACL2 skips
not only proof obligations but all analysis except that required to
compute the effect of successfully executed [events]. To explain
the distinction, let us consider one particular event, say a
[defun]. Very roughly speaking, a [defun] event normally involves a
check of the syntactic well-formedness of the submitted definition,
the generation and proof of the termination conditions, and the
computation and storage of various rules such as a :[definition]
rule and some :[type-prescription] rules. By ``normally'' above we
mean when ld-skip-proofsp is nil. How does a [defun] behave when
ld-skip-proofsp is non-nil?
If ld-skip-proofsp is t, then [defun] performs the syntactic
well-formedness checks and computes and stores the various rules,
but it does not actually carry out the termination proofs. If
ld-skip-proofsp is '[include-book], [defun] does not do the
syntactic well-formedness check nor does it carry out the
termination proof. Instead, it merely computes and stores the rules
under the assumption that the checks and proofs would all succeed.
Observe that a setting of '[include-book] is ``stronger'' than a
setting of t in the sense that '[include-book] causes [defun] to
assume even more about the admissibility of the event than t does.
As one might infer from the choice of name, the [include-book] event
sets ld-skip-proofsp to '[include-book] when processing the
[events] in a book being loaded. Thus, [include-book] does the
miminal work necessary to carry out the effects of every event in
the book. The syntactic checks and proof obligations were,
presumably, successfully carried out when the book was certified.
A non-nil value for ld-skip-proofsp also affects the system's output
messages. Event summaries (the paragraphs that begin ``Summary''
and display the event forms, rules used, etc.) are not printed when
ld-skip-proofsp is non-nil. Warnings and observations are printed
when ld-skip-proofsp is t but are not printed when it is
'[include-book].
Intuitively, ld-skip-proofsp t means skip just the proofs and
otherwise do all the work normally required for an event; while
ld-skip-proofsp '[include-book] is ``stronger'' and means do as
little as possible to process [events]. In accordance with this
intuition, [local] [events] are processed when ld-skip-proofsp is t
but are skipped when ld-skip-proofsp is '[include-book].
The ACL2 system itself uses only two settings, nil and
'[include-book], the latter being used only when executing the
[events] inside of a book being included. The ld-skip-proofsp
setting of t is provided as a convenience to the user. For example,
suppose one has a file of [events]. By loading it with [ld] with
ld-skip-proofsp set to t, the [events] can all be checked for
syntactic correctness and assumed without proof. This is a
convenient way to recover a state lost by a system crash or to
experiment with a modification of an [events] file.
The foregoing discussion is actually based on a lie. ld-skip-proofsp
is allowed two other values, 'initialize-acl2 and
'include-book-with-locals. The first causes behavior similar to t
but skips [local] [events] and avoids some error checks that would
otherwise prevent ACL2 from properly booting. The second is
identical to '[include-book] but also executes [local] [events].
These additional values are not intended for use by the user, but
no barriers to their use have been erected.
We close by reminding the user that ACL2 is potentially unsound if
ld-skip-proofsp is ever set by the user. We provide access to it
simply to allow experimentation and rapid reconstruction of lost or
modified logical [world]s.")
(LD-VERBOSE
(LD)
"Determines whether [ld] prints ``ACL2 Loading ...''
Ld-verbose is an [ld] special (see [ld]). The accessor is (ld-verbose
state) and the updater is (set-ld-verbose val state). Ld-verbose
must be t, nil or a string or [consp] suitable for [fmt] printing
via the ~@ command. The initial value of ld-verbose is a [fmt]
message that prints the ACL2 version number, [ld] level and
connected book directory.
Note: Ld-verbose has no effect on proofs. See [set-gag-mode] and see
[set-inhibit-output-lst] for how to control the size of proof
output.
Before processing the forms in [standard-oi], [ld] may print a
header. The printing of this header is controlled by ld-verbose. If
ld-verbose is nil, no header is printed. If it is t, [ld] prints
the message
ACL2 loading <file>
where <file> is the input channel supplied to [ld]. A similar message
is printed when [ld] completes. If ld-verbose is neither t nor nil
then it is presumably a header and is printed with the ~@ [fmt]
directive before [ld] begins to read and process forms. In this
case the ~@ [fmt] directive is interpreted in an environment in
which #\\v is the ACL2 version string, #\\l is the level of the
current recursion in [ld] and/or [wormhole], and #\\c is the
connected book directory (cbd).")
(LEMMA-INSTANCE
(HINTS FUNCTIONAL-INSTANTIATION)
"An object denoting an instance of a theorem
Lemma instances are the objects one provides via :use and :by [hints]
(see [hints]) to bring to the theorem prover's attention some
previously proved or easily provable fact. A typical use of the
:use hint is given below. The value specified is a list of five
lemma instances.
:use (reverse-reverse
(:type-prescription app)
(:instance assoc-of-app
(x a) (y b) (z c))
(:functional-instance p-f
(p consp) (f flatten))
(:instance (:theorem (equal x x))
(x (flatten a))))
Observe that an event name can be a lemma instance. The :use hint
allows a single lemma instance to be provided in lieu of a list, as
in:
:use reverse-reverse
or
:use (:instance assoc-of-app (x a) (y b) (z c))
A lemma instance denotes a formula which is either known to be a
theorem or which must be proved to be a theorem before it can be
used. To use a lemma instance in a particular subgoal, the theorem
prover adds the formula as a hypothesis to the subgoal before the
normal theorem proving heuristics are applied.
A lemma instance, or lmi, is of one of the following five forms:
(1) name, where name names a previously proved theorem, axiom, or
definition and denotes the formula (theorem) of that name.
(2) rune, where rune is a [rune] (see [rune]) denoting the
:[corollary] justifying the rule named by the [rune].
(3) (:theorem term), where term is any term alleged to be a theorem.
Such a lemma instance denotes the formula term. But before using
such a lemma instance the system will undertake to prove term.
(4) (:instance lmi (v1 t1) ... (vn tn)), where lmi is recursively a
lemma instance, the vi's are distinct variables, and the ti's are
terms. Such a lemma instance denotes the formula obtained by
instantiating the formula F denoted by lmi, normally by replacing
each vi by ti in F and requiring that each vi must be bound in F.
There are two exceptions. If the keyword :extra-bindings-ok is
inserted immediately after the lemma instance in order to remove
that requirement, as follows, then that requirement is ignored:
(:instance lmi :extra-bindings-ok (v1 t1) ... (vn tn)). Otherwise,
if one or more variables vi do not occur in F, but for each such vi
exactly one variable v with the same [symbol-name] as vi occurs in
F and no other vj with the same symbol-name as v is bound in the
substitution, then the pair (vi ti) is replaced by the pair (v ti)
in the substitution.
(5) (:functional-instance lmi (f1 g1) ... (fn gn)), where lmi is
recursively a lemma instance and each fi is an ``instantiable''
function symbol of arity ni and gi is a function symbol, a macro
alias for a function symbol gi' (see [macro-aliases-table]) in
which case we treat gi as gi', or a pseudo-lambda expression of
arity ni. An instantiable function symbol is any defined or
constrained function symbol except the primitives [not], [member],
[implies], and [o<], and a few others, as listed by the constant
*non-instantiable-primitives*. These are built-in in such a way
that we cannot recover the [constraint]s on them. (Special case: a
function introduced in the :partial-theory of a dependent
clause-processor is not instantiable; see
[define-trusted-clause-processor].) A pseudo-lambda expression is
an expression of the form (lambda (v1 ... vn) body) where the vi
are distinct variable symbols and body is any term. No a priori
relation is imposed between the vi and the variables of body, i.e.,
body may ignore some vi's and may contain ``free'' variables.
However, we do not permit v to occur freely in body if the
functional substitution is to be applied to any formula (lmi or the
[constraint]s to be satisfied) in a way that inserts v into the
scope of a binding of v by [let] or [mv-let] (or, [lambda]). If you
happen to violate this restriction, an informative error message
will be printed. That message will list for you the potentially
illegal choices for v in the context in which the functional
substitution is offered. A :functional-instance lemma instance
denotes the formula obtained by functionally instantiating the
formula denoted by lmi, replacing fi by gi. However, before such a
lemma instance can be used, the system will generate proof
obligations arising from the replacement of the fi's by the gi's in
constraints that ``support'' the lemma to be functionally
instantiated; see [constraint]. One might expect that if the same
instantiated constraint were generated on behalf of several events,
then each of those instances would have to be proved. However, for
the sake of efficiency, ACL2 stores the fact that such an
instantiated constraint has been proved and avoids it in future
events.
See [functional-instantiation-example] for an example of the use of
:functional-instance (so-called ``functional instantiation'').
Note that ACL2(r) (see [real]) imposes additional requirements for
functional instantiation. See [functional-instantiation-in-ACL2r].
(6) (:termination-theorem name) or (:termination-theorem! name),
where name is a function symbol in [logic] mode. Such a lemma
instance denotes the termination theorem previously proved for
name. If no such theorem exists --- for example, if the definition
of name is not recursive --- then the lemma instance is illegal in
the case of :termination-theorem, but denotes T in the case of
:termination-theorem!. If name is defined as part of a
mutually-recursive clique of definitions (see [mutual-recursion]),
then the lemma instance refers to the termination theorem proved
for the entire clique. See [termination-theorem-example] and see
[tthm].
(7) (:guard-theorem name), where name is a [guard]-verified function
symbol (hence, in particular, is in [logic] mode). Such a lemma
instance denotes the guard theorem previously proved for name. If
name is defined as part of a mutually-recursive clique of
definitions (see [mutual-recursion]), then the lemma instance
refers to the guard theorem proved for the entire clique. See
[guard-theorem-example] and see [gthm].
Obscure case for [definition]s. If the lemma instance refers to a
:definition [rune], then it refers to the [corollary] formula of
that rune, which can be a simplified (``normalized'') form of the
original formula. However, if the hint is a :by hint and the lemma
instance is based on a name (i.e., a symbol), rather than a rune,
then the formula is the original formula of the event, as shown by
:[pe], rather than the normalized version, as shown by :[pf]. This
is as one would expect: If you supply the name of an event, you
expect it to refer to the original event. For :use hints we use the
simplified (normalized) form instead, which is reasonable since one
would expect simplification during the proof that re-traces the
normalization done at the time the rule was created.
We conclude with remarks on (6) and (7). The termination or guard
theorem actually used is an unsimplified version of what was
originally proved for the indicated function. That is: while in
general, the termination or guard theorem is simplified before
being given to the prover, nevertheless the unsimplified theorem is
what is actually used for these lemma instances. See
[guard-obligation] for how to obtain the simplified guard theorem.
Moreover, the :[measure-debug] and :[guard-debug] keywords for
[xargs] are ignored when generating the termination or guard
theorem. You can see the termination or guard theorem for an
existing function symbol FN by evaluating the form
(termination-theorem 'FN (w state)) or (guard-theorem 'FN (w state)
state), respectively. In the former case, failure is indicated by a
result of the form (FAILED . msg), where msg is a message suitable
for [fmt]; see [msg].
Why do we avoid simplification (as described in the preceding
paragraph)? The reason is that it could in principle strengthen the
theorems, which is sound when admitting the original function but
not for lemma instances. Future work might try to allow
simplification at lemma-instance time, by ensuring that
simplification never strengthens the theorem. Alternatively,
simplification might be checked for each usage to be
equivalence-preserving by defining a suitable macro based on
[make-event]. For now, by avoiding simplification we guarantee that
the theorem we are using is truly a theorem. The theorem being used
might not be exactly the theorem originally proved, for example
because of the use of [case-split-limitations], which depends on
the current logical [world]; but we expect the two theorems to be
logically equivalent.
Subtopics
[Guard-theorem]
Use a previously-proved [guard] theorem
[Guard-theorem-example]
How to use a previously-proved [guard] theorem
[Termination-theorem]
Use a previously-proved measure theorem
[Termination-theorem-example]
How to use a previously-proved measure theorem")
(LEN
(LISTS ACL2-BUILT-INS)
"Length of a list
Len returns the length of a list.
A Common Lisp function that is appropriate for both strings and
proper lists is length; see [length]. The guard for len is t.
(Low-level implementation note. ACL2 provides a highly-optimized
implementation of len, which is tail-recursive and fixnum-aware,
that differs from its simple ACL2 definition.)
Function: <len>
(defun len (x)
(declare (xargs :guard t))
(if (consp x) (+ 1 (len (cdr x))) 0))")
(LENGTH
(LISTS STRINGS ACL2-BUILT-INS)
"Length of a string or proper list
Length is the function for determining the length of a sequence. In
ACL2, the argument is required to be either a [true-listp] or a
string.
For a similar function that is logically defined to be equal to zero
on any atom, including any string, see [len].
Length is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <length>
(defun length (x)
(declare (xargs :guard (if (true-listp x) t (stringp x))))
(if (stringp x)
(len (coerce x 'list))
(len x)))")
(LET
(BASICS ACL2-BUILT-INS)
"Binding of lexically scoped (local) variables
Introduction
Example
(let ((x (* x x))
(y (* 2 x)))
(list x y))
If the form above is executed in an environment in which x has the
value -2, then the result is '(4 -4).
Let expressions bind variables so that their ``local'' values, the
values they have when the ``body'' of the let is evaluated, are
possibly different than their ``global'' values, the values they
have in the context in which the let expression appears. In the let
expression above, the local variables bound by the let are x and y.
They are locally bound to the values delivered by the two forms (*
x x) and (* 2 x), respectively, that appear in the ``bindings'' of
the let. The body of the let is (list x y).
Suppose that the let expression above occurs in a context in which x
has the value -2. (The global value of y is irrelevant to this
example.) For example, one might imagine that the let form above
occurs as the body of some function, fn, with the formal parameter
x and we are evaluating (fn -2).
To evaluate the let above in a context in which x is -2, we first
evaluate the two forms specifying the local values of the
variables. Thus, (* x x) is evaluated and produces 4 (because x is
-2) and (* 2 x) is evaluated and produces -4 (because x is -2).
Then x and y are bound to these values and the body of the let is
evaluated. Thus, when the body, (list x y) is evaluated, x is 4 and
y is -4. Thus, the body produces '(4 -4).
Note that the binding of y, which is written after the binding of x
and which mentions x, nevertheless uses the global value of x, not
the new local value. That is, the local variables of the let are
bound ``in parallel'' rather than ``sequentially.'' In contrast, if
the example let* form:
(let* ((x (* x x))
(y (* 2 x)))
(list x y))
is evaluated when the global value of x is -2, then the result is '(4
8), because the local value of y is computed after x has been bound
to 4. [Let*] binds its local variables ``sequentially.''
General let forms
(let ((var1 term1) ... (varn termn)) body)
and
(let ((var1 term1) ... (varn termn))
(declare ...) ... (declare ...)
body)
where the vari are distinct variables, the termi are terms involving
only variables bound in the environment containing the let, and
body is a term involving only the vari plus the variables bound in
the environment containing the let. Each vari must be used in body
or else [declare]d ignored.
A let form is evaluated by first evaluating each of the termi,
obtaining for each a vali. Then, each vari is bound to the
corresponding vali and body is evaluated.
Actually, let forms are just abbreviations for certain uses of lambda
notation. In particular
(let ((var1 term1) ... (varn termn)) (declare ...) body)
is equivalent to
((lambda (var1 ... varn)
(declare ...)
body)
term1 ... termn).
[Let*] forms are used when it is desired to bind the vari
sequentially, i.e., when the local values of preceding varj are to
be used in the computation of the local value for vari.
General let* forms:
(let* ((var1 term1) ... (varn termn)) body)
and
(let* ((var1 term1) ... (varn termn))
(declare (ignore x1 ... xm))
body)
where the vari are variables (not necessarily distinct), the termi
are terms involving only variables bound in the environment
containing the [let*] and those varj such that j<i, and body is a
term involving only the vari plus the variables bound in the
environment containing the [let*]. Each vari must be used either in
some subsequent termj or in body, except that in the second form
above we make an exception when vari is among the xk, in which case
vari must not be thus used. Note that [let*] does not permit the
inclusion of any [declare] forms other than one as shown above. In
the second general form above, every xk must be among the vari, and
furthermore, xk may not equal vari and varj for distinct i, j.
The first [let*] above is equivalent to
(let ((var1 term1))
...
(let ((varn termn)) body)...)
Thus, the termi are evaluated successively and after each evaluation
the corresponding vali is bound to the value of termi. The second
[let*] is similarly expanded, except that each for each vari that
is among the (x1 ... xm), the form (declare (ignore vari)) is
inserted immediately after (vari termi).
Each (vari termi) pair in a let or [let*] form is called a
``binding'' of vari and the vari are called the ``local variables''
of the let or [let*]. The common use of let and [let*] is to save
the values of certain expressions (the termi) so that they may be
referenced several times in the body without suggesting their
recomputation.
Let is part of Common Lisp. See any Common Lisp documentation for
more information.")
(LET*
(BASICS ACL2-BUILT-INS)
"Binding of lexically scoped (local) variables
Examples
(let* ((x (* x x))
(y (* 2 x)))
(list x y))
(let* ((x (* x x))
(y (* 2 x))
(x (* x y))
(a (* x x)))
(declare (ignore a))
(list x y))
If the forms above are executed in an environment in which x has the
value -2, then the respective results are '(4 8) and '(32 8). See
[let] for a discussion of both [let] and let*, or read on for a
briefer discussion.
The difference between [let] and let* is that the former binds its
local variables in parallel while the latter binds them
sequentially. Thus, in let*, the term evaluated to produce the
local value of one of the locally bound variables is permitted to
reference any locally bound variable occurring earlier in the
binding list and the value so obtained is the newly computed local
value of that variable. See [let].
In ACL2 the only [declare] forms allowed for a let* form are ignore,
ignorable, and type. See [declare]. Moreover, no variable declared
ignored or ignorable may be bound more than once. A variable with a
type declaration may be bound more than once, in which case the
type declaration is treated by ACL2 as applying to each binding
occurrence of that variable. It seems unclear from the Common Lisp
spec whether the underlying Lisp implementation is expected to
apply such a declaration to more than one binding occurrence,
however, so performance in such cases may depend on the underlying
Lisp.
Let* is a Common Lisp macro. See any Common Lisp documentation for
more information.")
(LEXORDER
(<< ACL2-BUILT-INS)
"Total order on ACL2 objects
Lexorder is a non-strict total order, a ``less than or equal,'' on
ACL2 objects. Also see [alphorder], the restriction of lexorder to
atoms; the notion of ``non-strict total order'' is defined there.
Lexorder has a guard of t.
For lexorder, an [atom] and a [cons] are ordered so that the [atom]
comes first, and two [cons]es are ordered so that the one with the
recursively smaller [car] comes first, with the [cdr]s being
compared only if the [car]s are equal. Lexorder compares two atoms
by using [alphorder].
Function: <lexorder>
(defun lexorder (x y)
(declare (xargs :guard t))
(cond ((atom x)
(cond ((atom y) (alphorder x y)) (t t)))
((atom y) nil)
((equal (car x) (car y))
(lexorder (cdr x) (cdr y)))
(t (lexorder (car x) (car y)))))")
(LINEAR
(RULE-CLASSES)
"Make some arithmetic inequality rules
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Example:
(defthm length-member-leq-length If inequality reasoning begins to
(implies (and (eqlablep e) consider how (length (member a b))
(true-listp x)) compares to any other term, add to
(<= (length (member e x)) the set of known inequalities the fact
(length x))) that it is no larger than (length b),
:rule-classes :linear) provided (eqlablep a) and
(true-listp b) rewrite to t.
General Form:
(and ...
(implies (and ...hi...)
(implies (and ...hk...)
(and ...
(rel lhs rhs)
...)))
...)
We process the :[corollary] formula of one :linear rule class object
to create one or more :linear rules. The first step is to flatten
the [and] and [implies] structure of the formula, transforming it
into a conjunction of formulas, each of the form
(implies (and h1 ... hn) (rel lhs rhs))
where no hypothesis is a conjunction and rel is one of the inequality
relations [<], [<=], [=], [/=], [>], or [>=]. If necessary, the
hypothesis of such a conjunct may be vacuous. We create a :linear
rule for each such conjunct, if possible, and otherwise cause an
error. To create a :linear rule from a term (i.e., from a single
such conjunct), we apply the following sequence of transformations.
1. Remove [guard-holders] such as [prog2$] from the term to obtain
(implies hyp concl), where hyp is t in the case of an
unconditional rule.
2. If concl is (not (not concl2)), replace concl by concl2.
3. For the resulting concl, replace [=] and [/=] by [equal] and not
equal, respectively.
4. Finally, the resulting concl is processed (``linearized'') to attempt
to create a corresponding polynomial or disjunction of two
polynomials. This process includes the evaluation of ground
subexpressions, for example replacing (* '3 '4) by '12, and
employs techniques that include [type-set] reasoning.
Each rule has one or more ``trigger terms'' which may be specified by
the user using the :trigger-terms field of the rule class or which
may be defaulted to values chosen by the system. We discuss the
determination of trigger terms after discussing how linear rules
are used.
:Linear rules are used by an arithmetic decision procedure during
rewriting. See [linear-arithmetic] and see [non-linear-arithmetic].
Here we assume that the reader is familiar with the material
described in [linear-arithmetic].
Recall that we eliminate the unknowns of an inequality in term-order,
largest unknowns first. (See [term-order].) In order to facilitate
this strategy, we store the inequalities in ``linear pots''. For
purposes of the present discussion, let us say that an inequality
is ``about'' its largest unknown. Then, all of the inequalities
about a particular unknown are stored in the same linear pot, and
the pot is said to be ``labeled'' with that unknown. This storage
layout groups all of the inequalities which are potential
candidates for cancellation with each other into one place. It is
also key to the efficient operation of :linear rules.
If the arithmetic decision procedure has stabilized and not yielded a
contradiction, we scan through the list of linear pots examining
each label as we go. If the trigger term of some :linear rule can
be instantiated to match the label, we so instantiate that rule and
attempt to relieve the hypotheses with general-purpose rewriting.
If we are successful, we rewrite each of the two terms being
compared by the conclusion (which is an equality or inequality),
under the substitution produced by the rule's instantation. We then
add the resulting equality or inequality to our set of
inequalities. This may let cancellation continue.
Note: Problems may arise if you explicitly store a linear lemma under
a trigger term that, when instantiated, is not the largest unknown
in the instantiated concluding inequality. Suppose for example you
store the linear rule (<= (fn i j) (/ i (* j j))) under the trigger
term (fn i j). Then when the system ``needs'' an inequality about
(fn a b), (i.e., because (fn a b) is the label of some linear pot,
and hence the largest unknown in some inequality), it will appeal
to the rule and deduce (<= (fn a b) (/ a (* b b))). However, the
largest unknown in this inequality is (/ a (* b b)) and hence it
will be stored in a linear pot labeled with (/ a (* b b)). The
original, triggering inequality which is in a pot about (fn a b)
will therefore not be cancelled against the new one. It is
generally best to specify as a trigger term one of the ``maximal''
terms of the polynomial, as described below.
We now describe how the trigger terms are determined. Most of the
time, the trigger terms are not specified by the user and are
instead selected by the system. However, the user may specify the
terms by including an explicit :trigger-terms field in the rule
class, e.g.,
General Form of a Linear Rule Class:
(:LINEAR :COROLLARY formula
:TRIGGER-TERMS (term1 ... termk))
Each termi must be a term and must not be a variable, quoted
constant, lambda application, let-expression or if-expression. In
addition, each termi must be such that if all the variables in the
term are instantiated and then the hypotheses of the corollary
formula are relieved (possibly instantiating additional free
variables), then all the variables in the concluding inequality are
instantiated. We generate a linear rule for each conjuctive branch
through the corollary and store each rule under each of the
specified triggers. Thus, if the corollary formula contains several
conjuncts, the variable restrictions on the termi must hold for
each conjunct.
If :trigger-terms is omitted the system computes a set of trigger
terms. Each conjunct of the corollary formula may be given a unique
set of triggers depending on the variables that occur in the
conjunct and the addends that occur in the concluding inequality.
In particular, the trigger terms for a conjunct is the list of all
``maximal addends'' in the concluding inequality.
The ``addends'' of (+ x y) and (- x y) are the union of the addends
of x and y. The addends of (- x) and (* n x), where n is a rational
constant, is just {x}. The addends of an inequality are the union
of the addends of the left- and right-hand sides. The addends of
any other term, x, is {x}.
A term is maximal for a conjunct (implies hyps concl) of the
corollary if (a) the term is a non-variable, non-quote, non-lambda
application, non-[let] and non-[if] expression, (b) the term
contains enough variables so that when they are instantiated and
the hypotheses are relieved (which may bind some free variables;
see [free-variables]) then all the variables in concl are
instantiated, and (c) no other addend is always ``bigger'' than the
term, in the technical sense described below.
The technical notion referenced above depends on the notion of
fn-count, the number of function symbols in a term, and
pseudo-fn-count, which is essentially the number of function
symbols implicit in a constant (see [term-order], specifically the
discussion of ``pseudo-function application count'' at the end). We
say term1 is always bigger than term2 if all instances of term1
have a larger fn-count (actually lexicographic order of fn-count
and pseudo-fn-count) than the corresponding instances of term2.
This is equivalent to saying that the fn-count of term1 is larger
than that of term2 (by ``fn-count'' here we mean the lexicographic
order of fn-count and pseudo-fn-count) and the variable bag for
term2 is a subbag of that for term1. For example, (/ a (* b b)) is
always bigger than (fn a b) because the first has two function
applications and {a b} is a subbag of {a b b}, but (/ a (* b b)) is
not always bigger than (fn a x).
Subtopics
[Backchain-limit]
Limiting the effort expended on relieving hypotheses
[Bind-free]
To bind free variables of a rewrite, definition, or linear rule
[Case-split]
Like force but immediately splits the top-level goal on the
hypothesis
[Force]
Identity function used to force a hypothesis
[Linear-arithmetic]
A description of the linear arithmetic decision procedure
[Non-linear-arithmetic]
Non-linear Arithmetic
[Syntaxp]
Attach a heuristic filter on a rule")
(LINEAR-ARITHMETIC
(LINEAR)
"A description of the linear arithmetic decision procedure
We describe the procedure very roughly here. Fundamental to the
procedure is the notion of a linear polynomial inequality. A
``linear polynomial'' is a sum of terms, each of which is the
product of a rational constant and an ``unknown.'' The ``unknown''
is permitted to be 1 simply to allow a term in the sum to be
constant. Thus, an example linear polynomial is 3*x + 7*a + 2; here
x and a are the (interesting) unknowns. However, the unknowns need
not be variable symbols. For example, (length x) might be used as
an unknown in a linear polynomial. Thus, another linear polynomial
is 3*(length x) + 7*a. A ``linear polynomial inequality'' is an
inequality (either [<] or [<=]) relation between two linear
polynomials. Note that an equality may be considered as a pair of
inequalities; e.q., 3*x + 7*a + 2 = 0 is the same as the
conjunction of 3*x + 7*a + 2 <= 0 and 0 <= 3*x + 7*a + 2.
Certain linear polynomial inequalities can be combined by
cross-multiplication and addition to permit the deduction of a
third inequality with fewer unknowns. If this deduced inequality is
manifestly false, a contradiction has been deduced from the assumed
inequalities.
For example, suppose we have two assumptions
p1: 3*x + 7*a < 4
p2: 3 < 2*x
and we wish to prove that, given p1 and p2, a < 0. As suggested
above, we proceed by assuming the negation of our goal
p3: 0 <= a.
and looking for a contradiction.
Our first step will be to eliminate the variable x. To that end, we
cross-multiply based on the coefficients of x in the two
inequalities. By multiplying p1 by 2 and p2 by 3, and then adding
the respective sides, we deduce the intermediate result
p4: 6*x + 14*a + 9 < 8 + 6*x
which, after cancellation, is:
p4: 14*a + 1 < 0.
If we then cross-multiply and add p3 to p4, we get
p5: 1 <= 0,
a contradiction. Thus, we have proved that p1 and p2 imply the
negation of p3.
All of the unknowns of an inequality must be eliminated by
cancellation in order to produce a constant inequality. We can
choose to eliminate the unknowns in any order, but we eliminate
them in term-order, largest unknowns first. (See [term-order].)
That is, two polys are cancelled against each other only when they
have the same largest unknown. For instance, in the above example
we see that x is the largest unknown in each of p1 and p2, and a in
p3 and p4.
Now suppose that this procedure does not produce a contradiction but
instead yields a set of nontrivial inequalities. A contradiction
might still be deduced if we could add to the set some additional
inequalities allowing further cancellations. That is where :linear
lemmas come in. When the set of inequalities has stabilized under
cross-multiplication and addition and no contradiction is produced,
we search the database of :[linear] rules for rules about the
unknowns that are candidates for cancellation (i.e., are the
largest unknowns in their respective inequalities). See [linear]
for a description of how :[linear] rules are used.
See also [non-linear-arithmetic] for a description of an extension to
the linear-arithmetic procedure described here.")
(LIST
(LISTS ACL2-BUILT-INS)
"Build a list
List is the macro for building a list of objects. For example, (list
5 6 7) returns a list of length 3 whose elements are 5, 6, and 7
respectively. Also see [list*].
List is defined in Common Lisp. See any Common Lisp documentation for
more information.
Macro: <list>
(defmacro list (&rest args)
(list-macro args))
Function: <list-macro>
(defun list-macro (lst)
(declare (xargs :guard t))
(if (consp lst)
(cons 'cons
(cons (car lst)
(cons (list-macro (cdr lst)) nil)))
nil))")
(LIST*
(LISTS ACL2-BUILT-INS)
"Build a list
List* is the Common Lisp macro for building a list of objects from
given elements and a tail. For example, (list* 5 6 '(7 8 9)) equals
the list '(5 6 7 8 9). Also see [list].
List* is a Common Lisp function. See any Common Lisp documentation
for more information.
Macro: <list*>
(defmacro list* (&rest args)
(declare (xargs :guard (consp args)))
(list*-macro args))
Function: <list*-macro>
(defun list*-macro (lst)
(declare (xargs :guard (and (true-listp lst) (consp lst))))
(if (endp (cdr lst))
(car lst)
(cons 'cons
(cons (car lst)
(cons (list*-macro (cdr lst)) nil)))))")
(LISTP
(LISTS CONSES ACL2-BUILT-INS)
"Recognizer for (not necessarily proper) lists
(listp x) is true when x is either a [cons] pair or is nil.
Listp has no [guard], i.e., its [guard] is t.
Listp is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <listp>
(defun listp (x)
(declare (xargs :guard t))
(or (consp x) (equal x nil)))")
(LISTS
(PROGRAMMING)
"Lists of objects, the classic Lisp data structure.
Subtopics
[ACL2-number-listp]
Recognizer for a true list of numbers
[Add-to-set]
Add a symbol to a list
[Append]
[concatenate] zero or more lists
[Atom-listp]
Recognizer for a true list of [atom]s
[Boolean-listp]
Recognizer for a true list of booleans
[Butlast]
All but a final segment of a list
[Character-listp]
Recognizer for a true list of characters
[Concatenate]
Concatenate lists or strings together
[Count]
Count the number of occurrences of an item in a string or true-list
[Endp]
Recognizer for empty lists
[Eqlable-listp]
Recognizer for a true list of objects each suitable for [eql]
[Fix-true-list]
Coerce to a true list
[Good-atom-listp]
Recognizer for a true list of ``good'' [atom]s
[Improper-consp]
Recognizer for improper (non-null-terminated) non-empty lists
[Integer-listp]
Recognizer for a true list of integers
[Intersection$]
Elements of one list that are not elements of another
[Intersectp]
Test whether two lists intersect
[Keyword-value-listp]
Recognizer for true lists whose even-position elements are keywords
[Last]
The last [cons] (not element) of a list
[Len]
Length of a list
[Length]
Length of a string or proper list
[List]
Build a list
[List*]
Build a list
[Listp]
Recognizer for (not necessarily proper) lists
[Make-list]
Make a list of a given size
[Member]
Membership predicate
[Nat-listp]
Recognizer for a true list of natural numbers
[No-duplicatesp]
Check for duplicates in a list
[Nth]
The nth element (zero-based) of a list
[Nthcdr]
Final segment of a list
[Pairlis]
See [pairlis$]
[Pairlis$]
Zipper together two lists
[Position]
Position of an item in a string or a list
[Proper-consp]
Recognizer for proper (null-terminated) non-empty lists
[Rational-listp]
Recognizer for a true list of rational numbers
[Real-listp]
ACL2(r) recognizer for a true list of real numbers
[Remove]
Remove all occurrences
[Remove-duplicates]
Remove duplicates from a string or a list
[Remove1]
Remove first occurrences, testing using [eql]
[Revappend]
Concatentate the [reverse] of one list to another
[Reverse]
Reverse a list or string
[Search]
Search for a string or list in another string or list
[Set-difference$]
Elements of one list that are not elements of another
[Standard-char-listp]
Recognizer for a true list of standard characters
[String-listp]
Recognizer for a true list of strings
[Subseq]
Subsequence of a string or list
[Subsetp]
Test if every [member] of one list is a [member] of the other
[Substitute]
Substitute into a string or a list, using [eql] as test
[Symbol-listp]
Recognizer for a true list of symbols
[Take]
Initial segment (first n elements) of a list
[True-list-listp]
Recognizer for true (proper) lists of true lists
[True-listp]
Recognizer for proper (null-terminated) lists
[Union$]
Elements of one list that are not elements of another
[Update-nth]
Modify a list by putting the given value at the given position")
(LOCAL
(EVENTS)
"Hiding an event in an encapsulation or book
Examples:
(local (defthm hack1
(implies (and (acl2-numberp x)
(acl2-numberp y)
(equal (* x y) 1))
(equal y (/ x)))))
(local (defun double-naturals-induction (a b)
(cond ((and (integerp a) (integerp b) (< 0 a) (< 0 b))
(double-naturals-induction (1- a) (1- b)))
(t (list a b)))))
General Form:
(local ev)
where ev is an event form. If the current default [defun-mode] (see
[default-defun-mode]) is :[logic] and [ld-skip-proofsp] is nil or
t, then (local ev) is equivalent to ev. But if the current default
[defun-mode] is :[program] or if [ld-skip-proofsp] is
'[include-book], then (local ev) is a no-op. Thus, if such forms
are in the event list of an [encapsulate] event or in a book, they
are processed when the encapsulation or book is checked for
admissibility in :[logic] mode but are skipped when extending the
host [world]. Such [events] are thus considered ``local'' to the
verification of the encapsulation or book. The non-local [events]
are the ones ``exported'' by the encapsulation or book. See
[encapsulate] for a thorough discussion. Also see
[local-incompatibility] for a discussion of a commonly encountered
problem with such event hiding: you can't make an event local if
its presence is required to make sense of a non-local one.
Note that [events] that change the default [defun-mode], and in fact
any [events] that set the [ACL2-defaults-table], are disallowed
inside the scope of local. See [embedded-event-form].")
(LOCAL-INCOMPATIBILITY
(MISCELLANEOUS)
"When non-local [events] won't replay in isolation
Sometimes a ``[local] incompatibility'' is reported while attempting
to embed some [events], as in an [encapsulate] or [include-book].
This is generally due to the use of a locally defined name in a
non-local event or the failure to make a witnessing definition
[local].
[Local] incompatibilities may be detected while trying to execute the
strictly non-local [events] of an embedding. For example,
[encapsulate] operates by first executing all the [events] ([local]
and non-local) with [ld-skip-proofsp] nil, to confirm that they are
all admissible. Then it attempts merely to assume the non-local
ones to create the desired theory, by executing the [events] with
[ld-skip-proofsp] set to '[include-book]. Similarly, [include-book]
assumes the non-local ones, with the understanding that a
previously successful [certify-book] has performed the admissiblity
check.
How can a sequence of [events] admitted with [ld-skip-proofsp] nil
fail when [ld-skip-proofsp] is '[include-book]? The key observation
is that in the latter case only the non-local [events] are
processed. The [local] ones are skipped and so the non-local ones
must not depend upon them.
Two typical mistakes are suggested by the detection of a [local]
incompatibility: (1) a locally defined function or macro was used
in a non-[local] event (and, in the case of [encapsulate], was not
included among the [signature]s) and (2) the witnessing definition
of a function that was included among the [signature]s of an
[encapsulate] was not made [local].
An example of mistake (1) would be to include among your
[encapsulate]d [events] both (local (defun fn ...)) and (defthm
lemma (implies (fn ...) ...)). Observe that fn is defined locally
but a formula involving fn is defined non-locally. In this case,
either the [defthm] should be made [local] or the [defun] should be
made non-local.
An example of mistake (2) would be to include (fn (x) t) among your
[signature]s and then to write (defun fn (x) ...) in your [events],
instead of (local (defun fn ...)).
One subtle aspect of [encapsulate] is that if you constrain any
member of a mutually recursive clique you must define the entire
clique locally and then you must constrain those members of it you
want axiomatized non-locally.
Errors due to [local] incompatibility should never occur in the
assumption of a fully certified book. Certification ensures against
it. Therefore, if [include-book] reports an incompatibility, we
assert that earlier in the processing of the [include-book] a
warning was printed advising you that some book was uncertified. If
this is not the case --- if [include-book] reports an
incompatibility and there has been no prior warning about lack of
certification --- please report it to us.
When a [local] incompatibility is detected, we roll-back to the
[world] in which we started the [encapsulate] or [include-book].
That is, we discard the intermediate [world] created by trying to
process the [events] skipping proofs. This is clean, but we realize
it is very frustrating because the entire sequence of [events] must
be processed from scratch. Assuming that the embedded [events]
were, once upon a time, processed as top-level [command]s (after
all, at some point you managed to create this sequence of
[command]s so that the [local] and non-local ones together could
survive a pass in which proofs were done), it stands to reason that
we could define a predicate that would determine then, before you
attempted to embed them, if [local] incompatibilities exist. We
hope to do that, eventually.
We conclude with a subtle example of [local] incompatibility. The
problem is that in order for foo-type-prescription to be admitted
using the specified :typed-term (foo x), the conclusion (my-natp
(foo x)) depends on my-natp being a [compound-recognizer]. This is
fine on the first pass of the [encapsulate], during which lemma
my-natp-cr is admitted. But my-natp-cr is skipped on the second
pass because it is marked [local], and this causes
foo-type-prescription to fail on the second pass.
(defun my-natp (x)
(declare (xargs :guard t))
(and (integerp x)
(<= 0 x)))
(defun foo (x)
(nfix x))
(encapsulate
()
(local (defthm my-natp-cr
(equal (my-natp x)
(and (integerp x)
(<= 0 x)))
:rule-classes :compound-recognizer))
(defthm foo-type-prescription
(my-natp (foo x))
:hints ((\"Goal\" :in-theory (enable foo)))
:rule-classes ((:type-prescription :typed-term (foo x)))))")
(LOGAND
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical `and' of zero or more integers
When integers are viewed in their two's complement representation,
logand returns their bitwise logical `and'. In ACL2 logand is a
macro that expands into calls of the binary function binary-logand,
except that (logand) expands to -1 and (logand x) expands to x.
The [guard] for binary-logand requires its arguments to be integers.
Logand is defined in Common Lisp. See any Common Lisp documentation
for more information.
Macro: <logand>
(defmacro logand (&rest args)
(cond ((null args) -1)
((null (cdr args)) (car args))
(t (xxxjoin 'binary-logand args))))
Function: <binary-logand>
(defun binary-logand (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(cond ((zip i) 0)
((zip j) 0)
((eql i -1) j)
((eql j -1) i)
(t (let ((x (* 2 (logand (floor i 2) (floor j 2)))))
(+ x
(cond ((evenp i) 0)
((evenp j) 0)
(t 1)))))))")
(LOGANDC1
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical `and' of two ints, complementing the first
When integers are viewed in their two's complement representation,
logandc1 returns the bitwise logical `and' of the second with the
bitwise logical `not' of the first.
The [guard] for logandc1 requires its arguments to be integers.
Logandc1 is defined in Common Lisp. See any Common Lisp
documentation for more information.
Function: <logandc1>
(defun logandc1 (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(logand (lognot i) j))")
(LOGANDC2
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical `and' of two ints, complementing the second
When integers are viewed in their two's complement representation,
logandc2 returns the bitwise logical `and' of the first with the
bitwise logical `not' of the second.
The [guard] for logandc2 requires its arguments to be integers.
Logandc2 is defined in Common Lisp. See any Common Lisp
documentation for more information.
Function: <logandc2>
(defun logandc2 (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(logand i (lognot j)))")
(LOGBITP
(NUMBERS ACL2-BUILT-INS)
"The ith bit of an integer
For a nonnegative integer i and an integer j, (logbitp i j) is a
Boolean, which is t if and only if the value of the ith bit is 1 in
the two's complement representation of j.
(Logbitp i j) has a [guard] that i is a nonnegative integer and j is
an integer.
Logbitp is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <logbitp>
(defun logbitp (i j)
(declare (xargs :guard (and (integerp j)
(integerp i)
(>= i 0))))
(oddp (floor (ifix j) (expt 2 (nfix i)))))")
(LOGCOUNT
(NUMBERS ACL2-BUILT-INS)
"Number of ``on'' bits in a two's complement number
(Logcount x) is the number of ``on'' bits in the two's complement
representation of x.
(Logcount x) has a [guard] of (integerp x).
Logcount is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <logcount>
(defun
logcount (x)
(declare (xargs :guard (integerp x)))
(cond ((zip x) 0)
((< x 0) (logcount (lognot x)))
((evenp x)
(logcount (nonnegative-integer-quotient x 2)))
(t (1+ (logcount (nonnegative-integer-quotient x 2))))))")
(LOGEQV
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical equivalence of zero or more integers
When integers are viewed in their two's complement representation,
logeqv returns their bitwise logical equivalence. In ACL2 logeqv is
a macro that expands into calls of the binary function
binary-logeqv, except that (logeqv) expands to -1 and (logeqv x)
expands to x.
The [guard] for binary-logeqv requires its arguments to be integers.
Logeqv is defined in Common Lisp. See any Common Lisp documentation
for more information.
Macro: <logeqv>
(defmacro logeqv (&rest args)
(cond ((null args) -1)
((null (cdr args)) (car args))
(t (xxxjoin 'binary-logeqv args))))
Function: <binary-logeqv>
(defun binary-logeqv (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(logand (logorc1 i j) (logorc1 j i)))")
(LOGIC
(DEFUN-MODE)
"To set the default [defun-mode] to :logic
Example:
ACL2 p!>:logic
ACL2 !>
Typing the keyword :logic sets the default [defun-mode] to :logic.
Functions defined in :logic mode are logically defined. See
[defun-mode].
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
See [defun-mode] for a discussion of the [defun-mode]s available and
what their effects on the logic are. See [default-defun-mode] for a
discussion of how the default [defun-mode] is used. This event is
equivalent to (table acl2-defaults-table :defun-mode :logic), and
hence is [local] to any [books] and [encapsulate] [events] in which
it occurs. See [ACL2-defaults-table].
Recall that the top-level form :logic is equivalent to (logic); see
[keyword-commands]. Thus, to change the default [defun-mode] to
:logic in a book, use (logic), which is an embedded event form,
rather than :logic, which is not a legal form for [books]. See
[embedded-event-form].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Background knowledge in ACL2 logic for theorem prover tutorial
You might think that in order to use the theorem prover you have to
know the mathematical logic supported by ACL2. But you need to know
a lot less about it than you might think.
Technically, a theorem is a formula that can be derived from axioms
by using rules of inference. Thus, to do a proof you have to know
(a) the syntax of formulas, (b) the axioms, and (c) the rules of
inference. Traditionally, these things are spelled out in
excruciating detail in treatments of mathematical logic -- and for
good reason.
The whole point of proving theorems is that it is a way to determine
that a formula is ``always true'' (under some model of the axioms).
By ``always true'' we actually mean what logicians mean when they
say the formula is valid: true in the model, for all possible
values of the variables. Here by ``model of the axioms'' we mean an
understanding of the meaning of the various function symbols so
that the axioms are true for all values of the variables. If the
variables in your conjecture can take on an infinite number of
values, proof is often the only way to determine that a conjecture
is ``always true.'' So if proof is being used to determine that a
questionable formula is always true the proof must be carried out
flawlessly. Thus, the (a) syntax, (b) axioms, and (c) rules of
inference must be described precisely and followed to the letter.
But formal mathematical logic was invented to explain how people
reason. To the extent that logic mimics human reasoning, proofs can
be seen as just extremely carefully crafted arguments. Given that
ACL2 is responsible for following the rules ``to the letter,'' your
main job is ``explain'' the big leaps.
To use the theorem prover you must understand (a) the syntax, because
you must be able to write formulas flawlessly. But you don't have
to know (b) the axioms and (c) the rules of inference at nearly the
same level of precision, as long as you understand the basic
structure and language of proofs.
Below is part of a proof of a certain theorem. You ought to be able
to understand the following. Since what we describe is a proof of
one case of the formula, we hope that you're convinced that the
formula holds for that case.
Read this and follow the links to confirm that you understand what
happens. Be sure to then use your browser's Back Button to return
to this page and continue.
An Annotated Proof of
(implies (true-listp z)
(equal (rev (rev z)) z))
``We will prove that reversing the reverse of a true-listp yields the
original list. The formula stating this is above. We will prove it
by [induction] on the list structure of z.
The [base case] of the induction is:
(implies (endp z)
(implies (true-listp z)
(equal (rev (rev z)) z))).
This formula is equivalent, by [propositional calculus], to
(implies (and (endp z)
(true-listp z))
(equal (rev (rev z)) z))
[Rewriting] with the definition of endp produces:
(implies (and (not (consp z))
(true-listp z))
(equal (rev (rev z)) z))
[Rewriting repeatedly] starting with the definition of true-listp
produces:
(implies (and (not (consp z))
(equal z nil))
(equal (rev (rev z)) z))
Then using the second hypothesis, just [substituting equals for
equals], we get
(implies (and (not (consp z))
(equal z nil))
(equal (rev (rev nil)) nil))
Since the conclusion involves no variables, we can [evaluate] it,
getting
(implies (and (not (consp z))
(equal z nil))
T)
But this is an [instance] of the [tautology] (implies p T). Thus, the
base case is proved.''
Now it is time for a little quiz. There are just three questions.
Q1: The case above was the Base Case of an inductive proof of
(implies (true-listp z)
(equal (rev (rev z)) z))
in which we did induction on the structure of the linear list z. What
is the Induction Step? That is, what do you have to prove besides
the Base Case to complete this inductive proof?
Below are four commonly given answers; choose one. Then look [here]
to find out if you're right.
Induction Step -- Choice (i):
(implies (not (endp z))
(implies (true-listp z)
(equal (rev (rev z)) z)))
Induction Step -- Choice (ii):
(implies (true-listp (cdr z))
(equal (rev (rev (cdr z))) (cdr z)))
Induction Step -- Choice (iii):
(implies (and (not (endp z))
(equal (rev (rev (cdr x))) (cdr x)))
(implies (true-listp z)
(equal (rev (rev z)) z)))
Induction Step -- Choice (iv):
(implies (and (not (endp z))
(implies (true-listp (cdr z))
(equal (rev (rev (cdr z))) (cdr z))))
(implies (true-listp z)
(equal (rev (rev z)) z)))
Q2: To prove the Induction Step we must prove one or more of the
goals below.
Which combinations are sufficient to imply the Induction Step? Decide
what is required and then look [here] to find out if you're right.
To help you, the Induction Step is of the form:
Induction Step:
(implies (and c
(implies p' q'))
(implies p q))
and beside each candidate subgoal we show its structure in those
terms.
Subgoal (i):
(implies (and (not (endp z)) ; (implies (and c
(true-listp z)) ; p)
(true-listp (cdr z))) ; p')
Subgoal (ii):
(implies (and (not (endp z)) ; (implies (and c
(true-listp z) ; p
(equal (rev (rev (cdr z))) (cdr z))) ; q')
(equal (rev (rev z)) z)) ; q)
Subgoal (iii):
(implies (and (not (endp z)) ; (implies (and c
(equal (rev (rev (cdr z))) (cdr z))) ; q')
(equal (rev (rev z)) z)) ; q)
Subgoal (iv):
(implies (and (not (endp z)) ; (implies (and c
(true-listp (cdr z)) ; p'
(equal (rev (rev (cdr z))) (cdr z))) ; q')
(equal (rev (rev z)) z)) ; q)
Q3: Suppose you know the theorem
Theorem:
(implies (p (f x))
(equal (g (h x))
x))
and you wish to rewrite the target (g (h a)) to a in
Goal Conjecture:
(implies (and (q (f a))
(r a))
(s (g (h a))))
What must you prove to relieve the hypothesis of Theorem?
After you've thought about it, look [here] for our answer.
End of the Quiz
If this page made sense, you're ready to read the introduction to the
theorem prover.
If you are reading this as part of the tutorial introduction to the
theorem prover, use your browser's Back Button now to return to
[introduction-to-the-theorem-prover].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-BASE-CASE
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"A brief explanation of base cases
According to the sentence, the conjecture being proved is ``reversing
the reverse of a true-listp yields the original list.'' The formula
corresponding to this conjecture is:
(implies (true-listp z)
(equal (rev (rev z)) z)).
We're also told that this is an inductive proof. Evidently we're
doing an induction on the structure of the list z. Then the Base
Case is the formula:
(implies (endp z)
(implies (true-listp z)
(equal (rev (rev z)) z))).
Now use your browser's Back Button to return to the example proof in
[logic-knowledge-taken-for-granted].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-EQUALS-FOR-EQUALS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Substitution of equals for equals
Anytime you have an equality hypothesis relating two terms, e.g.,
(equal lhs rhs)
it is legal to substitute one for the other anyplace else in the
formula. Doing so does not change the truthvalue of the formula.
You can use a negated equality this way provided it appears in the
conclusion. For example, it is ok to transform
(implies (true-listp x)
(not (equal x 23)))
to
(implies (true-listp 23)
(not (equal x 23)))
by substitutions of equals for equals. That is because, by
[propositional calculus], we could rearrange the formulas into
their contrapositive forms:
(implies (equal x 23)
(not (true-listp x)))
and
(implies (equal x 23)
(not (true-listp 23)))
and see the equality as a hypothesis and the substitution of 23 for x
as sensible.
Sometimes people speak loosely and say ``substitution of equals for
equals'' when they really mean ``substitutions of equivalents for
equivalents.'' Equality, as tested by EQUAL, is only one example of
an equivalence relation. The next most common is propositional
equivalence, as tested by IFF. You can use propositional
equivalence hypotheses to substitute one side for the other
provided the target term occurs in a propositional place, as
discussed at the bottom of [propositional calculus].
Now use your browser's Back Button to return to the example proof in
[logic-knowledge-taken-for-granted].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-EVALUATION
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Evaluation during proofs
Any time you are proving a formula and see a subterm in the formula
that contains no variables, you can just evaluate the subterm.
This is familiar from algebra: It is not uncommon to rearrange a
polynominal to collect all the constants and then add them up:
(3x + 2 + 7y + 2)
=
(3x + 7y + (2 + 2))
=
(3x + 7y + 4).
That last step is just evaluation.
It happens often in ACL2 proofs because theorems involve constants
and defined functions and when those constants ``drift into the
maw'' of a function, the function call can be eliminated and
replaced by a new constant. ACL2 does this automatically; you don't
have to tell it. In fact, there are a few occasions where you might
prefer it not evaluate and those are the ones you have to look out
for! They'll be obvious when they happen because you'll see a
mysterious constant crop up in the proof.
Evaluation is legal because it is just the repeated use of
unconditional rewriting to replace definitions by their
instantiated bodies until no function calls remain.
Now use your browser's Back Button to return to the example proof in
[logic-knowledge-taken-for-granted].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INDUCTIVE-PROOF
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"A brief explanation of induction
We start by showing classical induction on the natural numbers in an
ACL2 setting before turning to a more general treatment of
induction.
Classical Induction on Natural Numbers: Induction is familiar in the
arithmetic setting. Let (p n) denote some formula involving the
variable n (and perhaps some other variables which we don't
exhibit). Then to prove (p n), for all n, by classical induction on
the construction of the natural numbers, prove each of the
following:
Base Case:
(implies (zp n) (p n))
Induction Step:
(implies (and (not (zp n))
(p (- n 1)))
(p n))
The Base Case establishes that p holds for 0. In fact, because of the
definition of [zp] [{ICON}], it establishes that (p n) holds when n
is 0 and it holds when n is not a natural number.
The Induction Step establishes that if n is a natural number other
than 0, and if p holds for n-1, then p holds for n. The hypothesis
(p (- n 1)) above is called the induction hypothesis.
Note that if the Base Case and Induction Step are valid, then we know
(p n), for all n. You can convince yourself of this by picking any
object and asking ``how do I know p holds for this object?'' For
example, (p -7), (p 'abc), and (p 0) are all established by the
Base Case. What about (p 1)? That follows from (p 0), given the
Induction Step. Why? To prove (p 1) using the Induction Step, you
have to establish (not (zp 1)), which is true, and (p (- 1 1)),
which is (p 0), which is true by the Base Case. So (p 1) is true.
Similar reasoning proves (p 2) from from (p 1), etc. Clearly, for
every natural number other than 0 we could reason like this to show
that p holds. Since the Base Case handled all the objects that are
not natural numbers, and handled 0, we know (p n), for all n.
There is a duality between recursion and induction that ACL2
exploits. The fact that the Base and Induction steps above are
sufficient to prove p for all objects is related to the fact that
the following recursion defines a total, terminating function:
(defun nat-recursion (n)
(if (zp n)
n
(nat-recursion (- n 1))))
When this function is admitted we have to prove that if (zp n) does
not hold, then (- n 1) is smaller, in some sense, than n. This
sense of ``smaller'' is determined by some measure of the
arguments. That measure must return an ordinal ([ordinals]
[{ICON}]), but the most common measures return natural numbers,
which are among the ordinals. Furthermore, that measure should
insure that the terms in the recursive calls are smaller than the
formals, i.e., the measure of (- n 1) must be smaller than the
measure of n, when the recursive branches are taken. This sense of
``smaller'' must be well-founded: it must be impossible to have an
infinitely descending chain of smaller things. This is true of the
less-than relation on the ordinals (see [o<] [{ICON}]).
Well-foundedness means that eventually any recursion must ``bottom
out'' because things can't keep getting smaller forever.
The recursion in nat-recursion suggests the induction shown above:
the Base Case is defined by the if branch that does not lead to a
recursive call. The Induction Step is defined by the other branch.
The induction hypothesis is defined by what we recur on, i.e., (- n
1). The theorems proved when nat-recursion is introduced justify
the classical induction scheme noted above.
Every recursively defined ACL2 function suggests a legal induction
and vice versa.
Furthermore, every call of a recursively defined function on distinct
variable symbols also suggests a legal induction: just take the
induction suggested by the function's recursive definition after
renaming the formal parameters to be the variables in the call.
For example, it should be clear that (nat-recursion a) suggests a
Base Case defined by (zp a), and induction step defined by (not (zp
a)) and an induction hypothesis about (- a 1).
Note that the term (fact n) suggests the same classical induction on
natural numbers shown above, where fact is defined as follows (even
though we've used the formal parameter k below).
(defun fact (k)
(if (zp k)
1
(* k (fact (- k 1)))))
The induction suggested by a term like (fact n) is insensitive to the
name of the formal parameter used in the defun.
The induction suggested by a function or term is insensitive to the
value returned by the function or term.
It doesn't matter what the function returns in its ``base case''
(e.g., 1 in fact) or what the function ``does'' to its recursive
call (e.g., multiply by k in the defun of fact).
All that matters is (i) how the if structure breaks down the cases on
k, (ii) which branches lead to recursion, and (iii) what arguments
are passed to the recursive calls. Those things determine (i) the
case analysis of the induction scheme, (ii) which cases are Base
Cases and which are Induction Steps, and (iii) what the induction
hypotheses are.
For a selection of common inductions schemes in ACL2 (e.g., on the
structure of natural numbers, lists, and trees and on several
variables at once, multiple base cases, multiple induction
hypotheses, multiple induction steps, etc.) [check this link].
Every legal ACL2 induction corresponds to an admissible recursive
function and vice versa. Similarly, every legal ACL2 induction
corresponds to a call of a recursively defined function on distinct
variables.
ACL2 chooses which induction to do by looking at the terms that occur
in the conjecture. For many elementary theorems, ACL2 chooses the
right induction by itself.
You may occasionally need to tell it what induction to do. You do
that by showing it a term that suggests the induction you want.
We'll explain how you communicate this to ACL2 later. If you
understand how recursive functions suggest inductions, then you
know what you need to know to use ACL2.
The main point of this discussion of induction is familiarize you
with the basic terms: Base Case (of which there may be several),
Induction Step (of which there may be several), Induction
Hypothesis (of which there may be several in each Induction Step),
measure and well-founded relation justifying an induction, and the
induction suggested by a term or recursive function definition.
Furthermore, every Induction Hypothesis is always an [instance] of
the conjecture being proved: each induction hypothesis is obtained
from the conjecture being proved by applying a substitution
replacing variables by terms.
If you are reviewing the material taken for granted about logic while
working your way through the introduction to the theorem prover,
please use your browser's Back Button to return to the example
proof in [logic-knowledge-taken-for-granted].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"A brief explanation of substitution instances
Let p and q be terms or formulas (there is no difference in ACL2).
Then we say p is an instance or substitution instance of q if and
only if p can be obtained from q by uniformly replacing the
variables of q by terms. Sometimes we call p the target and q the
pattern because by choosing appropriate replacements we can make
the pattern match many different targets.
For example, the following target is an instance of the given
pattern:
target: (APP (APP (REV A) (REV B)) (REV C))
pattern: (APP (APP x y ) (REV z))
The replacement or substitution used in this match of the pattern to
the target is:
variable in pattern replacement term
x (REV A)
y (REV B)
z C
Such substitutions are usually written this way in ACL2:
((x (REV A))
(y (REV B))
(z C)).
Please use your browser's Back Button to return to the page that
mentioned ``instance.''")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"A brief explanation of propositional calculus
It is impossible in this short introduction to teach you
propositional calculus if you don't already know it!
A typical use of propositional calculus is to observe that
(implies (endp z)
(implies (true-listp z)
(equal (rev (rev z)) z)))
is equivalent to:
(implies (and (endp z)
(true-listp z))
(equal (rev (rev z)) z))
If this is surprising and you know propositional calculus, then the
problem might be our notation. We're exploiting the tautology
(p ---> (q ---> r)) <---> ((p & q) ---> r)
where ---> and <---> are meant to be the traditional arrows denoting
logical implication and logical equivalence.
If you don't know propositional calculus, we'll say just a few things
to help ease your journey.
A propositional formula, in ACL2, is any formula written entirely in
terms of variable symbols, T, NIL, and the propositional functions
AND, OR, NOT, IMPLIES, and IFF. The ``tautology'' above in
traditional notation is this propositional formula in ACL2:
(IFF (IMPLIES P (IMPLIES Q R))
(IMPLIES (AND P Q) R)).
If you have a formula like
(implies hyp
concl)
then we say that formula is an implication, that hyp is the
hypothesis, and that concl is the conclusion. If the hypothesis is
an and expression, as in
(implies (and hyp1
hyp2
...)
concl)
then we call hyp1 is the first hypothesis, hyp2 is the second
hypothesis, etc.
If a term is of the form
(and term1 term2 ...)
we say it is a conjunction and that term1 is the first conjunct,
term2 is the second conjunct, etc. We treat an or-term analogously
but call it a disjunction and its arguments are disjuncts.
A tautology is any propositional formula that can be proved by
testing it under all combinations of Boolean assignments to its
variables. We give an example of such a truth-table proof below,
but hasten to add that ACL2 does not generally use truth tables to
recognize tautologies. It primarily uses IF-normalization and BDDs
to recognize tautologies, which can be seen as a mix of symbolic
manipulation and case analysis.
Many tautologies have names, but ACL2 doesn't refer to them by name
because it derives them from first principles. We list a few here
because we sometimes use the names in our documentation; more
importantly, you should look at these formulas and convince
yourself that they're always true for all Boolean values of the
variables:
Double Negation:
(iff (not (not p)) p)
DeMorgan:
(iff (not (and p q))
(or (not p) (not q)))
Distributivity:
(iff (and p (or q r))
(or (and p q)
(and p r)))
Promotion:
(iff (implies p (implies q r))
(implies (and p q) r))
Implicative Disjunction:
(iff (implies p q)
(or (not p) q))
Contrapositive:
(iff (implies p q)
(implies (not q) (not p)))
Generalized Contrapositive:
(iff (implies (and p r) q)
(implies (and p (not q)) (not r)))
There are, of course, many others, even with these same names! For
example, there is a dual version of DeMorgan showing how not
distributes over or, a dual version of Distributivity for or over
and, etc.
Dealing with propositional calculus will not generally be a problem
for you because it is decidable and ACL2 has procedures that decide
propositional formulas. However, propositional calculus can lead to
exponential explosion and can thus explain why ACL2 has ``gone out
to lunch.'' In addition, sometimes if you are curious as to why
ACL2 is working on a certain subgoal the reason can be traced back
to propositional calculus.
The most common example of this is that to prove a formula of the
form
(implies (implies p1 q1)
(implies p2 q2))
propositional calculus will convert it to
(and (implies (and p2 (not p1)) q2)
(implies (and p2 q1) q2))
Many users are surprised that the first conjunct above does not have
q1 as a hypothesis. If you ever stare at an ACL2 goal and say to
yourself ``A hypothesis is missing!'' the chances are that
propositional calculus is ``to blame.'' In particular, if you are
trying to prove that (implies p1 q1) implies something, you must
deal with the case that (implies p1 q1) is true because p1 is
false. Think about it.
Now we illustrate the truth table method for deciding tautologies,
even though that is not what ACL2 generally uses. Consider the
formula called Promotion above:
(IFF (IMPLIES P (IMPLIES Q R))
(IMPLIES (AND P Q) R))
The formula above is a tautology. It contains three variables, P, Q,
and R, and so there are 8 combinations of Boolean assignments to
them. If we let
formula1: (IMPLIES P (IMPLIES Q R))
formula2: (IMPLIES (AND P Q) R)
then we wish to test the formula (IFF formula1 formula2):
P Q R formula1 formula2 (IFF formula1 formula2)
---------
T T T T T T
T T NIL NIL NIL T
T NIL T T T T
T NIL NIL T T T
NIL T T T T T
NIL T NIL T T T
NIL NIL T T T T
NIL NIL NIL T T T
So we see that the formula always returns T and is thus a tautology.
Recall that in the original example at the top of this page we were
trying to prove the formula
(implies (endp z)
(implies (true-listp z)
(equal (rev (rev z)) z)))
This formula is an [instance] of
(implies p (implies q r)).
The substitution required by the match is
sigma:
((p (endp z))
(q (true-listp z))
(r (equal (rev (rev z)) z)))
Since we know the tautology:
(iff (implies p (implies q r))
(implies (and p q) r)).
is always true no matter what Boolean values p, q, and r have, then
we know this instance of it (obtained by applying the substitution
sigma above) is always true:
(iff (implies (endp z) formula1'
(implies (true-listp z)
(equal (rev (rev z)) z)))
(implies (and (endp z) formula2'
(true-listp z))
(equal (rev (rev z)) z))).
Thus, if we're trying to prove formula1' it is permitted to try to to
prove formula2' instead, because they return the same truthvalue.
This sketch of propositional reasoning in ACL2 is a little suspect
because we didn't address the possibility that the substitution
might replace the propositional variables by non-propositional
terms. But the tautology was verified only on Boolean values for
those variables. This actually works out because in ACL2 all
propositional testing is done against nil and any non-nil value,
including t, is as good as another. However, the tautology allows
us to replace one formula by the other only in contexts in which we
just care about propositional truth, i.e., whether the formula is
nil or not. When we prove a formula in ACL2 we are really
establishing that it never returns nil, i.e., no matter what the
values of the variables, the value of the formula is non-nil.
A very simple example of this is with Double Negation.
(iff (not (not p)) p)
is a tautology. This means that if we were trying to prove
(implies (not (not p)) ...)
we could transform it to
(implies p ...).
But if we were trying to prove:
(equal (not (not p)) p)
we could not prove it by using Double Negation! The formula above
claims that (not (not p)) and p have identical values. They do not!
For example, (not (not 3)) is t, not 3. However, (not (not 3)) and
t are propositionally equivalent (i.e., satisfy iff) because one is
as good as the other in a test. That is what Double Negation says.
As long as you only use propositional formulas in propositional
places this aspect of ACL2 should not affect you.
Now please use your browser's Back Button to return to the example
proof in [logic-knowledge-taken-for-granted].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q1-ANSWER
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"The inductive step of the rev-rev proof -- Answer to Question 1
The correct answer to Question 1 in
[logic-knowledge-taken-for-granted] is Choice (iv).
The Induction Step of the inductive proof of
(implies (true-listp z)
(equal (rev (rev z)) z))
for an induction on the linear list z is:
Induction Step:
(implies (and (not (endp z))
(implies (true-listp (cdr z))
(equal (rev (rev (cdr z))) (cdr z))))
(implies (true-listp z)
(equal (rev (rev z)) z)))
The second hypothesis above is the the induction hypothesis. The
conclusion above is the formula we are trying to prove. Each
induction hypothesis is always an [instance] of the formula being
proved, i.e., it is obtained from the formula being proved by
uniformly replacing the variables in the formula with terms. Notice
how the induction hypothesis above is the same as the induction
conclusion, except that all the zs have been replaced by (cdr z).
If you thought the right answer was
Induction Step -- Choice (i):
(implies (not (endp z))
(implies (true-listp z)
(equal (rev (rev z)) z)))
then perhaps you didn't understand that we're doing an inductive
proof. Certainly if you prove the Base Case already discussed and
you prove Choice (i) above, then you will have proved the goal
conjecture, but you would have done it by simple case analysis:
prove it when (endp z) and prove it when (not (endp z)). While
logically valid, you probably can't prove Choice (i) directly
because you have no induction hypothesis to work with.
If you thought the right answer was:
Induction Step -- Choice (ii):
(implies (true-listp (cdr z))
(equal (rev (rev (cdr z))) (cdr z)))
then perhaps you misunderstand the difference between the Induction
Step and the Induction Hypothesis. The Induction Step is the
``other half'' of the main proof, balancing the Base Case. The
Induction Hypothesis is just a hypothesis you get to use during the
Induction Step. The question Q1 asked what is the Induction Step.
If you thought the right answer was:
Induction Step -- Choice (iii):
(implies (and (not (endp z))
(equal (rev (rev (cdr x))) (cdr x))) ; ``induction hyp''
(implies (true-listp z)
(equal (rev (rev z)) z)))
then you are making the most common mistake newcomers make to
induction. You are giving yourself an ``induction hypothesis'' that
is not an instance of the conjecture you're proving. This alleged
induction hypothesis says that (rev (rev (cdr x))) is (cdr x),
whereas the correct induction hypothesis says those two terms are
equal if (true-listp (cdr x)). This alleged induction hypothesis is
a stronger claim than we're trying to prove. It turns out that by
making this mistake you can ``prove'' conjectures that are not
always true! Remember: the induction hypothesis is always an
instance of the conjecture you're proving, not just some piece of
it. Of course, ACL2 ``knows'' this and will never make this
mistake. But we remind you of it because there may be times when
you intuit a different hypothesis and don't understand why ACL2
doesn't use it.
If this doesn't make sense, perhaps you should read about [induction]
again.
When you understand why Choice (iv) is the correct answer, use your
browser's Back Button to return to
[logic-knowledge-taken-for-granted] and go to question Q2.")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q2-ANSWER
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"The inductive step of the rev-rev proof -- Answer to Question 2
The correct answer to Question 2 in
[logic-knowledge-taken-for-granted] is Subgoal (i) plus any one of
the other other three. For your reference, the four choices were:
Subgoal (i):
(implies (and (not (endp z))
(true-listp z))
(true-listp (cdr z)))
Subgoal (ii):
(implies (and (not (endp z))
(true-listp z)
(equal (rev (rev (cdr z))) (cdr z)))
(equal (rev (rev z)) z))
Subgoal (iii):
(implies (and (not (endp z))
(equal (rev (rev (cdr z))) (cdr z)))
(equal (rev (rev z)) z))
Subgoal (iv):
(implies (and (not (endp z))
(true-listp (cdr z))
(equal (rev (rev (cdr z))) (cdr z)))
(equal (rev (rev z)) z))
In particular, it is wrong to think the Induction Step of the proof
of
(implies (true-listp z)
(equal (rev (rev z)) z))
can be established by proving just Subgoal (ii), Subgoal (iii),
Subgoal (iv), or combinations of those three. You must also prove
Subgoal (i) or something like it!
The Inductive Step for the conjecture above is
Induction Step:
(implies (and (not (endp z))
; Induction Hypothesis:
(implies (true-listp (cdr z))
(equal (rev (rev (cdr z))) (cdr z))))
; Induction Conclusion:
(implies (true-listp z)
(equal (rev (rev z)) z)))
Note that the Inductive Hypothesis is an implication:
(implies (true-listp (cdr z))
(equal (rev (rev (cdr z))) (cdr z)))
This hypothesis can be true two different ways. The ``normal'' way --
the way everybody remembers -- is that (true-listp (cdr z)) is true
and thus (equal (rev (rev (cdr z))) (cdr z)) is true. But the way
many people forget is that (true-listp (cdr z)) is false. You must
prove the Induction Step even in this ``forgetable'' case.
In this case, the Induction Step simplifies to
Induction Step:
(implies (and (not (endp z))
(not (true-listp (cdr z))))
(implies (true-listp z)
(equal (rev (rev z)) z)))
By Promotion (see the list of tautologies in our discussion of
[propositional calculus]) this is
Induction Step':
(implies (and (not (endp z))
(not (true-listp (cdr z)))
(true-listp z))
(equal (rev (rev z)) z))
Using the Contrapositive and rearranging the order of the hypotheses
(see [propositional calculus] again), this is
Induction Step'':
(implies (and (not (endp z))
(true-listp z)
(not (equal (rev (rev z)) z)))
(true-listp (cdr z)))
Notice that Subgoal (i) implies Induction Step'':
Subgoal (i):
(implies (and (not (endp z))
(truelistp z))
(truelistp (cdr z)))
Every inductive proof of an implication raises a case like this. If
we denote the conjecture (implies p q) as p ---> q, then the
Induction Step will look like this:
( c & (p' ---> q'))
--->
(p ---> q)
where c is the test that determines the inductive step, (e.g., (not
(endp z))) and p' and q' are inductive instances of p and q.
Promotion produces
( c & p & (p' ---> q'))
--->
q
It is then very common to prove that p implies p',
(i):
(c & p) ---> p'
and then prove that q' implies q,
(ii):
(c & p & q') ---> q
These correspond exactly to our choices Subgoal (i) and Subgoal (ii).
It is sometimes helpful to remember this diagram:
(c & (p' ---> q')
^ |
| |
| v
--> (p ---> q )
When you understand why Subgoals (i) and (ii) are sufficient, use
your browser's Back Button to return to
[logic-knowledge-taken-for-granted] and go to question Q3.")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q3-ANSWER
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"The inductive step of the rev-rev proof -- Answer to Question 2
The correct answer to Question 3 in
[logic-knowledge-taken-for-granted] is that you need to prove
Subgoal to Relieve Hyp 1:
(implies (and (q (f a))
(r a))
(p (f a)))
in order to use
Theorem:
(implies (p (f x))
(equal (g (h x))
x))
to rewrite the target (g (h a)) to a in
Goal Conjecture:
(implies (and (q (f a))
(r a))
(s (g (h a))))
If you don't see why, re-read the discussion of [rewriting] again.
Forgetting about the need to relieve hypotheses is a common mistake
in informal proofs. ACL2 won't forget to relieve them. But if you
forget about the need to do it, you may be confused when ACL2
doesn't see the ``proof'' you see!
Now use your browser's Back Button to return to the end of quiz in
[logic-knowledge-taken-for-granted].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-REWRITING
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"A brief explanation of rewriting from the logical perspective
First we give two examples of rewriting. Then we give a rather
detailed description. We recommend you read the description, even
if you understand the two examples, just so that you learn our
terminology.
Example 1: Suppose your goal conjecture is:
Goal Conjecture:
(implies (and (endp z)
(true-listp z))
(equal (rev (rev z)) z))
Then you can use the following theorem (actually the definitional
axiom introduced by the defun of endp):
Definitional Axiom: endp
(equal (endp x)
(not (consp x))).
to rewrite the Goal Conjecture to
Rewritten Goal Conjecture:
(implies (and (not (consp z))
(true-listp z))
(equal (rev (rev z)) z))
Note that in this example, rewriting replaced the call of endp by its
body after instantiating its body with the actuals from the call.
This is sometimes just called expanding the definition of endp.
(The notions of formal, body, call, and actuals are discussed in
[programming-knowledge-taken-for-granted].)
Expanding a definition is an example of unconditional rewriting. All
definitions in ACL2 are just bare equalities relating a call of the
function on its formals to its body. Any time you use an equality
theorem, whether a definitional equality or something more general
like
(equal (append (append x y) z)
(append x (append y z)))
to replace an instance of one side by the corresponding instance of
the other in a goal conjecture, we call that unconditional
rewriting with the equality.
Example 2: Suppose your goal conjecture is:
Goal Conjecture:
(implies (and (subsetp a b)
(true-listp b)
(member e a))
(< (len (rm e b)) (len b))).
This conjecture may be read ``if a is a subset of the true-listp b
and e is a member of a, then the result of removing e from b has a
shorter length than b.''
You can use the following theorem:
Theorem:
(implies (member u v)
(equal (len (rm u v))
(- (len v) 1)))
to rewrite the Goal Conjecture to
Rewritten Goal Conjecture:
(implies (and (subsetp a b)
(true-listp b)
(member e a))
(< (- (len b) 1) (len b))).
To do this you must know that the following subgoal is provable:
Subgoal to Relieve Hyp 1:
(implies (and (subsetp a b)
(true-listp b)
(member e a))
(member e b)).
This is an example of conditional rewriting. In order to use the
Theorem we had to establish that its hypotheses are satisfied. That
is called relieving the hypotheses and was done by proving the
Subgoal to Relieve Hyp 1. Conditional rewriting is the most
commonly used proof technique in ACL2.
Unconditional rewriting is just a special case, where there are no
hypotheses to relieve.
Expanding a definition is just another special case, where there are
no hypotheses to relieve and the pattern is easy to match because
it is a call of a function on distinct variables.
This page discusses rewriting from the logical perspective. It is
important that you are familiar with the notions of a pattern term
being an [instance] of a target term. We often say the pattern
matches the target. These notions involve a corresponding
substitution of terms for variables. All these notions are
discussed in the link for ``[instance]'' above and we recommend you
read it before continuing. Then use your browser's Back Button to
come back here.
You should also be aware of the terms introduced in our discussion of
[propositional calculus].
Rewriting is a fundamental rule of inference in our system. The rule
allows you to use a theorem, i.e., an axiom, lemma, or definition,
to replace one term by another in the goal conjecture you're trying
to prove.
Suppose you have a theorem that is of the form (or can be put into
the form):
Theorem:
(implies (and hyp1
...
hypk)
(equal pattern
replacement))
From the logical perspective we don't care how the theorem was
actually written when it was proved. It might have no hypotheses
(in which case the hypi could just be t), or it could have been
written in a different but equivalent propositional style, (or (not
hyp1) ...), or the equality could have been written the other way
around, (equal replacement pattern). Such syntactic details don't
matter. Just take a theorem and use propositional calculus to
rearrange it equivalently into this form for the purposes of this
one rewrite step.
Suppose pattern is an instance of some target term, target that
occurs in your goal conjecture. Let the corresponding substitution
be sigma. If sigma does not contain a binding for every variable
that occurs in Theorem, then extend sigma to sigma' by adding one
binding for each such variable. (This is necessary only if pattern
does not contain every variable in Theorem.)
Let replacement' be the result of instantiating replacement with
sigma'. Let hypi' be the result of instantiating hypi with sigma'.
Then the Rewrite Rule of Inference tells us it is permitted to
replace that occurrence of target in the goal by replacement' -- if
you can prove each hypi' in this context. We make this last
condition clear in a moment.
The justification for this is that Theorem is true for all values of
the variables. Hence, it is true for the values specified by
sigma'. If the hypi' are true, then the target is really equal to
replacement'. But it is always permitted to replace something by
something it's equal to.
Rewriting thus involves several steps:
(1) Finding a target and a theorem to use to rewrite it to some more
desirable replacement.
(2) Instantiating pattern in the (rearranged) theorem to match
target.
(3) Extending sigma to sigma' to bind all the variables in Theorem.
(4) Establishing that the sigma' instances of each of the hypi hold.
This is called relieving the hypotheses of the theorem and is
discussed in greater detail below.
(5) Replacing the occurrence of target in the goal conjecture by the
sigma' instance of replacement, provided all the hypotheses are
relieved.
Step (4) above, relieving the hypotheses, requires first identifying
the ``context'' of the target in the goal conjecture. To do this,
use propositional calculus to rearrange the goal conjecture so the
occurrence of target is in the conclusion and let context be the
hypothesis.
Rearranged Conjecture:
(implies context
(... target ...))
To relieve the hypotheses you must then prove each of the following
subgoals:
Subgoal to Relieve Hyp i:
(implies context hypi').
It is important to note that this description of rewriting with
Theorem describes the process from a strictly logical perspective.
The syntax of the theorem and the goal don't matter. You're free to
use propositional calculus to rearrange them to put them into the
appropriate forms to fit the descriptions given. Clearly, if you
have a candidate Theorem in the ``wrong'' form and but it can be
rearranged with propositional calculus into the ``right'' form,
then that rearranged theorem is also a Theorem and can be used as
described. But in the actual implementation of ACL2, the syntactic
form of a proved Theorem affects how it is used by rewriting. If a
proved theorem takes the form of an implication concluding with an
equality, ACL2 treats the left-hand side of the equality as pattern
and the right-hand side as replacement, unless you tell it
otherwise. We'll discuss this later.
Furthermore, being from the logical perspective this discussion of
rewriting does not address (a) how you extend simga to sigma' --
any extension will do provided it allows you to relieve the
hypotheses. The ACL2 theorem prover uses certain heuristics which
we'll discuss later, including methods by which you can guide the
system in the selection.
Crucially, it does not discuss whether it is a good idea to do a
particular rewrite! For example, the definitional equality:
(equal (len x)
(if (endp x)
0
(+ 1 (len (cdr x)))))
may be used repeatedly, endlessly, to replace (len a) by an ever
growing sequence of terms:
(len a)
=
(if (endp a)
0
(+ 1 (len (cdr a))))
=
(if (endp a)
0
(+ 1 (if (endp (cdr a))
0
(+ 1 (len (cdr (cdr a)))))))
= ...
The ACL2 implmentation of rewriting uses certain heuristics and the
you can guide the system in its choices. We'll discuss this later.
Now use your browser's Back Button to return to the example proof in
[logic-knowledge-taken-for-granted].")
(LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-REWRITING-REPEATEDLY
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Further information on expanding definitions via rewriting
We assume you've read about ``[instances]'' and picked up our basic
terminology including the ideas of matching a pattern term to a
target term, obtaining a substitution and how to instantiate a term
with a substitution. We use these notions below without further
citation.
In addition, we assume you've read about ``[rewriting]'' where we
introduced the idea of treating a theorem (axiom, definition, or
lemma) as a conditional rewrite rule and replaced one term by an
equivalent one provided we can relieve the hypotheses.
Suppose you're trying to prove formula1 and you transform it to
formula2 by rewriting. What happened?
formula1:
(implies (and (not (consp z))
(true-listp z))
(equal (rev (rev z)) z))
formula2:
(implies (and (not (consp z))
(equal z nil))
(equal (rev (rev z)) z))
Evidently we replaced (true-listp z) by (equal z nil). But how did
that happen? What really happened was the sequential application of
several unconditional rewrites and the use of replacement of equals
by equals.
The definition of true-listp is:
(defun true-listp (x)
(if (consp x)
(true-listp (cdr x))
(equal x nil))).
By rewriting once with the definition of true-listp, we transform
formula1 to:
formula1':
(implies (and (not (consp z))
(if (consp z)
(true-listp (cdr z))
(equal z nil)))
(equal (rev (rev z)) z)).
Note how the call of true-listp has been replaced by the entire body
of true-listp.
Next, note that the first hypothesis above is that (consp z) is
false. That is, (not (consp z)) is the same as (equal (consp z)
nil). Thus, replacement of equals by equals means we can transform
formula1' to
formula1'':
(implies (and (not (consp z))
(if nil
(true-listp (cdr z))
(equal z nil)))
(equal (rev (rev z)) z)).
(We will explore replacement of equals by equals later.)
Furthermore, we know the basic axiom about if:
Axiom if-nil:
(if nil x y) = y.
Rewriting with this particular axiom, using (if nil x y) as the
pattern and y as the replacement, will transform formula1'' to
formula2:
(implies (and (not (consp z))
(equal z nil))
(equal (rev (rev z)) z)).
Often when we say we derived one formula from another by
``expansion'' and or by ``rewriting'' we take many rewrite steps,
as here. We typically use hypotheses of the formula without noting
``replacement of equals by equals'' as when we replaced (consp z)
by nil, and we typically omit to mention the use of basic axioms
like if-nil above.
Now use your browser's Back Button to return to the example proof in
[logic-knowledge-taken-for-granted].")
(LOGICAL-NAME
(EVENTS WORLD)
"A name created by a logical event
Examples:
assoc
caddr
+
\"ACL2-USER\"
\"arith\"
\"project/task-1/arith.lisp\"
:here
A logical name is either a name introduced by some event, such as
[defun], [defthm], or [include-book], or else is the keyword :here,
which refers to the most recent such event. See [events]. Every
logical name is either a symbol or a string. For the syntactic
rules on names, see [name]. The symbols name functions, macros,
constants, axioms, theorems, labels, and [theories]. The strings
name packages or [books]. We permit the keyword symbol :here to be
used as a logical name denoting the most recently completed event.
The logical name introduced by an [include-book] is the full book
name string for the book (see [full-book-name]). Thus, under the
appropriate setting for the current book directory (see [cbd]) the
event (include-book \"arith\") may introduce the logical name
\"/usr/home/smith/project/task-1/arith.lisp\" .
Under a different [cbd] setting, it may introduce a different logical
name, perhaps
\"/local/src/acl2/library/arith.lisp\" .
It is possible that identical [include-book] events forms in a
session introduce two different logical names because of the
current book directory.
A logical name that is a string is either a package name or a book
name. If it is not a package name, we support various conventions
to interpret it as a book name. If it does not end with the string
\".lisp\" we extend it appropriately. Then, we search for any book
name that has the given logical name as a terminal substring.
Suppose (include-book \"arith\") is the only [include-book] so far
and that \"/usr/home/smith/project/task-1/arith.lisp\" is the source
file it processed. Then \"arith\", \"arith.lisp\" and
\"task-1/arith.lisp\" are all logical names identifying that
[include-book] event (unless they are package names). Now suppose a
second (include-book \"arith\") is executed and processes
\"/local/src/acl2/library/arith.lisp\". Then \"arith\" is no longer a
logical name, because it is ambiguous. However, \"task-1/arith\" is a
logical name for the first [include-book] and \"library/arith\" is a
logical name for the second. Indeed, the first can be named by
\"1/arith\" and the second by \"y/arith\".
Logical names are used primarily in the theory manipulation
functions, e.g., [universal-theory] and [current-theory] with which
you may obtain some standard [theories] as of some point in the
historical past. The reference points are the introductions of
logical names, i.e., the past is determined by the [events] it
contains. One might ask, ``Why not discuss the past with the much
more flexible language of [command] descriptors?'' (See
[command-descriptor].) The reason is that inside of such [events]
as [encapsulate] or macro [command]s that expand to [progn]s of
[events], [command] descriptors provide too coarse a grain.
When logical names are used as referents in theory expressions used
in [books], one must consider the possibility that the defining
event within the book in question becomes redundant by the
definition of the name prior to the assumption of the book. See
[redundant-events].")
(LOGIOR
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical inclusive or of zero or more integers
When integers are viewed in their two's complement representation,
logior returns their bitwise logical inclusive or. In ACL2 logior
is a macro that expands into calls of the binary function
binary-logior, except that (logior) expands to 0 and (logior x)
expands to x.
The [guard] for binary-logior requires its arguments to be integers.
Logior is defined in Common Lisp. See any Common Lisp documentation
for more information.
Macro: <logior>
(defmacro logior (&rest args)
(cond ((null args) 0)
((null (cdr args)) (car args))
(t (xxxjoin 'binary-logior args))))
Function: <binary-logior>
(defun binary-logior (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(lognot (logand (lognot i) (lognot j))))")
(LOGNAND
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical `nand' of two integers
When integers are viewed in their two's complement representation,
lognand returns their bitwise logical `nand'.
The [guard] for lognand requires its arguments to be integers.
Lognand is defined in Common Lisp. See any Common Lisp
documentation for more information.
Function: <lognand>
(defun lognand (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(lognot (logand i j)))")
(LOGNOR
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical `nor' of two integers
When integers are viewed in their two's complement representation,
lognor returns the bitwise logical `nor' of the first with the
second.
The [guard] for lognor requires its arguments to be integers. Lognor
is defined in Common Lisp. See any Common Lisp documentation for
more information.
Function: <lognor>
(defun lognor (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(lognot (logior i j)))")
(LOGNOT
(NUMBERS ACL2-BUILT-INS)
"Bitwise not of a two's complement number
(lognot i) is the two's complement bitwise `not' of the integer i.
Lognot is actually defined by coercing its argument to an integer
(see [ifix]), negating the result, and then subtracting 1.
The [guard] for lognot requires its argument to be an integer.
Lognot is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <lognot>
(defun lognot (i)
(declare (xargs :guard (integerp i)))
(+ (- (ifix i)) -1))")
(LOGORC1
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical inclusive or of two ints, complementing the first
When integers are viewed in their two's complement representation,
logorc1 returns the bitwise logical inclusive or of the second with
the bitwise logical `not' of the first.
The [guard] for logorc1 requires its arguments to be integers.
Logorc1 is defined in Common Lisp. See any Common Lisp
documentation for more information.
Function: <logorc1>
(defun logorc1 (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(logior (lognot i) j))")
(LOGORC2
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical inclusive or of two ints, complementing the second
When integers are viewed in their two's complement representation,
logorc2 returns the bitwise logical inclusive or of the first with
the bitwise logical `not' of the second.
The [guard] for logorc2 requires its arguments to be integers.
Logorc2 is defined in Common Lisp. See any Common Lisp
documentation for more information.
Function: <logorc2>
(defun logorc2 (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(logior i (lognot j)))")
(LOGTEST
(NUMBERS ACL2-BUILT-INS)
"Test if two integers share a `1' bit
When integers x and y are viewed in their two's complement
representation, (logtest x y) is true if and only if there is some
position for which both x and y have a `1' bit in that position.
The [guard] for logtest requires its arguments to be integers.
Logtest is defined in Common Lisp. See any Common Lisp
documentation for more information.
Function: <logtest>
(defun logtest (x y)
(declare (xargs :guard (and (integerp x) (integerp y))))
(not (zerop (logand x y))))")
(LOGXOR
(NUMBERS ACL2-BUILT-INS)
"Bitwise logical exclusive or of zero or more integers
When integers are viewed in their two's complement representation,
logxor returns their bitwise logical exclusive or. In ACL2 logxor
is a macro that expands into calls of the binary function
binary-logxor, except that (logxor) expands to 0 and (logxor x)
expands to x.
The [guard] for binary-logxor requires its arguments to be integers.
Logxor is defined in Common Lisp. See any Common Lisp documentation
for more information.
Macro: <logxor>
(defmacro logxor (&rest args)
(cond ((null args) 0)
((null (cdr args)) (car args))
(t (xxxjoin 'binary-logxor args))))
Function: <binary-logxor>
(defun binary-logxor (i j)
(declare (xargs :guard (and (integerp i) (integerp j))))
(lognot (logeqv i j)))")
(LOOP-STOPPER
(REWRITE)
"Limit application of permutative rewrite rules
See [rule-classes] for a discussion of the syntax of the
:loop-stopper field of :[rewrite] rule-classes. Here we describe
how that field is used, and also how that field is created when the
user does not explicitly supply it.
For example, the built-in :[rewrite] rule commutativity-of-+,
(implies (and (acl2-numberp x)
(acl2-numberp y))
(equal (+ x y) (+ y x))),
creates a rewrite rule with a loop-stopper of ((x y binary-+)). This
means, very roughly, that the term corresponding to y must be
``smaller'' than the term corresponding to x in order for this rule
to apply. However, the presence of [binary-+] in the list means
that certain functions that are ``invisible'' with respect to
[binary-+] (by default, [unary--] is the only such function) are
more or less ignored when making this ``smaller'' test. We are much
more precise below.
Our explanation of loop-stopping is in four parts. First we discuss
ACL2's notion of ``term order.'' Next, we bring in the notion of
``invisibility'', and use it together with term order to define
orderings on terms that are used in the loop-stopping algorithm.
Third, we describe that algorithm. These topics all assume that we
have in hand the :loop-stopper field of a given rewrite rule; the
fourth and final topic describes how that field is calculated when
it is not supplied by the user.
ACL2 must sometimes decide which of two terms is syntactically
simpler. It uses a total ordering on terms, called the ``term
order.'' Under this ordering constants such as '(a b c) are simpler
than terms containing variables such as x and (+ 1 x). Terms
containing variables are ordered according to how many occurrences
of variables there are. Thus x and (+ 1 x) are both simpler than
(cons x x) and (+ x y). If variable counts do not decide the order,
then the number of function applications are tried. Thus (cons x x)
is simpler than (+ x (+ 1 y)) because the latter has one more
function application. Finally, if the number of function
applications do not decide the order, a lexicographic ordering on
Lisp objects is used. See [term-order] for details.
When the loop-stopping algorithm is controlling the use of
permutative :[rewrite] rules it allows term1 to be moved leftward
over term2 only if term1 is smaller, in a suitable sense. Note: The
sense used in loop-stopping is not the above explained term order
but a more complicated ordering described below. The use of a total
ordering stops rules like commutativity from looping indefinitely
because it allows (+ b a) to be permuted to (+ a b) but not vice
versa, assuming a is smaller than b in the ordering. Given a set of
permutative rules that allows arbitrary permutations of the tips of
a tree of function calls, this will normalize the tree so that the
smallest argument is leftmost and the arguments ascend in the order
toward the right. Thus, for example, if the same argument appears
twice in the tree, as x does in the [binary-+] tree denoted by the
term (+ a x b x), then when the allowed permutations are done, all
occurrences of the duplicated argument in the tree will be
adjacent, e.g., the tree above will be normalized to (+ a b x x).
Suppose the loop-stopping algorithm used term order, as noted above,
and consider the [binary-+] tree denoted by (+ x y (- x)). The
arguments here are in ascending term order already. Thus, no
permutative rules are applied. But because we are inside a
+-expression it is very convenient if x and (- x) could be given
virtually the same position in the ordering so that y is not
allowed to separate them. This would allow such rules as (+ i (- i)
j) = j to be applied. In support of this, the ordering used in the
control of permutative rules allows certain unary functions, e.g.,
the unary minus function above, to be ``invisible'' with respect to
certain ``surrounding'' functions, e.g., [+] function above.
Briefly, a unary function symbol fn1 is invisible with respect to a
function symbol fn2 if fn2 belongs to the value of fn1 in
[invisible-fns-table]; also see [set-invisible-fns-table], which
explains its format and how it can be set by the user. Roughly
speaking, ``invisible'' function symbols are ignored for the
purposes of the term-order test.
Consider the example above, (+ x y (- x)). The translated version of
this term is (binary-+ x (binary-+ y (unary-- x))). The initial
[invisible-fns-table] makes [unary--] invisible with repect to
[binary-+]. The commutativity rule for [binary-+] will attempt to
swap y and (unary-- x) and the loop-stopping algorithm is called to
approve or disapprove. If term order is used, the swap will be
disapproved. But term order is not used. While the loop-stopping
algorithm is permuting arguments inside a [binary-+] expression,
[unary--] is invisible. Thus, insted of comparing y with (unary--
x), the loop-stopping algorithm compares y with x, approving the
swap because x comes before y.
Here is a more precise specification of the total order used for
loop-stopping with respect to a list, fns, of functions that are to
be considered invisible. Let x and y be distinct terms; we specify
when ``x is smaller than y with respect to fns.'' If x is the
application of a unary function symbol that belongs to fns, replace
x by its argument. Repeat this process until the result is not the
application of such a function; let us call the result x-guts.
Similarly obtain y-guts from y. Now if x-guts is the same term as
y-guts, then x is smaller than y in this order iff x is smaller
than y in the standard term order. On the other hand, if x-guts is
different than y-guts, then x is smaller than y in this order iff
x-guts is smaller than y-guts in the standard term order.
Now we may describe the loop-stopping algorithm. Consider a rewrite
rule with conclusion (equiv lhs rhs) that applies to a term x in a
given context; see [rewrite]. Suppose that this rewrite rule has a
loop-stopper field (technically, the :heuristic-info field) of ((x1
y1 . fns-1) ... (xn yn . fns-n)). (Note that this field can be
observed by using the command :[pr] with the name of the rule; see
[pr].) We describe when rewriting is permitted. The simplest case
is when the loop-stopper list is nil (i.e., n is 0); in that case,
rewriting is permitted. Otherwise, for each i from 1 to n let xi'
be the actual term corresponding to the variable xi when lhs is
matched against the term to be rewritten, and similarly correspond
yi' with y. If xi' and yi' are the same term for all i, then
rewriting is not permitted. Otherwise, let k be the least i such
that xi' and yi' are distinct. Let fns be the list of all functions
that are invisible with respect to every function in fns-k, if
fns-k is non-empty; otherwise, let fns be nil. Then rewriting is
permitted if and only if yi' is smaller than xi' with respect to
fns, in the sense defined in the preceding paragraph.
It remains only to describe how the loop-stopper field is calculated
for a rewrite rule when this field is not supplied by the user. (On
the other hand, to see how the user may specify the :loop-stopper,
see [rule-classes].) Suppose the conclusion of the rule is of the
form (equiv lhs rhs). First of all, if rhs is not an instance of
the left hand side by a substitution whose range is a list of
distinct variables, then the loop-stopper field is nil. Otherwise,
consider all pairs (u . v) from this substitution with the property
that the first occurrence of v appears in front of the first
occurrence of u in the print representation of rhs. For each such u
and v, form a list fns of all functions fn in lhs with the property
that u or v (or both) appears as a top-level argument of a subterm
of lhs with function symbol fn. Then the loop-stopper for this
rewrite rule is a list of all lists (u v . fns).
Subtopics
[Add-invisible-fns]
Make some unary functions invisible to the [loop-stopper] algorithm
[Invisible-fns-table]
Functions that are invisible to the [loop-stopper] algorithm
[Remove-invisible-fns]
Make some unary functions no longer invisible
[Set-invisible-fns-table]
Set the invisible functions table")
(LOWER-CASE-P
(CHARACTERS ACL2-BUILT-INS)
"Recognizer for lower case characters
(Lower-case-p x) is true if and only if x is a lower case character,
i.e., a member of the list #\\A, #\\B, ..., #\\Z.
The [guard] for lower-case-p requires its argument to be a standard
character (see [standard-char-p]).
Lower-case-p is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <lower-case-p>
(defun lower-case-p (x)
(declare (xargs :guard (and (characterp x)
(standard-char-p x))))
(and (member x
'(#\\a #\\b #\\c #\\d #\\e #\\f #\\g
#\\h #\\i #\\j #\\k #\\l #\\m #\\n #\\o #\\p #\\q
#\\r #\\s #\\t #\\u #\\v #\\w #\\x #\\y #\\z))
t))")
(LP
(LD)
"The Common Lisp entry to ACL2
To enter the ACL2 [command] loop from Common Lisp, call the Common
Lisp program lp (which stands for ``loop,'' as in ``read-eval-print
loop'' or ``[command] loop.'') The ACL2 [command] loop is actually
coded in ACL2 as the function [ld] (which stands for ``load''). The
[command] loop is just what you get by loading from the standard
object input channel, [*standard-oi*]. Calling [ld] directly from
Common Lisp is possible but fragile because hard lisp errors or
aborts throw you out of [ld] and back to the top-level of Common
Lisp. Lp calls [ld] in such a way as to prevent this and is thus
the standard way to get into the ACL2 [command] loop. Also see
[ACL2-customization] for information on the loading of an
initialization file.
All of the visible functionality of lp is in fact provided by [ld],
which is written in ACL2 itself. Therefore, you should see [ld] for
detailed [documentation] of the ACL2 [command] loop. We sketch it
below, for novice users.
Every expression typed to the ACL2 top-level must be an ACL2
expression.
Any ACL2 expression may be submitted for evaluation. Well-formedness
is checked. Some well-formed expressions cannot be evaluated
because they involve (at some level) undefined constrained
functions (see [encapsulate]). In addition, ACL2 does not allow
``global variables'' in expressions to be evaluated. Thus, (car '(a
b c)) is legal and evaluates to A, but (car x) is not, because
there is no ``global context'' or binding environment that gives
meaning to the variable symbol x.
There is an exception to the global variable rule outlined above:
single-threaded objects (see [stobj]) may be used as global
variables in top-level expressions. The most commonly used such
object is the ACL2 ``current state,'' which is the value of the
variable symbol [state]. This variable may occur in the top-level
form to be evaluated, but must be passed only to ACL2 functions
``expecting'' state as described in the documentation for [state]
and for [stobj]s in general. If the form returns a new [state]
object as one of its values, then that is considered the new
``current'' [state] for the evaluation of the subsequent form. See
[state].
ACL2 provides some support for the functionality usually provided by
global variables in a read-eval-print loop, namely the saving of
the result of a computation for subsequent re-use in another
expression. See [assign] and see [@].
If the form read is a single keyword, e.g., :[pe] or :[ubt], then
special procedures are followed. See [keyword-commands].
The [command] loop keeps track of the [command]s you have typed and
allows you to review them, display them, and roll the logical
[state] back to that created by any [command]. See [history].
ACL2 makes the convention that if a top-level form returns three
values, the last of which is an ACL2 [state], then the first is
treated as a flag that means ``an error occurred,'' the second is
the value to be printed if no error occurred, and the third is (of
course) the new [state]. When ``an error occurs'' no value is
printed. Thus, if you execute a top-level form that happens to
return three such values, only the second will be printed (and that
will only happen if the first is nil!). See [ld] for details.
Subtopics
[Q]
Quit ACL2 (type :q) --- reenter with ([lp])")
(MACRO-ALIASES-TABLE
(MACROS)
"A [table] used to associate function names with macro names
Example:
(table macro-aliases-table 'append 'binary-append)
This example associates the function symbol [binary-append] with the
macro name [append]. As a result, the name [append] may be used as
a runic designator (see [theories]) by the various theory
functions. Thus, for example, it will be legal to write
(in-theory (disable append))
as an abbreviation for
(in-theory (disable binary-append))
which in turn really abbreviates
(in-theory (set-difference-theories (current-theory :here)
'(binary-append)))
General Form:
(table macro-aliases-table 'macro-name 'function-name)
or very generally
(table macro-aliases-table macro-name-form function-name-form)
where macro-name-form and function-name-form evaluate, respectively,
to a macro name and a symbol in the current ACL2 [world]. See
[table] for a general discussion of tables and the table event used
to manipulate tables.
Note that function-name-form (above) does not need to evaluate to a
function symbol, but only to a symbol. As a result, one can
introduce the alias before defining a recursive function, as
follows.
(table macro-aliases-table 'mac 'fn)
(defun fn (x)
(if (consp x)
(mac (cdr x))
x))
Although this is obviously contrived example, this flexibility can be
useful to macro writers; see for example the definition of ACL2
system macro [defun-inline].
The [table] [macro-aliases-table] is an alist that associates macro
symbols with function symbols, so that macro names may be used as
runic designators (see [theories]). For a convenient way to add
entries to this [table], see [add-macro-alias]. To remove entries
from the [table] with ease, see [remove-macro-alias].
This [table] is used by the theory functions; see [theories]. For
example, in order that (disable append) be interpreted as (disable
binary-append), it is necessary that the example form above has
been executed. In fact, this [table] does indeed associate many of
the macros provided by the ACL2 system, including [append], with
function symbols. Loosely speaking, it only does so when the macro
is ``essentially the same thing as'' a corresponding function; for
example, (append x y) and (binary-append x y) represent the same
term, for any expressions x and y.")
(MACRO-ARGS
(MACROS)
"The formals list of a macro definition
Examples:
(x y z)
(x y z &optional max (base '10 basep))
(x y &rest rst)
(x y &key max base)
(&whole sexpr x y)
The ``lambda-list'' of a macro definition may include simple formal
parameter names as well as appropriate uses of the following
lambda-list keywords from CLTL (pp. 60 and 145), respecting the
order shown:
&whole,
&optional,
&rest,
&body,
&key, and
&allow-other-keys.
ACL2 does not support &aux and &environment. In addition, we make the
following restrictions:
(1) initialization forms in &optional and &key specifiers must be
quoted values;
(2) &allow-other-keys may only be used once, as the last specifier;
and
(3) destructuring is not allowed.
You are encouraged to experiment with the macro facility. One way to
do so is to define a macro that does nothing but return the
quotation of its arguments, e.g.,
(defmacro demo (x y &optional opt &key key1 key2)
(list 'quote (list x y opt key1 key2)))
You may then execute the macro on some sample forms, e.g.,
term value
(demo 1 2) (1 2 NIL NIL NIL)
(demo 1 2 3) (1 2 3 NIL NIL)
(demo 1 2 :key1 3) error: non-even key/value arglist
(because :key1 is used as opt)
(demo 1 2 3 :key2 5) (1 2 3 NIL 5)
In particular, Common Lisp specifies that if you use both &rest and
&key, then both will be bound using the same list of arguments. The
following example should serve to illustrate how this works.
ACL2 !>(defmacro foo (&rest args &key k1 k2 k3)
(list 'quote (list args k1 k2 k3)))
Summary
Form: ( DEFMACRO FOO ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO
ACL2 !>(foo :k1 3 :k2 4 :k3 5)
((:K1 3 :K2 4 :K3 5) 3 4 5)
ACL2 !>(foo :k1 3 :k2 4)
((:K1 3 :K2 4) 3 4 NIL)
ACL2 !>(foo :k1 3 :bad-key 7)
ACL2 Error in macro expansion: Illegal key/value args (:BAD-KEY 7)
in macro expansion of (FOO :K1 3 :BAD-KEY 7). The argument list for
FOO is
(&REST ARGS &KEY K1 K2 K3).
ACL2 !>
If we don't want to get the error above, we can use
&allow-other-keys, as follows.
ACL2 !>(defmacro bar (&rest args &key k1 k2 k3
&allow-other-keys)
(list 'quote (list args k1 k2 k3)))
Summary
Form: ( DEFMACRO BAR ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
BAR
ACL2 !>(bar :k1 3 :bad-key 7)
((:K1 3 :BAD-KEY 7) 3 NIL NIL)
ACL2 !>
Also see [trans].
Subtopics
[Set-duplicate-keys-action]
Control action for macro calls with duplicate keyword arguments")
(MACRO-COMMAND
(PROOF-CHECKER)
"Compound command for the proof-checker
The proof-checker (see [proof-checker]) allows the user to supply
interactive commands. Compound commands, called macro commands, may
be defined; these expand into zero or more other commands. Some of
these are ``atomic'' macro commands; these are viewed as a single
command step when completed successfully.
More [documentation] will be written on the [proof-checker]. For now,
we simply point out that there are lots of examples of the use of
define-pc-macro and define-pc-atomic-macro in the ACL2 source file
\"proof-checker-b.lisp\". The former is used to create macro
commands, which can be submitted to the interactive loop (see
[verify]) and will ``expand'' into zero or more commands. The
latter is similar, except that the undoing mechanism (see
[ACL2-pc::undo]) understands atomic macro commands to represent
single interactive commands. Also see [ACL2-pc::comm] and see
[ACL2-pc::commands] for a discussion of the display of interactive
commands.
Also see [toggle-pc-macro] for how to change a macro command to an
atomic macro command, and vice versa.")
(MACROS
(ACL2)
"Macros allow you to extend the syntax of ACL2.
Subtopics
[Add-binop]
Associate a function name with a macro name
[Add-macro-alias]
Associate a function name with a macro name
[Add-macro-fn]
Associate a function name with a macro name
[Defabbrev]
A convenient form of macro definition for simple expansions
[Defmacro]
Define a macro
[Macro-aliases-table]
A [table] used to associate function names with macro names
[Macro-args]
The formals list of a macro definition
[Make-event]
Evaluate (expand) a given form and then evaluate the result
[Remove-binop]
Remove the association of a function name with a macro name
[Remove-macro-alias]
Remove the association of a function name with a macro name
[Remove-macro-fn]
Remove the association of a function name with a macro name
[Set-duplicate-keys-action]
Control action for macro calls with duplicate keyword arguments
[Trans]
Print the macroexpansion of a form
[Trans!]
Print the macroexpansion of a form without single-threadedness
concerns
[Trans1]
Print the one-step macroexpansion of a form
[Untrans-table]
Associates a function symbol with a macro for printing user-level
terms
[User-defined-functions-table]
An advanced [table] used to replace certain system functions")
(MAKE
(DEFREC ACL2-BUILT-INS)
"Constructor macro for [defrec] structures.
The make macro is built into ACL2, and allows you to construct new
instances of structures that have been introduced with [defrec].
For instance:
(make employee :name \"Jimmy\"
:salary 0
:position \"Unpaid Intern\")
Creates a new employee structure with the given values for its name,
salary, and position fields. See [defrec] for more information.")
(MAKE-CHARACTER-LIST
(CHARACTERS ACL2-BUILT-INS)
"[coerce] to a list of characters
Non-characters in the given list are [coerce]d to the character with
code 0.
Function: <make-character-list>
(defun make-character-list (x)
(declare (xargs :guard t))
(cond ((atom x) nil)
((characterp (car x))
(cons (car x)
(make-character-list (cdr x))))
(t (cons (code-char 0)
(make-character-list (cdr x))))))")
(MAKE-EVENT
(EVENTS MACROS)
"Evaluate (expand) a given form and then evaluate the result
Make-event is a utility for generating [events]. It provides a
capability not offered by Lisp macros (see [defmacro]), as it
allows access to the ACL2 [state] and logical [world]. In essence,
the expression (make-event form) replaces itself with the result of
evaluating form, say, ev, as though one had submitted ev instead of
the make-event call. For example, (make-event (quote (defun f (x)
x))) is equivalent to the event (defun f (x) x).
We break this documentation into the following sections.
Introduction
Detailed Documentation
Error Reporting
Restriction to Event Contexts
Examples Illustrating How to Access State
Advanced Expansion Control
We begin with an informal introduction, which focuses on examples and
introduces the key notion of ``expansion phase''.
Introduction
Make-event is particularly useful for those who program using the
ACL2 [state]; see [programming-with-state]. That is because the
evaluation of form may read and even modify the ACL2 [state].
Suppose for example that we want to define a constant *world-length*,
that is the length of the current ACL2 [world]. A make-event form
can accomplish this task, as follows.
ACL2 !>(length (w state))
98883
ACL2 !>(make-event
(list 'defconst '*world-length* (length (w state))))
Summary
Form: ( DEFCONST *WORLD-LENGTH* ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Summary
Form: ( MAKE-EVENT (LIST ...))
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
*WORLD-LENGTH*
ACL2 !>*world-length*
98883
ACL2 !>(length (w state))
98890
ACL2 !>
How did this work? First, evaluation of the form (list 'defconst
'*world-length* (length (w state))) returned the event form
(defconst *world-length* 98883). Then that event form was
automatically submitted to ACL2. Of course, that changed the ACL2
logical [world], which is why the final value of (length (w state))
is greater than its initial value.
The example above illustrates how the evaluation of a make-event call
takes place in two phases. The first phase evaluates the argument
of the call, in this case (list 'defconst '*world-length* (length
(w state))), to compute an event form, in this case (defconst
*world-length* 98883). We call this evaluation the ``expansion''
phase. Then the resulting event form is evaluated, which in this
case defines the constant *world-length*.
Now suppose we would like to introduce such a [defconst] form any
time we like. It is common practice to define macros to automate
such tasks. Now we might be tempted simply to make the following
definition.
; WRONG!
(defmacro define-world-length-constant (name state)
(list 'defconst name (length (w state))))
But ACL2 rejects such a definition, because a macro cannot take the
ACL2 state as a parameter; instead, the formal parameter to this
macro named \"STATE\" merely represents an ordinary object. You can
try to experiment with other such direct methods to define such a
macro, but they won't work.
Instead, however, you can use the approach illustrated by the
make-event example above to define the desired macro, as follows.
(defmacro define-world-length-constant (name)
`(make-event (list 'defconst ',name (length (w state)))))
Here are example uses of this macro.
ACL2 !>(define-world-length-constant *foo*)
Summary
Form: ( DEFCONST *FOO* ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Summary
Form: ( MAKE-EVENT (LIST ...))
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
*FOO*
ACL2 !>*foo*
98891
ACL2 !>:pe *foo*
2:x(DEFINE-WORLD-LENGTH-CONSTANT *FOO*)
> (DEFCONST *FOO* 98891)
ACL2 !>(length (w state))
98897
ACL2 !>(define-world-length-constant *bar*)
Summary
Form: ( DEFCONST *BAR* ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Summary
Form: ( MAKE-EVENT (LIST ...))
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
*BAR*
ACL2 !>*bar*
98897
ACL2 !>:pe *bar*
3:x(DEFINE-WORLD-LENGTH-CONSTANT *BAR*)
> (DEFCONST *BAR* 98897)
ACL2 !>(length (w state))
98903
ACL2 !>
Finally, we note that the expansion phase can be used for computation
that has side effects, generally by modifying state. Here is a
modification of the above example that does not change the world at
all, but instead saves the length of the world in a state global.
(make-event
(pprogn (f-put-global 'my-world-length (length (w state)) state)
(value '(value-triple nil))))
Notice that this time, the value returned by the expansion phase is
not an event form, but rather, is an [error-triple] whose value
component is an event form, namely, the event form (value-triple
nil). Evaluation of that event form does not change the ACL2 world
(see [value-triple]). Thus, the sole purpose of the make-event call
above is to change the [state] by associating the length of the
current logical world with the state global named 'my-world-length.
After evaluating this form, (@ my-world-length) provides the length
of the ACL2 world, as illustrated by the following transcript.
ACL2 !>:pbt 0
0:x(EXIT-BOOT-STRAP-MODE)
ACL2 !>(length (w state))
98883
ACL2 !>(make-event
(pprogn (f-put-global 'my-world-length (length (w state)) state)
(value '(value-triple nil))))
Summary
Form: ( MAKE-EVENT (PPROGN ...))
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
NIL
ACL2 !>(length (w state))
98883
ACL2 !>:pbt 0
0:x(EXIT-BOOT-STRAP-MODE)
ACL2 !>
When make-event is invoked by a book, it is expanded during book
certification but not, by default, when the book is included. So
for the example (define-world-length-constant *foo*) given above,
if that form is in a book, then the value of *foo* will be the
length of the world at the time this form was invoked during book
certification, regardless of world length at [include-book] time.
(The expansion is recorded in the book's [certificate], and
re-used.) To overcome this default, you can specify keyword value
:CHECK-EXPANSION t. This will cause an error if the expansion is
different, but it can be useful for side effects. For example, if
you insert the following form in a book, then the length of the
world will be printed when the form is encountered, whether during
[certify-book] or during [include-book].
(make-event
(pprogn (fms \"Length of current world: ~x0~|\"
(list (cons #\\0 (length (w state))))
*standard-co* state nil)
(value '(value-triple nil)))
:check-expansion t)
Detailed Documentation
Examples:
; Trivial example: evaluate (quote (defun foo (x) x)) to obtain
; (defun foo (x) x), which is then evaluated.
(make-event (quote (defun foo (x) x)))
; Evaluate (generate-form state) to obtain (mv nil val state), and
; then evaluate val. (Generate-form is not specified here, but
; imagine for example that it explores the state and then generates
; some desired definition or theorem.)
(make-event (generate-form state))
; As above, but make sure that if this form is in a book, then when
; we include the book, the evaluation of (generate-form state)
; should return the same value as it did when the book was
; certified.
(make-event (generate-form state)
:CHECK-EXPANSION t)
; As above (where the :CHECK-EXPANSION value can be included or
; not), where if there is an error during expansion, then the error
; message will explain that expansion was on behalf of the indicated
; object, typically specified as the first argument.
(make-event (generate-form state)
:ON-BEHALF-OF (generate-form state))
General Form:
(make-event form :CHECK-EXPANSION chk :ON-BEHALF-OF obj :EXPANSION? form)
where chk is nil (the default), t, or the intended ``expansion
result'' from the evaluation of form (as explained below); and if
supplied, obj is an arbitrary ACL2 object, used only in reporting
errors in expansion, i.e., in the evaluation of form. The
:EXPANSION? keyword is discussed in the final section, on Advanced
Expansion Control.
We strongly recommend that you browse some .lisp files in the
community books directory books/make-event/. You may even find it
helpful, in order to understand make-event, to do so before
continuing to read this documentation. You may also find it useful
to browse community book books/misc/eval.lisp, which contains
definitions of macros must-succeed and must-fail that are useful
for testing and are used in many books in the books/make-event/
directory, especially eval-tests.lisp. Another example,
books/make-event/defrule.lisp, shows how to use macros whose calls
expand to make-event forms, which in turn can generate [events].
For more examples, see file books/make-event/Readme.lsp. Other than
the examples, the explanations here should suffice for most users.
If you want explanations of subtler details, see
[make-event-details].
Note that make-event may only be used at the ``top level'' or where
an event is expected. See the section ``Restriction to Event
Contexts'', below.
Make-event is related to Lisp macroexpansion in the sense that its
argument is evaluated to obtain an expansion result, which is
evaluated again. Let us elaborate on each of these notions in turn:
``is evaluated,'' ``expansion result'', and ``evaluated again.''
The final section, on Advanced Expansion Control, will generalize
these processes in a way that we ignore for now.
``is evaluated'' --- The argument can be any expression, which is
evaluated as would be any expression submitted to ACL2's top
level loop. Thus, [state] and user-defined [stobj]s may appear
in the form supplied to make-event. Henceforth, we will refer
to this evaluation as ``expansion.'' Expansion is actually done
in a way that restores ACL2's built-in [state] global
variables, including the logical [world], to their
pre-expansion values (with a few exceptions --- see
[make-event-details] --- and where we note that changes to
user-defined [state] global variables (see [assign]) are
preserved). So, for example, events might be evaluated during
expansion, but they will disappear from the logical [world]
after expansion returns its result. Moreover, proofs are
enabled by default at the start of expansion (see
[ld-skip-proofsp]) if keyword :CHECK-EXPANSION is supplied and
has a non-nil value.
``expansion result'' --- The above expansion may result in an
ordinary (non-[state], non-[stobj]) value, which we call the
``expansion result.'' Or, expansion may result in a multiple
value of the form (mv erp val state), or, more generally, (mv
erp val state stobj-1 ... stobj-k) where each stobj-i is a
[stobj]; then the expansion result is val unless erp is not
nil, in which case there is no expansion result, and the
original make-event evaluates to a soft error. In either case
(single or multiple value), either val is an embedded event
form (see [embedded-event-form]), or else the original
make-event evaluates to a soft error, printed as described
under ``Error Reporting'' below.
(Technical remark: The expansion result described above may be
modified for [include-book], [add-include-book-dir], and
[add-include-book-dir!], replacing book names by full
pathnames, using syntax (:system . relative-pathname) for
[community-books] (i.e., system books); see [full-book-name],
and for further details see comments in source function
make-include-books-absolute. End of technical remark.)
``evaluated again'' --- the expansion result is evaluated in place of
the original make-event.
The expansion process can invoke subsidiary calls of make-event, and
the expansion result can (perhaps after macroexpansion) be a call
of make-event. It can be useful to track all these make-event
calls. The [state] global variable make-event-debug may be set to a
non-nil value, for example (assign make-event-debug t), in order to
see a trace of the expansion process, where a level is displayed
(as in ``3>'') to indicate the depth of subsidiary expansions.
Expansion of a make-event call will yield an event that replaces the
original make-event call. In particular, if you put a make-event
form in a book, then in essence it is replaced by its expansion
result, created during the proof pass of the [certify-book]
process. We now elaborate on this idea of keeping the original
expansion.
A make-event call generates a ``make-event replacement'' that may be
stored by the system. In the simplest case, this replacement is the
expansion result. When a book is certified, these replacements are
stored in a book's certificate (technically, in the
:EXPANSION-ALIST field). Thus, although the book is not textually
altered during certification, one may imagine a ``book expansion''
corresponding to the original book, in which events are substituted
by replacements that were generated during the proof phase of
certification. A subsequent [include-book] will then include the
book expansion corresponding to the indicated book. When a book is
compiled during [certify-book], it is actually the corresponding
book expansion, stored as a temporary file, that is compiled
instead. That temporary file is deleted after compilation unless
one first evaluates the form (assign keep-tmp-files t). Note
however that all of the original forms must still be legal
[events]; see [embedded-event-form]. So for example, if the first
event in a book is (local (defmacro my-id (x) x)), and is followed
by (my-id (make-event ...)), the final ``include-book'' pass of
[certify-book] will fail because my-id is not defined when the
my-id call is encountered.
A make-event replacement might not be the expansion when either of
the keyword arguments :CHECK-EXPANSION or :EXPANSION? is supplied.
We deal with the latter in the final section, on Advanced Expansion
Control. If :CHECK-EXPANSION t is supplied and the expansion is
exp, then the replacement is obtained from the original make-event
call, by substituting exp for t as the value of keyword
:CHECK-EXPANSION. Such a make-event call --- during the second pass
of an [encapsulate], or during event processing on behalf of
[include-book] other than when including a book near the end of its
certification process --- will do the expansion again and check
that the expansion result is equal to the original expansion
result, exp. In the unusual case that you know the expected
expansion result, res, you can specify :CHECK-EXPANSION res in the
first place, so that the check is also done during the initial
evaluation of the make-event form. IMPORTANT BUT OBSCURE DETAIL:
That expansion check is only done when processing events, not
during a preliminary load of a book's compiled file. The following
paragraph elaborates.
(Here are details on the point made just above, for those who use the
:CHECK-EXPANSION argument to perform side-effects on the [state].
When you include a book, ACL2 generally loads a compiled file
before processing the events in the book; see [book-compiled-file].
While it is true that a non-nil :CHECK-EXPANSION argument causes
[include-book] to perform expansion of the make-event form during
event processing it does not perform expansion when the compiled
file (or expansion file; again, see [book-compiled-file]) is
loaded.)
ACL2 performs the following space-saving optimization: when the
expansion result is a [local] event, then the make-event
replacement is (local (value-triple :ELIDED)).
The notion of ``expansion'' and ``replacement'' extend to the case
that a call of make-event is found in the course of macroexpansion.
The following example illustrates this point.
(encapsulate
()
(defmacro my-mac ()
'(make-event '(defun foo (x) x)))
(my-mac))
:pe :here
The above call of [pe] shows that the form (my-mac) has a make-event
expansion (and replacement) of (DEFUN FOO (X) X):
(ENCAPSULATE NIL
(DEFMACRO MY-MAC
NIL
'(MAKE-EVENT '(DEFUN FOO (X) X)))
(RECORD-EXPANSION (MY-MAC)
(DEFUN FOO (X) X)))
Error Reporting
Suppose that expansion produces a soft error as described above. That
is, suppose that the argument of a make-event call evaluates to a
multiple value (mv erp val state ...) where erp is not nil. If erp
is a string, then that string is printed in the error message. If
erp is a [cons] pair whose [car] is a string, then the error prints
\"~@0\" with #\\0 bound to that cons pair; see [fmt]. Any other
non-nil value of erp causes a generic error message to be printed.
Restriction to Event Contexts
A make-event call must occur either at the top level, or during
make-event expansion, or as an argument of an event constructor. We
explain in more detail below. This restriction is imposed to enable
ACL2 to track expansions produced by make-event.
The following examples illustrate this restriction.
; Legal:
(progn (with-output
:on summary
(make-event '(defun foo (x) x))))
; Illegal:
(mv-let (erp val state)
(make-event '(defun foo (x) x))
(mv erp val state))
More precisely: a make-event call that is not itself evaluated during
make-event expansion is subject to the following requirement. After
macroexpansion has taken place, such a make-event call must be in
an ``event context'', defined recursively as follows. (All but the
first two cases below correspond to similar cases for constructing
events; see [embedded-event-form].)
* A form submitted at the top level, or more generally, supplied to a
call of [ld], is in an event context.
* A form occurring at the top level of a book is in an event context.
* If ([local] x1) is in an event context, then so is x1.
* If ([skip-proofs] x1) is in an event context, then so is x1.
* If ([make-event] x ...) is in an event context and its expansion x1
is an embedded event form, then x1 is in an event context.
* If ([with-output] ... x1), ([with-prover-step-limit] ... x1 ...), or
([with-prover-time-limit] ... x1) is in an event context, then
so is x1.
* For any call of [progn] or [progn!], each of its arguments is in an
event context.
* For any call of [encapsulate], each of its arguments except the first
(the signature list) is in an event context.
* If (RECORD-EXPANSION x1 x2) is in an event context, then x1 and x2
are in event contexts. Note: record-expansion is intended for
use only by the implementation, which imposes the additional
restriction that x1 and its subsidiary make-event calls (if
any) must specify a :CHECK-EXPANSION argument that is a
[consp].
Low-level remark, for system implementors. There is the one exception
to the above restriction: a single [state-global-let*] form
immediately under a progn! call. For example:
(progn! (state-global-let* <bindings> (make-event ...)))
However, the following form may be preferable (see [progn!]):
(progn! :STATE-GLOBAL-BINDINGS <bindings> (make-event ...))
Also see [remove-untouchable] for an interesting use of this
exception.
Examples Illustrating How to Access State
You can modify the ACL2 [state] by doing your state-changing
computation during the expansion phase, before expansion returns
the event that is submitted. Here are some examples.
First consider the following. Notice that expansion modifies state
global my-global during make-event expansion, and then expansion
returns a [defun] event to be evaluated.
(make-event
(er-progn (assign my-global (length (w state)))
(value '(defun foo (x) (cons x x)))))
Then we get:
ACL2 !>(@ my-global)
72271
ACL2 !>:pe foo
L 1:x(MAKE-EVENT (ER-PROGN # #))
>L (DEFUN FOO (X) (CONS X X))
ACL2 !>
Here's a slightly fancier example, where the computation affects the
[defun]. In a new session, execute:
(make-event
(er-progn (assign my-global (length (w state)))
(value `(defun foo (x) (cons x ,(@ my-global))))))
Then:
ACL2 !>(@ my-global)
72271
ACL2 !>:pe foo
L 1:x(MAKE-EVENT (ER-PROGN # #))
>L (DEFUN FOO (X) (CONS X 72271))
ACL2 !>
Note that ACL2 [table] [events] may avoid the need to use [state]
globals. For example, instead of the example above, consider this
example in a new session.
(make-event
(let ((world-len (length (w state))))
`(progn (table my-table :STORED-WORLD-LENGTH ,world-len)
(defun foo (x) (cons x ,world-len)))))
Then:
ACL2 !>(table my-table)
((:STORED-WORLD-LENGTH . 72271))
ACL2 !>:pe foo
1:x(MAKE-EVENT (LET # #))
>L (DEFUN FOO (X) (CONS X 72271))
ACL2 !>
By the way, most built-in [state] globals revert after expansion. But
your own global (like my-global above) can be set during expansion,
and the new value will persist.
Advanced Expansion Control
We conclude this [documentation] section by discussing three kinds of
additional control over make-event expansion. These are all
illustrated in community book
books/make-event/make-event-keywords-or-exp.lisp. The discussion
below is split into the following three parts.
(1) The value produced by expansion may have the form (:DO-PROOFS
exp), which specifies exp as the expansion result, to be evaluated
without skipping proofs even when including a book.
(2) The value produced by expansion may have the form (:OR exp-1 ...
exp-k), which specifies that the first form exp-i to evaluate
without error is the expansion result.
(3) The keyword argument :EXPANSION? can serve to eliminate the
storing of make-event replacements, as described above for the
``book expansion'' of a book.
We now elaborate on each of these.
(1) :DO-PROOFS ``call'' produced by expansion.
We have discussed the expansion result produced by the expansion
phase of evaluating a make-event call. However, if the expansion
phase produces an expression of the form (:DO-PROOFS exp), then the
expansion result is actually exp. The :DO-PROOFS wrapper indicates
that even if proofs are currently being skipped (see
[ld-skip-proofsp]), then evaluation of exp should take place with
proofs not skipped. For example, proofs will be performed when
evaluating the make-event expansion, namely the indicated defthm
event, in the following example.
(set-ld-skip-proofsp t state)
(make-event '(:DO-PROOFS
(defthm app-assoc (equal
(append (append x y) z)
(append x y z)))))
Note that such use of :DO-PROOFS causes proofs to be performed when
evaluating the expansion while including an uncertified book. But
when including a certified book, then unless :CHECK-EXPANSION is
supplied a non-nil value, the make-event replacement will just be
the expansion, which does not include the :DO-PROOFS wrapper and
hence will be evaluated with proofs skipped.
(2) :OR ``call'' produced by expansion.
There may be times where you want to try different expansions. For
example, the community book books/make-event/proof-by-arith.lisp
attempts to admit a given event, which we'll denote EV, by trying
events of the following form as BOOK varies over different
community books.
(encapsulate
()
(local (include-book BOOK :DIR :SYSTEM))
EV)
A naive implementation of this macro would evaluate all such
[encapsulate] events until one succeeds, and then return that
successful event as the expansion. Then that event would need to be
evaluated again! With some hacking one could avoid that
re-evaluation by using [skip-proofs], but that won't work if you
are trying to create a certified book without skipped proofs.
Instead, the implementation creates an expansion of the form (:OR
ev-1 ev-2 ... ev-k), where the list (ev-1 ev-2 ... ev-k) enumerates
the generated encapsulate events. In general, for this
``disjunctive case'' of a result from expansion, each ev-i is
evaluated in sequence, and the first that succeeds without error is
considered to be the expansion result --- and a repeat evaluation
is avoided. If evaluation of each ev-i results in an error, then so
does the make-event call.
This special use of :OR in a value produced by expansion is only
supported at the top level. That is, the result can be (:OR ev-1
ev-2 ... ev-k) but then each ev-i must be a legal expansion result,
without such further use of :OR --- except, ev-i may be (:DO-PROOFS
ev-i'), where ev-i' then would serve as the expansion rather than
ev-i.
(3) The :EXPANSION? keyword argument.
If keyword argument :EXPANSION? has a nonnil value, then the
:CHECK-EXPANSION keyword must be omitted or have value nil or t,
hence not a cons pair.
The idea of the :EXPANSION? keyword is to give you a way to avoid
storing expansion results in a book's [certificate]. Roughly
speaking, when the expansion result matches the value of
:EXPANSION?, then no expansion result is stored for the event by
book certification; then when the book is later included, the value
of :EXPANSION? is used as the expansion, thus bypassing the
expansion phase. One could say that the event is its own make-event
replacement, but it is more accurate to say that there is no
make-event replacement at all, since nothing is stored in the
certificate for this event. Below, we elaborate on make-event
replacements when :EXPANSION is used and also discuss other
properties of this keyword.
We modify the notion of ``expansion result'' for make-event forms to
comprehend the use of the :EXPANSION? keyword. For that purpose,
let's consider a call of make-event to be ``reducible'' if it has
an :EXPANSION? keyword with non-nil value, exp, and its
:CHECK-EXPANSION keyword is missing or has value nil, in which case
the ``reduction'' of this make-event call is defined to be exp. The
expansion result as originally defined is modified by the following
``recursive reduction'' process: recur through the original
expansion, passing through calls of [local], [skip-proofs],
[with-output], [with-prover-step-limit], and
[with-prover-time-limit], and replacing (recursively) any reducible
call of make-event by its reduction. Furthermore, we refer to two
forms as ``reduction equivalent'' if their recursive reductions are
equal. Note that the recursive reduction process does not pass
through [progn] or [encapsulate], but that process is applied to
the computation of expansions for their subsidiary [make-event]
calls.
To explain further the effect of :EXPANSION? exp, we split into the
following two cases.
Case 1: Evaluation is not taking place when including a book or
evaluating the second pass of an [encapsulate] event; more
precisely, the value of (ld-skip-proofsp state) is not the symbol
INCLUDE-BOOK. There are two subcases.
* Case 1a: The expansion result is not reduction-equivalent to exp.
Then the make-event call is processed as though the :EXPANSION?
keyword had been omitted.
* Case 2a: The expansion result is reduction-equivalent to exp. Then
there is no make-event replacement for this call of make-event;
no replacement will be put into the [certificate] file for a
book containing this make-event call. When that book is
subsequently included, the original form will be evaluated in
the manner described in the next case.
Case 2: Evaluation is taking place when including a book or
evaluating the second pass of an [encapsulate] event; more
precisely, the value of (ld-skip-proofsp state) is the symbol
INCLUDE-BOOK. Then the expansion is exp. The expansion phase is
skipped unless :CHECK-EXPANSION is t.
The :EXPANSION? keyword can be particularly useful in concert with
the disjunctive (``:OR'') case (2) discussed above. Suppose that
expansion produces a value as discussed in (2) above, (:OR exp-1
... exp-k). If one of these expressions exp-i is more likely than
the others to be the expansion, then you may wish to specify
:EXPANSION? exp-i, as this will avoid storing a make-event
replacement in that common case. This could be useful if the
expressions are large, to avoid enlarging the [certificate] file
for a book containing the make-event call.
It is legal to specify both :EXPANSION? exp and :CHECK-EXPANSION t.
When either (ld-skip-proofsp state) is the symbol INCLUDE-BOOK, or
evaluation is taking place in raw Lisp, then this combination is
treated the same as if :EXPANSION? is omitted and the value of
:CHECK-EXPANSION is exp. Otherwise, this combination is treated the
same as :CHECK-EXPANSION t, modified to accommodate the effect of
:EXPANSION? as discussed above: if the expansion is indeed the
value of :EXPANSION?, then no make-event replacement is generated.
Subtopics
[Make-event-details]
Details on [make-event] expansion")
(MAKE-EVENT-DETAILS
(MAKE-EVENT)
"Details on [make-event] expansion
The normal user of make-event can probably ignore this section, but
we include it for completeness. We assume that the reader has read
and understood the basic documentation for make-event (see
[make-event]), but we begin below with a summary of expansion.
Introduction
Here is a summary of how we handle expansion involving make-event
forms.
(make-event form :check-expansion nil)
This shows the :check-expansion default of nil, and is typical user
input. We compute the expansion exp of form, which is the expansion
of the original make-event expression and is evaluated in place of
that expression.
(make-event form :check-expansion t)
The user presumably wants it checked that the expansion doesn't
change in the future, in particular during [include-book]. If the
expansion of form is exp, then we will evaluate exp to obtain the
value as before, but this time we record that the expansion of the
original make-event expression is (make-event form :check-expansion
exp) rather than simply exp.
(make-event form :check-expansion exp) ; exp a cons
This is generated for the case that :check-expansion is t, as
explained above. Evaluation is handled as described in that above
case, except here we check that the expansion result is the given
exp. (Actually, the user is also allowed supply such a form.) The
original make-event expression does not undergo any expansion
(intuitively, it expands to itself).
Now let us take a look at how we expand [progn] forms ([encapsulate]
is handled similarly).
(progn ... (make-event form :check-expansion nil) ...)
The expansion is obtained by replacing the make-event form as
follows. Let exp be the expansion of form. Then replace the above
make-event form, which we denote as F, by (record-expansion F exp).
Here, record-expansion is a macro that returns its second argument.
(progn ... (make-event form :check-expansion t) ...)
The expansion is of the form (record-expansion F exp) as in the nil
case above, except that this time exp is (make-event form
:check-expansion exp'), where exp' is the expansion of form.
(progn ... (make-event form :check-expansion exp) ...) ; exp a cons
No expansion takes place unless expansion takes place for at least
one of the other subforms of the progn, in which case each such
form F is replaced by (record-expansion F exp) where exp is the
expansion of F.
Detailed semantics
In our explanation of the semantics of make-event, we assume
familiarity with the notion of ``embedded event form'' (see
[embedded-event-form]).
Let's say that the ``actual embedded event form'' corresponding to a
given form is the underlying call of an ACL2 event: that is,
[local]s are dropped when ld-skip-proofsp is 'include-book, and
macros are expanded away, thus leaving us with a [progn], a
[make-event], or an event form (possibly [encapsulate]), any of
which might have surrounding [local], [skip-proofs], or
[with-output] calls.
Thus, such an actual embedded event form can be viewed as having the
form (rebuild-expansion wrappers base-form) where base-form is a
progn, a make-event, or an event form (possibly encapsulate), and
wrappers are (as in ACL2 source function destructure-expansion) the
result of successively removing the event form from the result of
macroexpansion, leaving a sequence of (local), (skip-proofs), and
(with-output ...) forms. In this case we say that the form
``destructures into'' the indicated wrappers and base-form, and
that it can be ``rebuilt from'' those wrappers and base-form.
Elsewhere we define the notion of the ``expansion result'' from an
evaluation (see [make-event]), and we mention that when expansion
concludes, the ACL2 logical [world] and most of the state are
restored to their pre-expansion values. Specifically, after
evaluation of the argument of make-event (even if it is aborted),
the ACL2 logical world is restored to its pre-evaluation value, as
are all state global variables in the list
*protected-system-state-globals*. Thus, assignments to user-defined
state globals (see [assign]) do persist after expansion, since they
are not in that list.
We recursively define the combination of evaluation and expansion of
an embedded event form, as follows. We also simultaneously define
the notion of ``expansion takes place,'' which is assumed to
propagate upward (in a sense that will be obvious), such that if no
expansion takes place, then the expansion of the given form is
considered to be itself. It is useful to keep in mind a goal that
we will consider later: Every make-event subterm of an expansion
result has a :check-expansion field that is a [consp], where for
this purpose make-event is viewed as a macro that returns its
:check-expansion field. (Implementation note: The latest expansion
of a [make-event], [progn], [progn!], or [encapsulate] is stored in
state global 'last-make-event-expansion, except that if no
expansion has taken place for that form then
'last-make-event-expansion has value nil.)
If the given form is not an embedded event form, then simply cause a
soft error, (mv erp val state) where erp is not nil. Otherwise:
If the evaluation of the given form does not take place (presumably
because [local] events are being skipped), then no expansion
takes place. Otherwise:
Let x be the actual embedded event form corresponding to the given
form, which destructures into wrappers W and base-form B. Then
the original form is evaluated by evaluating x, and its
expansion is as follows.
If B is (make-event form :check-expansion val), then expansion takes
place if and only if val is not a consp and no error occurs, as
now described. Let R be the expansion result from protected
evaluation of form, if there is no error. R must be an embedded
event form, or it is an error. Then evaluate/expand R, where if
val is not nil then state global 'ld-skip-proofsp is
initialized to nil. (This initialization is important so that
subsequent expansions are checked in a corresponding
environment, i.e., where proofs are turned on in both the
original and subsquent environments.) It is an error if this
evaluation causes an error. Otherwise, the evaluation yields a
value, which is the result of evaluation of the original
make-event expression, as well as an expansion, E_R. Let E be
rebuilt from W and E_R. The expansion of the original form is E
if val is nil, and otherwise is the result of replacing the
original form's :check-expansion field with E, with the added
requirement that if val is not t (thus, a consp) then E must
equal val or else we cause an error.
If B is either (progn form1 form2 ...) or (encapsulate sigs form1
form2 ...), then after evaluating B, the expansion of the
original form is the result of rebuilding from B, with wrappers
W, after replacing each formi in B for which expansion takes
place by (record-expansion formi formi'), where formi' is the
expansion of formi. Note that these expansions are determined
as the formi are evaluated in sequence (where in the case of
encapsulate, this determination occurs only during the first
pass). Except, if no expansion takes place for any formi, then
the expansion of the original form is itself.
Otherwise, the expansion of the original form is itself.
Similarly to the [progn] and [encapsulate] cases above, book
certification causes a book to be replaced by its so-called ``book
expansion.'' There, each event ev for which expansion took place
during the proof pass of certification --- say, producing ev' ---
is replaced by (record-expansion ev ev').
Implementation Note. The book expansion is actually implemented by
way of the :expansion-alist field of its [certificate], which
associates 0-based positions of top-level forms in the book (not
including the initial [in-package] form) with their expansions.
Thus, the book's source file is not overwritten; rather, the
certificate's expansion-alist is applied when the book is included
or compiled. End of Implementation Note.
It is straightforward by computational induction to see that for any
expansion of an embedded event form, every make-event sub-event has
a [consp] :check-expansion field. Here, by ``sub-event'' we mean to
expand macros; and we also mean to traverse progn and encapsulate
forms as well as :check-expansion fields of make-event forms. Thus,
we will only see make-event forms with consp :check-expansion
fields in the course of include-book forms, the second pass of
encapsulate forms, and raw Lisp. This fact guarantees that an event
form will always be treated as its original expansion.
Notes on ttags
See [defttag] for documentation of the notion of ``trust tag''
(``ttag''). We note here that even if an event (defttag tag-name)
for non-nil tag-name is admitted only during the expansion phase of
a [make-event] form, then such expansion will nevertheless still
cause tag-name to be recorded in the logical [world] (assuming that
the make-event form is admitted). So in order to certify such a
book, a suitable :ttags argument must be supplied; see
[certify-book].
ACL2 does provide a way to avoid the need for :ttags arguments in
such cases. The idea is to certify a book twice, where the results
of make-event expansion are saved from the first call of
[certify-book] and provided to the second call. See
[set-write-ACL2x].
Finally, we discuss a very unusual case where certification does not
involve trust tags but a subsequent [include-book] does involve
trust tags: a make-event call specifying :check-expansion t, whose
expansion generates a [defttag] event during [include-book] but not
[certify-book]. Consider the following book.
(in-package \"ACL2\")
(make-event
(er-progn
(if (@ skip-notify-on-defttag) ; non-nil when including a certified book
(pprogn
(fms \"Value of (@ skip-notify-on-defttag): ~x0~|\"
(list (cons #0 (@ skip-notify-on-defttag)))
*standard-co* state nil)
(encapsulate
()
(defttag :foo)
(value-triple \"Imagine something bad here!\")))
(value nil))
(value '(value-triple :some-value)))
:check-expansion t)
This book certifies successfully without the need for a :ttags
argument for [certify-book]. Indeed, the above book's [certificate]
does not specify :foo as a trust tag associated with the book,
because no defttag event was executed during book certification.
Unfortunately, if we try to include this book without specifying a
value of :ttags that allows :foo, book inclusion will cause
executing of the above [defttag]. If that inclusion happens in the
context of certifying some superior book and the appropriate :ttags
arguments have not been provided, that certification will fail.")
(MAKE-FAST-ALIST
(FAST-ALISTS ACL2-BUILT-INS)
"(make-fast-alist alist) creates a fast-alist from the input alist,
returning alist itself or, in some cases, a new object equal to it.
Note: it is often better to use with-fast-alist; see
[with-fast-alist].
Logically, make-fast-alist is the identity function.
Function: <make-fast-alist>
(defun make-fast-alist (alist)
(declare (xargs :guard t))
alist)
Under the hood, we construct and return an object that is equal to
alist and which is a fast alist. If alist is already a fast alist,
almost no work is required: we simply return it unchanged.
When alist is not fast, we must minimally construct a hash table for
its bindings. It is often possible to bind this new hash table to
alist itself. But in certain cases when the alist keys are not
[normed], a new alist must be constructed, also, and so we may
return an equal but not eq alist. (In these cases, we still try to
avoid at least some consing by reusing the \"longest normed tail\" of
the alist.)")
(MAKE-LIST
(LISTS ACL2-BUILT-INS)
"Make a list of a given size
For a nonnegative integer size, (Make-list size) is a list of
elements of length size, each of which is initialized to the
:initial-element (which defaults to nil).
Make-list is a macro in ACL2, defined in terms of a tail recursive
function make-list-ac whose [guard] requires size to be a
nonnegative integer. Make-list is a Common Lisp function. See any
Common Lisp documentation for more information.
Macro: <make-list>
(defmacro make-list (size &key initial-element)
(cons 'make-list-ac
(cons size
(cons initial-element (cons 'nil 'nil)))))
Function: <make-list-ac>
(defun make-list-ac (n val ac)
(declare (xargs :guard (and (integerp n) (>= n 0))))
(cond ((zp n) ac)
(t (make-list-ac (1- n)
val (cons val ac)))))")
(MAKE-ORD
(ORDINALS ACL2-BUILT-INS)
"A constructor for ordinals.
Make-ord is the ordinal constructor. Its use is recommended instead
of using [cons] to make ordinals. For a discussion of ordinals, see
[ordinals].
For any ordinal, alpha < epsilon-0, there exist natural numbers p and
n, positive integers x1, x2, ..., xn and ordinals a1 > a2 > ... >
an > 0 such that alpha > a1 and alpha = w^(a1)x1 + w^(a2)x2 + ... +
w^(an)xn + p. We call a1 the ``first exponent'', x1 the ``first
coefficient'', and the remainder (w^(a2)x2 + ... + w^(an)xn + p)
the ``rest'' of alpha.
(Make-ord fe fco rst) corresponds to the ordinal (w^fe)fco + rst.
Thus the first infinite ordinal, w (omega), is constructed by
(make-ord 1 1 0)
and, for example, the ordinal (w^2)5 + w2 + 7 is constructed by:
(make-ord 2 5 (make-ord 1 2 7)) .
The reason make-ord is used rather than [cons] is that it allows us
to reason more abstractly about the ordinals, without having to
worry about the underlying representation.
Function: <make-ord>
(defun make-ord (fe fco rst)
(declare (xargs :guard (and (posp fco) (o-p fe) (o-p rst))))
(cons (cons fe fco) rst))")
(MAKE-TAU-INTERVAL
(TAU-SYSTEM ACL2-BUILT-INS)
"Make a tau interval
General Form:
(make-tau-interval doc lo-rel lo hi-rel hi)
An interval is a structure of the form: (dom (lo-rel . lo) . (hi-rel
. hi)). Every tau contains an interval used to represent the
domain, the upper, and the lower bounds of the objects recognized
by the tau.
make-tau-interval constructs well-formed intervals only if its five
arguments satisfy certain restrictions given below. When these
restrictions are violated make-tau-interval can construct objects
that are not intervals! make-tau-interval does not attempt to
coerce or adjust its arguments to make well-formed intervals.
For examples of intervals (and non-intervals!) constructed by
make-tau-interval see [tau-intervalp]. For examples of what objects
are contained in certain intervals, see [in-tau-intervalp].
The components of an interval are as follows:
dom (``domain'') -- must be one of four symbols: INTEGERP, RATIONALP,
ACL2-NUMBERP, or NIL denoting no restriction on the domain.
The two ``relations,'' lo-rel and hi-rel are Booleans, where t
denotes less-than inequality ([<]) and nil represents
less-than-or-equal inequality ([<=]). Think of t meaning ``strong''
and nil meaning ``weak'' inequality.
Lo and hi must be either nil or explicit rational numbers. If lo is
nil it denotes negative infinity; if hi is nil it denotes positive
infinity. Lo must be no greater than hi. Note: Even though
ACL2-NUMBERP intervals may contain complex rationals, the lo and hi
bounds must be rational. This is an arbitrary decision made by the
implementors to simplify coding.
Finally, if the dom is INTEGERP, then both relations should be weak
and lo and hi must be integers when they are non-nil.
For x to be ``in'' an interval it must be of the type described by
the domain predicate dom, lo must be smaller than x in the strong
or weak sense denoted by lo-rel, and x must be smaller than hi in
the strong or weak sense denoted by hi-rel.
The components of an interval may be accessed with the functions
[tau-interval-dom], [tau-interval-lo-rel], [tau-interval-lo],
[tau-interval-hi-rel], and [tau-interval-hi].")
(MAKE-WORMHOLE-STATUS
(WORMHOLE)
"Creates a wormhole status object from given status, entry code, and
data
General Form: (make-wormhole-status whs code data)
See [wormhole]. Whs should be a well-formed wormhole status, code
should be :ENTER or :SKIP, and data is arbitrary. This function
returns a new status with the specified entry code and data,
reusing whs if it is appropriate.")
(MANAGING-ACL2-PACKAGES
(PACKAGES)
"User-contributed documentation on packages
Jared Davis has contributed documentation on {managing ACL2 packages
|
http://www.cs.utexas.edu/users/moore/acl2/contrib/managing-acl2-packages.html}.
Also see [working-with-packages].")
(MAX
(NUMBERS ACL2-BUILT-INS)
"The larger of two numbers
(Max x y) is the larger of the numbers x and y.
The [guard] for max requires its arguments to be rational ([real], in
ACL2(r)) numbers.
Max is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <max>
(defun max (x y)
(declare (xargs :guard (and (real/rationalp x)
(real/rationalp y))))
(if (> x y) x y))")
(MAXIMUM-LENGTH
(ARRAYS ACL2-BUILT-INS)
"Return the :maximum-length from the [header] of an array
Example Form:
(maximum-length 'delta1 a)
General Form:
(maximum-length name alist)
where name is an arbitrary object and alist is a 1- or 2-dimensional
array. This function returns the contents of the :maximum-length
field of the [header] of alist. Whenever an [aset1] or [aset2]
would cause the length of the alist to exceed its maximum length, a
[compress1] or [compress2] is done automatically to remove
irrelevant pairs from the array. Maximum-length operates in
virtually constant time if alist is the semantic value of name. See
[arrays].
Function: <maximum-length>
(defun
maximum-length (name l)
(declare (xargs :guard (or (array1p name l) (array2p name l))))
(cadr (assoc-keyword :maximum-length (cdr (header name l)))))")
(MBE
(GUARD PROGRAMMING ACL2-BUILT-INS)
"Attach code for execution
The macro mbe (``must be equal'') can be used in function definitions
in order to cause evaluation to use alternate code to that provided
for the logic. An example is given below. However, the use of mbe
can lead to non-terminating computations. See [defexec], perhaps
after reading the present documentation, for a way to prove
termination.
In the ACL2 logic, (mbe :exec exec-code :logic logic-code) equals
logic-code; the value of exec-code is ignored. However, in raw Lisp
it is the other way around: this form macroexpands simply to
exec-code. ACL2's [guard] verification mechanism ensures that the
raw Lisp code is only evaluated when appropriate, since the guard
proof obligations generated for (the macroexpansion of) this call
of mbe include not only the guard proof obligations from exec-code,
but also, under suitable contextual assumptions, the term (equal
exec-code logic-code). See [verify-guards] (in particular, for
discussion of the contextual assumptions from the :guard and
[if]-tests) and, for general discussion of guards, see [guard].
Normally, during evaluation of an mbe call, only the :logic code is
evaluated unless the call is in the body of a [guard]-verified
function or under a call of a :[program] mode function; in those
cases only the :exec code is evaluated. This implies that equality
of :exec and :logic code is never checked at runtime. (Rather, such
equality is proved when verifying guards.) We qualified with
``normally'' above because there are two exceptions. During a
``safe mode'', which is used in macroexpansion and evaluation of
[defconst] forms, the :logic and :exec code are both evaluated and
their equality is checked. Second, when guard-checking is set to
:all or :none, then for any mbe call in the body of a :logic mode
definition, only the :logic code will be evaluated.
Note that the :exec and the :logic code in an mbe call must have the
same output signature. For example, one cannot return ([mv] * *)
while the other returns just a single value.
Also see [mbt], which stands for ``must be true.'' You may find it
more natural to use [mbt] for certain applications, as described in
its [documentation].
Here is an example of the use of mbe. Suppose that you want to define
factorial in the usual recursive manner, as follows.
(defun fact (n)
(if (zp n)
1
(* n (fact (1- n)))))
But perhaps you want to be able to execute calls of fact on large
arguments that cause stack overflows, perhaps during proofs. (This
isn't a particularly realistic example, but it should serve.) So,
instead you can define this tail-recursive version of factorial:
(defun fact1 (n acc)
(declare (xargs :guard (and (integerp n) (>= n 0) (integerp acc))))
(if (zp n)
acc
(fact1 (1- n) (* n acc))))
We are now ready to define fact using mbe. Our intention is that
logically, fact is as shown in the first definition above, but that
fact should be executed by calling fact1. Notice that we defer
[guard] verification, since we are not ready to prove the
correspondence between fact1 and fact.
(defun fact (n)
(declare (xargs :guard (and (integerp n) (>= n 0))
:verify-guards nil))
(mbe :exec (fact1 n 1)
:logic (if (zp n)
1
(* n (fact (1- n))))))
Next, we prove the necessary correspondence lemmas. Notice the
inclusion of a community book to help with the arithmetic
reasoning.
(include-book \"books/arithmetic/top-with-meta\")
(defthm fact1-fact
(implies (integerp acc)
(equal (fact1 n acc)
(* acc (fact n)))))
We may now do guard verification for fact, which will allow the
execution of the raw Lisp fact function, where the above mbe call
expands simply to (fact1 n 1).
(verify-guards fact)
Now that guards have been verified, a trace of function calls
illustrates that the evaluation of calls of fact is passed to
evaluation of calls of fact1. The outermost call below is of the
logical function stored for the definition of fact; all the others
are of actual raw Common Lisp functions.
ACL2 !>(trace$ fact fact1)
NIL
ACL2 !>(fact 3)
1> (ACL2_*1*_ACL2::FACT 3)
2> (FACT 3)
3> (FACT1 3 1)
4> (FACT1 2 3)
5> (FACT1 1 6)
6> (FACT1 0 6)
<6 (FACT1 6)
<5 (FACT1 6)
<4 (FACT1 6)
<3 (FACT1 6)
<2 (FACT 6)
<1 (ACL2_*1*_ACL2::FACT 6)
6
ACL2 !>
You may occasionally get warnings when you compile functions defined
using mbe. (For commands that invoke the compiler, see
[compilation].) These can be inhibited by using an ignorable
[declare] form. Here is a simple but illustrative example. Note
that the declarations can optionally be separated into two
[declare] forms.
(defun foo (x y)
(declare (ignorable x)
(xargs :guard (equal x y)))
(mbe :logic x :exec y))
Finally, we observe that when the body of a function contains a term
of the form (mbe :exec exec-code :logic logic-code), the user would
be unlikely to notice any difference in the theorem prover if this
term were replaced by logic-code. ACL2 takes various steps to
ensure this. For example, the proof obligations generated for
admitting a function treat the above mbe term simply as logic-code.
Function expansion, :use [hints], :[definition] rules, generation
of [constraint]s for functional instantiation, and creation of
rules of class :[rewrite] and :[forward-chaining] also treat mbe
calls as their :logic code.
Subtopics
[Defexec]
Attach a terminating executable function to a definition
[Mbe1]
Attach code for execution
[Mbt]
Introduce a test into the logic that, however, evaluates to t
[Mbt*]
Introduce a guard proof obligation
[Must-be-equal]
Attach code for execution")
(MBE1
(MBE ACL2-BUILT-INS)
"Attach code for execution
The form (mbe1 exec logic) is equivalent to the forms (mbe :logic
logic :exec exec) and (must-be-equal logic exec). See [mbe].")
(MBT
(MBE ACL2-BUILT-INS)
"Introduce a test into the logic that, however, evaluates to t
The macro mbt (``must be true'') can be used in order to add code in
order to admit function definitions in :[logic] mode, without
paying a cost in execution efficiency. Examples below illustrate
its intended use.
Semantically, (mbt x) equals x. However, in raw Lisp (mbt x) ignores
x entirely, and macroexpands to t. ACL2's [guard] verification
mechanism ensures that the raw Lisp code is only evaluated when
appropriate, since a guard proof obligation (equal x t) is
generated. See [verify-guards] and, for general discussion of
guards, see [guard].
Also see [mbe], which stands for ``must be equal.'' Although mbt is
more natural in many cases, mbe has more general applicability. In
fact, (mbt x) is essentially defined to be (mbe :logic x :exec t).
Another related utility is [mbt*], which generates the same proof
obligation as mbt but logically, is simply t.
We can illustrate the use of mbt on the following generic example,
where <g>, <test>, <rec-x>, and <base> are intended to be terms
involving only the variable x.
(defun foo (x)
(declare (xargs :guard <g>))
(if <test>
(foo <rec-x>)
<base>))
In order to admit this function, ACL2 needs to discharge the proof
obligation that <rec-x> is smaller than x, namely:
(implies <test>
(o< (acl2-count <rec-x>)
(acl2-count x)))
But suppose we need to know that <g> is true in order to prove this.
Since <g> is only the [guard], it is not part of the logical
definition of foo. A solution is to add the guard to the definition
of foo, as follows.
(defun foo (x)
(declare (xargs :guard <g>))
(if (mbt <g>)
(if <test>
(foo <rec-x>)
<base>)
nil))
If we do this using <g> rather than (mbt <g>), then evaluation of
every recursive call of foo will cause the evaluation of (the
appropriate instance of) <g>. But since (mbt <g>) expands to t in
raw Lisp, then once we verify the guards of foo, the evaluations of
<g> will be avoided (except at the top level, when we check the
guard before allowing evaluation to take place in Common Lisp).
Other times, the guard isn't the issue, but rather, the problem is
that a recursive call has an argument that itself is a recursive
call. For example, suppose that <rec-x> is of the form (foo
<expr>). There is no way we can hope to discharge the termination
proof obligation shown above. A standard solution is to add some
version of this test:
(mbt (o< (acl2-count <rec-x>) (acl2-count x)))
Here is a specific example based on one sent by Vernon Austel.
(defun recurX2 (n)
(declare (xargs :guard (and (integerp n) (<= 0 n))
:verify-guards nil))
(cond ((zp n) 0)
(t (let ((call (recurX2 (1- n))))
(if (mbt (< (acl2-count call) n))
(recurX2 call)
1 ;; this branch is never actually taken
)))))
(defthm recurX2-0
(equal (recurX2 n) 0))
(verify-guards recurX2)
If you ([trace$] acl2-count), you will see that evaluation of
(recurX2 2) causes several calls of [ACL2-count] before the
[verify-guards]. But this evaluation does not call acl2-count after
the verify-guards, because the ACL2 evaluation mechanism uses raw
Lisp to do the evaluation, and the form (mbt (< (acl2-count call)
n)) macroexpands to t in Common Lisp.
You may occasionally get warnings when you compile functions defined
using mbt. (For commands that invoke the compiler, see
[compilation].) These can be inhibited by using an ignorable
[declare] form. Here is a simple but illustrative example. Note
that the declarations can optionally be separated into two
[declare] forms.
(defun foo (x y)
(declare (ignorable x)
(xargs :guard (equal x t)))
(and (mbt x) y))")
(MBT*
(MBE ACL2-BUILT-INS)
"Introduce a guard proof obligation
The macro mbt* is a variant of mbt (``must be true''). However,
unlike mbt, the call (mbt* test) is equivalent simply to t for both
logic and evaluation. The only effective difference between (mbt*
test) and t is that (mbt* test) generates a [guard] proof
obligation (when used in a [logic]-mode definition) of test.
If you think that mbt* might be of use, please see [assert*], which
is defined using mbt* to create a [guard] proof obligation without
any logical or execution burden.")
(MEASURE
(POINTERS)
"See [xargs] for keyword :measure.
Subtopics
[Measure-debug]
Generate markers to indicate sources of [measure] proof obligations
[Termination-theorem]
Use a previously-proved measure theorem
[Termination-theorem-example]
How to use a previously-proved measure theorem
[Tthm]
The [measure] (termination) theorem for a given function symbol")
(MEASURE-DEBUG
(MEASURE DEBUGGING)
"Generate markers to indicate sources of [measure] proof obligations
When ACL2 is asked to accept a recursive (or mutually recursive)
function definition, it generates a goal often called the ``measure
conjecture.'' That goal can split into numerous goals, some of
which may not be theorems if the definition being processed has
bugs. This [documentation] topic explains a capability provided by
ACL2 to help find such bugs. For a similar utility appropriate for
[guard] verification, see [guard-debug].
We begin with the following simple, admittedly artificial, example.
(defun f (x)
(if (consp x)
(f (cons x x))
x))
ACL2 generates the following proof obligation..
(IMPLIES (CONSP X)
(O< (ACL2-COUNT (CONS X X))
(ACL2-COUNT X)))
In this simple example, it is obvious that ACL2 cannot prove the goal
because in fact, (CONS X X) does not have a smaller [ACL2-count]
than X, even assuming (CONSP X). But you can get ACL2 to show
explicitly the source of this proof obligation by specifying
:measure-debug t in an [xargs] [declare] form, as follows.
ACL2 !>(defun f (x)
(declare (xargs :measure-debug t))
(if (consp x)
(f (cons x x))
x))
For the admission of F we will use the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT X). The non-trivial part of the measure conjecture is
Goal
(IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F))
'(F (CONS X X)))
(CONSP X))
(O< (ACL2-COUNT (CONS X X))
(ACL2-COUNT X))).
The extra-info call is telling us the following about the measure
conjecture:
The appropriate well-founded relation (typically [o<]) holds between
appropriate terms, because of the indicated recursive call, (F
(CONS X X)).
We now describe the measure-debug utility in some detail.
(Extra-info x y) always returns t by definition. However, if the
measure conjecture takes place with a non-nil value for the [xargs]
keyword :measure-debug, then the goals generated will include
hypotheses that are calls of extra-info. Such a hypothesis has one
of the following forms.
(extra-info '(:MEASURE (:RELATION function-name))
'recursive-call)
(extra-info '(:MEASURE (:DOMAIN function-name))
'(D (M term)))
The first form says that the goal is to show that the measure
decreases for the indicated recursive call in the body of the
function named function-name. The second form says that the goal is
to show that the measure always returns a suitable value.
We illustrate with a slightly more elaborate, but still contrived,
example, which we hope clearly illustrates the points above. Notice
that :measure-debug t need only be specified for a single [defun]
form in a call of [mutual-recursion]. Also notice in the output
that when there is more than one source for a goal, each source is
indicated by its own call of extra-info.
ACL2 !>(defstub my-measure (x) t) ; for the contrived example below
[[ .. output omitted here .. ]]
ACL2 !>(mutual-recursion
(defun f1 (x)
(declare (xargs :measure (my-measure x) :measure-debug t))
(if (consp x)
(f2 (cons x (cdr x)))
t))
(defun f2 (x)
(declare (xargs :measure (my-measure x)))
(if (consp x)
(f1 (cons (make-list (car x)) (cdr x)))
nil)))
For the admission of F1 and F2 we will use the relation O< (which is
known to be well-founded on the domain recognized by O-P) and the measure
(MY-MEASURE X) for F1 and (MY-MEASURE X) for F2. The non-trivial part
of the measure conjecture is
Goal
(AND (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F1))
'(F2 (CONS X (CDR X))))
(CONSP X))
(O< (MY-MEASURE (CONS X (CDR X)))
(MY-MEASURE X)))
(IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F2))
'(F1 (CONS (MAKE-LIST-AC (CAR X) NIL NIL)
(CDR X))))
(CONSP X))
(O< (MY-MEASURE (CONS (MAKE-LIST-AC (CAR X) NIL NIL)
(CDR X)))
(MY-MEASURE X)))
(IMPLIES (AND (EXTRA-INFO '(:MEASURE (:DOMAIN F2))
'(O-P (MY-MEASURE X)))
(EXTRA-INFO '(:MEASURE (:DOMAIN F1))
'(O-P (MY-MEASURE X))))
(O-P (MY-MEASURE X)))).
All rules (see [rune]) associated with extra-info are [disable]d by
default, so that hypotheses of the form described above are not
simplified to t. These hypotheses are intended to ride along for
free: you can generally expect the proof to have the same structure
whether or not the :measure-debug option is supplied, though on
rare occasions the proofs may diverge.")
(MEASURE-THEOREM (POINTERS)
"See [termination-theorem].")
(MEMBER
(LISTS ACL2-BUILT-INS)
"Membership predicate
General Forms:
(member x lst)
(member x lst :test 'eql) ; same as above (eql as equality test)
(member x lst :test 'eq) ; same, but eq is equality test
(member x lst :test 'equal) ; same, but equal is equality test
(Member x lst) equals the longest tail of the list lst that begins
with x, or else nil if no such tail exists. The optional keyword,
:TEST, has no effect logically, but provides the test (default
[eql]) used for comparing x with successive elements of lst.
The [guard] for a call of member depends on the test. In all cases,
the second argument must satisfy [true-listp]. If the test is
[eql], then either the first argument must be suitable for [eql]
(see [eqlablep]) or the second argument must satisfy
[eqlable-listp]. If the test is [eq], then either the first
argument must be a symbol or the second argument must satisfy
[symbol-listp].
See [equality-variants] for a discussion of the relation between
member and its variants:
(member-eq x lst) is equivalent to (member x lst :test 'eq);
(member-equal x lst) is equivalent to (member x lst :test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function member-equal.
Member is defined by Common Lisp. See any Common Lisp documentation
for more information.
Function: <member-equal>
(defun member-equal (x lst)
(declare (xargs :guard (true-listp lst)))
(cond ((endp lst) nil)
((equal x (car lst)) lst)
(t (member-equal x (cdr lst)))))")
(MEMBER-EQ (POINTERS) "See [member].")
(MEMBER-EQUAL (POINTERS)
"See [member].")
(MEMOIZATION (POINTERS)
"See [memoize].")
(MEMOIZE
(PROGRAMMING HONS-AND-MEMOIZATION EVENTS)
"Turn on memoization for a specified function
See [hons-and-memoization] for a general discussion of the
``[hons-enabled]'' features: memoization, hash consing, and
applicative hash tables.
Examples:
(memoize 'foo) ; remember the values of calls
; of foo
(memoize 'foo :condition t) ; same as above
(memoize 'foo :condition '(test x)) ; memoize for args satisfying
; the given condition
(memoize 'foo :condition-fn 'test) ; memoize for args satisfying
; a call of the given function
(memoize 'foo :recursive nil) ; don't memoize recursive calls
(memoize 'foo :aokp t) ; attachments OK for stored results
(memoize 'foo :stats nil) ; don't collect info for (memsum)
(memoize 'foo :ideal-okp t) ; memoize for raw Lisp even if foo is
; in :logic but not guard-verified
General Form:
(memoize fn ; memoizes fn and returns fn
:condition condition ; optional (default t)
:condition-fn condition-fn ; optional
:hints hints ; optional, for verifying the
; guards of condition-fn
:otf-flg otf-flg ; optional, for verifying the
; guards of condition-fn
:recursive t/nil ; optional (default t)
:commutative t/lemma-name ; optional (default nil)
:forget t/nil ; optional (default nil)
:memo-table-init-size size ; optional (default *mht-default-size*)
:aokp t/nil ; optional (default nil)
:stats t/nil ; optional (default t)
:ideal-okp t/:warn/nil ; optional (default nil)
:verbose t/nil ; optional (default t)
)
where fn evaluates to a user-defined function symbol; condition is
either t (the default), 't, nil, or 'nil, or else evaluates to an
expression whose free variables are among the formal parameters of
fn; and condition-fn is either nil (the default) or else evaluates
to a legal function symbol. Further restrictions and options are
discussed below. Note that all arguments are evaluated (but for the
special handling of value t for :commutative, the argument must
literally be t; see below).
Generally fn must evaluate to a defined function symbol. However,
this value can be the name of a macro that is associated with such
a function symbol; see [macro-aliases-table]. That associated
function symbol is the one called ``memoized'' in the discussion
below, but we make no more mention of this subtlety.
In the most common case, memoize takes a single argument, which
evaluates to a function symbol. We call this function symbol the
``memoized function'' because ``memos'' are saved and re-used, in
the following sense. When a call of the memoized function is
evaluated, the result is ``memoized'' by associating the call's
arguments with that result, in a suitable table. But first an
attempt is made to avoid such evaluation, by doing a lookup in that
table on the given arguments for the result, as stored for a
previous call on those arguments. If such a result is found, then
it is returned without further computation. This paragraph also
applies if :condition is supplied but is t or 't.
If keyword argument :condition-fn is supplied, but :condition is not,
then the result of evaluating :condition-fn must be a defined
function symbol whose formal parameter list and [guard] are the
same as for the function being memoized. If fn is in :[logic] mode,
then [guard]s must have been verified for :condition-fn. Such a
``condition function'' will be run whenever the memoized function
is called, on the same parameters, and the lookup or table store
described above are only performed if the result from the condition
function call is non-nil.
Suppose however that :condition is supplied. If the value supplied is
t or 't, then the lookup and table store described above are always
done. If the value is nil or 'nil, then this lookup and table store
are never done, although statistics may be gathered; see [profile].
Now consider other values for :condition. An attempt will be made
to define a condition function whose [guard] and formal parameters
list are the same as those of the memoized function, and whose body
is the result, r, of evaluating the given condition. The name of
that condition function is the result of evaluating :condition-fn
if supplied, else is the result of concatenating the string
\"-MEMOIZE-CONDITION\" to the end of the name of the memoized
function. The condition function will be defined with [guard]
verification turned off, but that definition will be followed
immediately by a [verify-guards] event; and this is where the
optional :hints and :otf-flg are attached. At evaluation time the
condition function is used as described in the preceding paragraph;
so in effect, the condition (r, above) is evaluated, with its
variables bound to the corresponding actuals of the memoized
function call, and the memoized function attempts a lookup or table
store if and only if the result of that evaluation is non-nil.
Note that fn can be either a :[logic] mode function or a :[program]
mode function. However, only the corresponding raw Lisp function is
actually memoized, so [guard] violations can defeat memoization,
and :[logic] mode functions without their [guard]s verified will
only be memoized when called by :[program] mode functions. (See
[guards-and-evaluation] for more information about guards and
evaluation in ACL2.) If fn is a :[logic] mode function and
:condition is supplied and not t or nil, then the condition must be
a [guard]-verified function.
Calls of this macro generate events of the form (table memoize-table
fn ((:condition-fn fn) ...)). When successful, the returned value
is of the form (mv nil function-symbol state).
Suppose that a function is already memoized. Then it is illegal to
memoize that function. Moreover, if the function was memoized with
an associated condition (i.e., was memoized with keyword :condition
or :condition-fn having value other than t or nil), then it is also
illegal to convert the function from :[program] to :[logic] mode
(see [verify-termination]). To turn off memoization, see
[unmemoize].
Memoize is illegal for a function if its arguments include [state] or
if it returns any [stobj]s. A stobj can be an input of a memoized
function, but in that case, the memoization table for that stobj
will be cleared every time that stobj is updated.
By default, memoize does not store results when any attachments have
been used (see [defattach]). However, such results are stored when
memoize keyword parameter :aokp has value t. Note that for purposes
of this discussion, the use of a stored value for a subsidiary
function that was memoized with :aokp t is treated as the use of an
attachment, since ACL2 does not know whether or not an attachment
was actually used in that case.
We conclude with by documenting keyword parameters not discussed
above.
Keyword parameter :recursive is t by default, which means that
recursive calls of fn will be memoized just as ``top-level'' calls
of fn. When :recursive is instead set to nil, memoization is only
done at the top level. Using :recursive nil is similar to writing a
wrapper function that just calls fn, and memoizing the wrapper
instead of fn.
If :trace has a non-nil value, then memoize also traces in a
traditional Lisp style. If :trace has value notinline or notinline,
then a corresponding declaration is added at the beginning of the
new definition of fn.
A non-nil value for :commutative can be supplied if fn is a binary
function in :logic mode. Suppose that the memoize event is
successful, and consider a subsequent call of fn for which some
argument to fn is either a rational number or, in some host Lisps
(currently either CCL, or GCL Version 2.6.12 or later) a [hons].
(Indeed, for such GCL versions this is true for any cons, not just
a hons.) Then when the evaluation of fn on those arguments is
memoized, the evaluation of fn on the swap of those arguments is,
in essence, also memoized. If :commutative is supplied and is not
nil or t, then it should be the name of a previously-proved theorem
whose formula states the commutativity of fn, i.e., is the formula
(equal (fn x y) (fn y x)) for a pair {x,y} of distinct variables.
If :commutative is t --- but not merely an expression that
evaluates to t --- then an attempt to prove such a lemma will be
made on-the-fly. The name of the lemma is the symbol in the same
package as fn, obtained by adding the suffix \"-COMMUTATIVE\" to the
[symbol-name] of fn. If the proof attempt fails, then you may want
first to prove the lemma yourself with appropriate hints and
perhaps supporting lemmas, and then supply the name of that lemma
as the value of :commutative.
If :commutative is supplied, and a non-commutative condition is
provided by :condition or :condition-fn, then although the results
will be correct, the extra memoization afforded by :commutative is
unspecified.
If :memo-table-init-size is supplied, then it should be a positive
integer specifying the initial size of an associated hash table.
Argument :aokp is relevant only when attachments are used; see
[defattach] for background on attachments. When :aokp is nil, the
default, computed values are not stored when an attachment was
used, or even when an attachment may have been used because a
function was called that had been memoized using :aokp t.
Otherwise, computed values are always stored, but saved values are
not used except when attachments are allowed. To summarize:
aokp=nil (default): ``Pure'', i.e., values do not depend on attachments
- Fetch: always legal
- Store: only store resulting value when attachments were not used
aokp=t: ``Impure'', i.e., values may depend on attachments
- Fetch: only legal when attachments are allowed (e.g., not during proofs)
- Store: always legal
The default value for :stats is essentially t. (Technically, this can
be subverted by using raw Lisp, to change the default by changing
the values of variables *record-xxx* introduced in ACL2 source file
memoize-raw.lisp.) When :stats has its default value (assuming the
above raw Lisp changes are not made) or value t, calls of memoized
functions will collect information that can be displayed by calling
[memsum]. But if :stats is nil, this information will not be
collected, possibly resulting in better performance for the
memoized function. As of this writing, built-in memoized functions
use :stats nil to benefit performance.
If :ideal-okp is supplied and not nil, then it is permitted to
memoize an ``ideal-mode'' function: one in :[logic] mode whose
[guard]s have not been verified. However, this might not have the
effect you desire, because you will be memoizing the raw Lisp
version of the function, not the safe (so-called ``*1*'') function
that is executed in the ACL2 loop and on behalf of the prover.
Thus, if you memoize an ideal-mode function and then call it at the
top-level of the ACL2 loop (or, for example, it is called to
evaluate a ground term arising in a proof or in the evaluation of a
[meta]function in a proof), the effects of memoization will not be
felt because the raw Lisp code is not run unless guards are
verified.
There are circumstances in which the raw Lisp code of an ideal-mode
function is called. For example, if the ideal-mode function is
called by a :[program] mode function, evaluation can transfer to
raw Lisp where the effects of memoization will be felt.
A trick, described below, with [ec-call] can provide some of the
benefit of memoizing an ideal-mode function. The trick exploits the
fact that ec-call allows you to call an ideal-mode function within
a [guard]-verified (``Common Lisp compliant'') :[logic] mode
function without having to verify guards for the ideal-mode
function. The following edited log illustrates the points above.
ACL2 !>(defun fib (n)
(declare (xargs :guard (natp n) :verify-guards nil))
(if (zp n)
0
(if (eql n 1)
1
(+ (fib (- n 1)) (fib (- n 2))))))
[[ .. output omitted .. ]]
FIB
ACL2 !>(memoize 'fib :ideal-okp t)
[[ .. output omitted .. ]]
FIB
ACL2 !>(time$ (fib 38)) ; slow, since *1*fib never calls fib
ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited
on recursive calls of the executable counterpart (i.e., in the ACL2
logic) of FIB. To check guards on all recursive calls:
(set-guard-checking :all)
To leave behavior unchanged except for inhibiting this message:
(set-guard-checking :nowarn)
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 3.91 seconds realtime, 3.90 seconds runtime
; (416 bytes allocated).
39088169
ACL2 !>(time$ (fib 38)) ; still slow; no results were stored before
ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited
on recursive calls of the executable counterpart (i.e., in the ACL2
logic) of FIB. To check guards on all recursive calls:
(set-guard-checking :all)
To leave behavior unchanged except for inhibiting this message:
(set-guard-checking :nowarn)
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 3.92 seconds realtime, 3.91 seconds runtime
; (416 bytes allocated).
39088169
ACL2 !>(defun fib-logic-wrapper (n) ; guard-verified
(declare (xargs :guard (natp n)))
(ec-call (fib n)))
[[ .. output omitted .. ]]
FIB-LOGIC-WRAPPER
ACL2 !>(memoize 'fib-logic-wrapper)
[[ .. output omitted .. ]]
FIB-LOGIC-WRAPPER
ACL2 !>(time$ (fib-logic-wrapper 38)) ; slow; no fib results are stored
ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited
on recursive calls of the executable counterpart (i.e., in the ACL2
logic) of FIB. To check guards on all recursive calls:
(set-guard-checking :all)
To leave behavior unchanged except for inhibiting this message:
(set-guard-checking :nowarn)
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 3.92 seconds realtime, 3.91 seconds runtime
; (2,128 bytes allocated).
39088169
ACL2 !>(time$ (fib-logic-wrapper 38)) ; fast; fib-logic-wrapper result was stored
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 0.00 seconds realtime, 0.00 seconds runtime
; (16 bytes allocated).
39088169
ACL2 !>(time$ (fib-logic-wrapper 37)) ; slow; result only for 38 was stored
ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited
on recursive calls of the executable counterpart (i.e., in the ACL2
logic) of FIB. To check guards on all recursive calls:
(set-guard-checking :all)
To leave behavior unchanged except for inhibiting this message:
(set-guard-checking :nowarn)
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 2.42 seconds realtime, 2.42 seconds runtime
; (416 bytes allocated).
24157817
ACL2 !>(defun fib-program-wrapper (n) ; program mode function
(declare (xargs :guard (natp n) :mode :program))
(fib n))
Summary
Form: ( DEFUN FIB-PROGRAM-WRAPPER ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FIB-PROGRAM-WRAPPER
ACL2 !>(time$ (fib-program-wrapper 100)) ; fast because raw-Lisp fib is called
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 0.00 seconds realtime, 0.00 seconds runtime
; (7,600 bytes allocated).
354224848179261915075
ACL2 !>
Two non-nil values are allowed for keyword parameter :ideal-okp:
:warn and t. Both of these values allow memoization of ideal-mode
functions, but if :warn is supplied then a warning will take place
at memoization time, specifically for the resluting [table] event.
Note that you may set the key :memoize-ideal-okp of the
[ACL2-defaults-table] to value t or :warn to change the default,
but if parameter :ideal-okp is supplied, the [ACL2-defaults-table]
value is ignored.
If :verbose is supplied, it should either be nil, which will inhibit
proof, event, and summary output (see [with-output]), or else t
(the default), which does not inhibit output. If the output baffles
you, try
:trans1 (memoize ...)
to see the single-step macroexpansion of your memoize call.
The default for :forget is nil. If :forget is supplied, and not nil,
then it must be t, which causes all memoization done for a
top-level call of fn to be forgotten when that top-level call
exits.
Subtopics
[Clear-hash-tables]
Deprecated feature
[Clear-memoize-statistics]
Clears all profiling info displayed by ([memoize-summary])
[Clear-memoize-table]
Forget values remembered for the given function
[Clear-memoize-tables]
Forget values remembered for all the memoized functions
[Memoize-summary]
Display all collected profiling and memoization info
[Memsum]
Display all collected profiling and memoization info
[Never-memoize]
Mark a function as unsafe to memoize.
[Protect-memoize-statistics]
Ensure the integrity of memoization statistics even upon aborts
[Restore-memoization-settings]
Restore the saved memoization settings
[Save-and-clear-memoization-settings]
Save and remove the current memoization settings
[Unmemoize]
Turn off memoization for the specified function")
(MEMOIZE-SUMMARY
(MEMOIZE)
"Display all collected profiling and memoization info
Logically, this function just returns nil, but it displays profiling
and memoization table information. The profiling statistics may be
cleared with ([clear-memoize-statistics]).
Note that by default, statistics might be inaccurate when calls of
[memoize]d functions are aborted. This issue can be avoided,
however; see [protect-memoize-statistics].
Function: <memoize-summary>
(defun memoize-summary
nil (declare (xargs :guard t))
nil)")
(MEMSUM
(MEMOIZE)
"Display all collected profiling and memoization info
This macro is an abbreviation for [memoize-summary]. Logically, it
just returns nil. Also see [protect-memoize-statistics].")
(META
(RULE-CLASSES)
"Make a :meta rule (a hand-written simplifier)
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Meta rules extend the ACL2 simplifier with hand-written code to
transform certain terms to equivalent ones. To add a meta rule, the
:[corollary] formula must establish that the hand-written
``metafunction'' preserves the meaning of the transformed term.
Examples:
(defthm fn-correct-1 ; Modify the rewriter to use fn to
(equal (evl x a) ; transform terms that are calls of
(evl (fn x) a)) ; nth or of foo.
:rule-classes ((:meta :trigger-fns (nth foo))))
(defthm fn-correct-2 ; As above, but this illustrates
(implies (and (pseudo-termp x) ; that without loss of generality we
(alistp a)) ; may restrict x to be shaped like a
(equal (evl x a) ; term and a to be an alist.
(evl (fn x) a)))
:rule-classes ((:meta :trigger-fns (nth foo))))
(defthm fn-correct-3 ; As above (with or without the
(implies (and (pseudo-termp x) ; hypotheses on x and a), with the
(alistp a) ; additional restriction that the
(evl (hyp-fn x) a)) ; meaning of (hyp-fn x) is true in
(equal (evl x a) ; the current context. That is, the
(evl (fn x) a))) ; applicability of the transformation
:rule-classes ; may be dependent upon some computed
((:meta :trigger-fns (nth foo)))) ; hypotheses.
While our intention is that the set of ACL2 documentation topics is
self-contained, readers might find it useful to see the following
paper for an introduction to meta reasoning in ACL2.
W. A. Hunt, Jr., R. B. Krug, M. Kaufmann, J S. Moore and E. W. Smith,
``Meta Reasoning in ACL2.'' TPHOLs 2005, ed. J. Hurd and T. F.
Melham, LNCS 3603, Springer-Verlag, Berlin, 2005, pp. 163-178.
A non-nil list of function symbols must be supplied as the value of
the :trigger-fns field in a :meta rule class object (except that a
macro alias can stand in for a function symbol; see
[add-macro-alias]).
General Forms:
(implies (and (pseudo-termp x) ; this hyp is optional
(alistp a) ; this hyp is optional
(ev (hyp-fn x ...) a) ; this hyp is optional
; meta-extract hyps may also be included (see below)
)
(equiv (ev x a)
(ev (fn x ...) a)))
where equiv is a known [equivalence] relation, x and a are distinct
variable names, and ev is an evaluator function (see below), and fn
is a function symbol, as is hyp-fn when provided. The arguments to
fn and hyp-fn should be identical. In the most common case, both
take a single argument, x, which denotes the term to be simplified.
If fn and/or hyp-fn are [guard]ed, their [guard]s should be
trivially implied by [pseudo-termp]. We say the theorem above is a
``metatheorem'' or ``metalemma'' and fn is a ``metafunction'', and
hyp-fn is a ``hypothesis metafunction''.
If ``...'' is empty, i.e., the metafunctions take just one argument,
we say they are ``vanilla flavored.'' If ``...'' is non-empty, we
say the metafunctions are ``extended.'' Extended metafunctions can
access [state] and context sensitive information to compute their
results, within certain limits. We discuss vanilla metafunctions
here and recommend a thorough understanding of them before
proceeding (at which time see [extended-metafunctions]).
If a metafunction application to a term, u, evaluates to a result of
the form (if TEST NEW-TERM u), then TEST is treated as an
``implicit hypothesis''. For discussion of this relatively advanced
feature, see [meta-implicit-hypothesis].
Additional hypotheses are supported, called ``meta-extract
hypotheses''. These allow metafunctions to depend on the validity
of certain terms extracted from the context or the logical [world].
These hypotheses provide a relatively advanced form of metatheorem
so we explain them elsewhere; see [meta-extract].
One might think that metafunctions and (if supplied) hypothesis
metafunctions must be executable: that is, not constrained (i.e.,
introduced in the [signature] of [encapsulate] [events]), and not
[declare]d :[non-executable]. After all, there is no point in
installing a simplifier that cannot be run! However, such a
restriction is not enforced, because one could introduce a
metafunction using [encapsulate] and then use [defattach] to attach
it to an executable function; see [defattach].
We defer discussion of the case in which there is a hypothesis
metafunction and for now address the case in which the other two
hypotheses are present.
In the discussion below, we refer to the argument, x, of fn and
hyp-fn as a ``(translated) term,'' i.e., an object satisfying the
ACL2 built-in predicate termp. When these metafunctions are
executed by the simplifier, they will be applied to (the quotations
of) terms. But during the proof of the metatheorem itself, x may
not be the quotation of a term. If the [pseudo-termp] hypothesis is
omitted, x may be any object. Even with the [pseudo-termp]
hypothesis, x may merely ``look like a term'' but use non-function
symbols or function symbols of incorrect arity. In any case, the
metatheorem is stronger than necessary to allow us to apply the
metafunctions to terms, as we do in the discussion below. We return
later to the question of proving the metatheorem.
Suppose the general form of the metatheorem above is proved with the
[pseudo-termp] and [alistp] hypotheses. Then when the simplifier
encounters a term, (h t1 ... tn), that begins with a function
symbol, h, listed in :trigger-fns, it applies the metafunction, fn,
to the quotation of the term, i.e., it evaluates (fn '(h t1 ...
tn)) to obtain some result, which can be written as 'val. If 'val
is different from '(h t1 ... tn) and val is a well-formed term (see
the next paragraph), then (h t1 ... tn) is replaced by val, which
is then passed along for further rewriting. Because the metatheorem
establishes the correctness of fn for all terms (even non-terms!),
there is no restriction on which function symbols are listed in the
:trigger-fns. Generally, of course, they should be the symbols that
head up the terms simplified by the metafunction fn.
Note that the result of applying a metafunction (or a hypothesis
metafunction) must be a term, i.e., must satisfy the predicate
[termp] in the current logical [world]. If not, then an error
occurs. See [term-table] for how one obtains some assistance
towards testing that val is indeed a term. ACL2 actually enforces a
stronger requirement, disallowing calls of certain ``forbidden''
function symbols as described in [set-skip-meta-termp-checks]. Both
of these runtime checks can be avoided by proving that the
metafunction (and the corresponding hypothesis metafunction, if
any) always produces an acceptable term. See
[well-formedness-guarantee]. Alternatively, with an active trust
tag (see [defttag]) you can tell ACL2 to skip these tests; see
[set-skip-meta-termp-checks].
The ``evaluator'' function, ev, is a function that can evaluate a
certain class of expressions, namely, all of those composed of
variables, constants, and applications of a fixed, finite set of
function symbols, g1, ..., gk. Generally speaking, the set of
function symbols handled by ev is chosen to be exactly the function
symbols recognized and manipulated by the metafunctions being
introduced. For example, if fn manipulates expressions in which
'[equal] and '[binary-append] occur as function symbols, then ev is
generally specified to handle [equal] and [binary-append]. The
actual requirements on ev become clear when the metatheorem is
proved. The standard way to introduce an evaluator is to use the
ACL2 macro [defevaluator], though this is not strictly necessary.
See [defevaluator] if you want details.
[Aside for the logic-minded.] Why are we justified in using
metafunctions this way? Suppose (fn 'term1) is 'term2. What
justifies replacing term1 by term2? The first step is to assert
that term1 is (ev 'term1 a), where a is an alist that maps 'var to
var, for each variable var in term1. This step is incorrect,
because 'term1 may contain function symbols other than the ones,
g1, ..., gk, that ev knows how to handle. But we can grow ev to a
``larger'' evaluator, ev*, an evaluator for all of the symbols that
occur in term1 or term2. We can prove that ev* satisfies the
[constraint]s on ev, provided no [defaxiom] events are adding
constraints to ev (or callers of ev, and recursively); ACL2 checks
this additional property. Hence, the metatheorem holds for ev* in
place of ev, by functional instantiation. We can then carry out the
proof of the [equivalence] of term1 and term2 as follows: Fix a to
be an alist that maps the quotations of the variables of term1 and
term2 to themselves. Then,
term1 = (ev* 'term1 a) ; (1) by construction of ev* and a
= (ev* (fn 'term1) a) ; (2) by the metatheorem for ev*
= (ev* 'term2 a) ; (3) by evaluation of fn
= term2 ; (4) by construction of ev* and a
Note that in line (2) above, where we appeal to the (functional
instantiation of the) metatheorem, we can relieve its (optional)
[pseudo-termp] and [alistp] hypotheses by appealing to the facts
that term1 is a term and a is an alist by construction. [End of
Aside for the logic-minded.]
There are subtleties related to the notion of ``growing'' ev to a
``larger'' evaluator, as mentioned in the paragraph just above. For
corresponding restrictions on :meta rules, see
[evaluator-restrictions].
Finally, we turn to the second case, in which there is a hypothesis
metafunction. In that case, consider as before what happens when
the simplifier encounters a term, (h t1 ... tn), where h is listed
in :trigger-fns. This time, after it applies fn to '(h t1 ... tn)
to obtain the quotation of some new term, 'val, it then applies the
hypothesis metafunction, hyp-fn. That is, it evaluates (hyp-fn '(h
t1 ... tn)) to obtain some result, which can be written as
'hyp-val. If hyp-val is not in fact a term, the metafunction is not
used. Provided hyp-val is a term, the simplifier attempts to
establish (by conventional backchaining) that this term is non-nil
in the current context. Note that this backchaining is done just as
it is done for hypotheses of [rewrite] (and [linear]) rules,
namely, by rewriting with special attention to calls of certain
functions including [force], [case-split], [syntaxp], and
[bind-free]. If this attempt to establish this term fails, then the
meta rule is not applied. Otherwise, (h t1...tn) is replaced by val
as in the previous case (where there was no hypothesis
metafunction).
Why is it justified to make this extension to the case of hypothesis
metafunctions? First, note that the rule
(implies (and (pseudo-termp x)
(alistp a)
(ev (hyp-fn x) a))
(equal (ev x a)
(ev (fn x) a)))
is logically equivalent to the rule
(implies (and (pseudo-termp x)
(alistp a))
(equal (ev x a)
(ev (new-fn x) a)))
where (new-fn x) is defined to be (list 'if (hyp-fn x) (fn x) x). (If
we're careful, we realize that this argument depends on making an
extension of ev to an evaluator ev* that handles [if] and the
functions manipulated by hyp-fn.) If we write 'term for the
quotation of the present term, and if (hyp-fn 'term) and (fn 'term)
are both terms, say hyp1 and term1, then by the previous argument
we know it is sound to rewrite term to (if hyp1 term1 term). But
since we have established in the current context that hyp1 is
non-nil, we may simplify (if hyp1 term1 term) to term1, as desired.
We now discuss the role of the [pseudo-termp] hypothesis.
(Pseudo-termp x) checks that x has the shape of a term. Roughly
speaking, it ensures that x is a symbol, a quoted constant, or a
true list consisting of a lambda expression or symbol followed by
some pseudo-terms. Among the properties of terms not checked by
[pseudo-termp] are that variable symbols never begin with
ampersand, lambda expressions are closed, and function symbols are
applied to the correct number of arguments. See [pseudo-termp].
There are two possible roles for [pseudo-termp] in the development of
a metatheorem: it may be used as the [guard] of the metafunction
and/or hypothesis metafunction and it may be used as a hypothesis
of the metatheorem. Generally speaking, the [pseudo-termp]
hypothesis is included in a metatheorem only if it makes it easier
to prove. The choice is yours. (An extreme example of this is when
the metatheorem is invalid without the hypothesis!) We therefore
address ourselves the question: should a metafunction have a
[pseudo-termp] [guard]? A [pseudo-termp] [guard] for a
metafunction, in connection with other considerations described
below, improves the efficiency with which the metafunction is used
by the simplifier.
To make a metafunction maximally efficient you should (a) provide it
with a [pseudo-termp] [guard] and exploit the [guard] when possible
in coding the body of the function (see [guards-and-evaluation],
especially the section on efficiency issues), (b) verify the
[guard]s of the metafunction (see [verify-guards]), and (c) compile
the metafunction (see [comp]). When these three steps have been
taken the simplifier can evaluate (fn 'term1) by running the
compiled ``primary code'' (see [guards-and-evaluation]) for fn
directly in Common Lisp. (Note however that explicit compilation
may be suppressed; see [compilation].)
Before discussing efficiency issues further, let us review for a
moment the general case in which we wish to evaluate (fn 'obj) for
some :[logic] function. We must first ask whether the [guard]s of
fn have been verified. If not, we must evaluate fn by executing its
logic definition. This effectively checks the [guard]s of every
subroutine and so can be slow. If, on the other hand, the [guard]s
of fn have been verified, then we can run the primary code for fn,
provided 'obj satisfies the [guard] of fn. So we must next evaluate
the [guard] of fn on 'obj. If the [guard] is met, then we run the
primary code for fn, otherwise we run the logic code.
Now in the case of a metafunction for which the three steps above
have been followed, we know the [guard] is (implied by)
[pseudo-termp] and that it has been verified. Furthermore, we know
without checking that the [guard] is met (because term1 is a term
and hence 'term1 is a [pseudo-termp]). Hence, we can use the
compiled primary code directly.
We strongly recommend that you compile your metafunctions, as well as
all their subroutines (unless explicit compilation is suppressed;
see [compilation]). Guard verification is also recommended.
Finally, we present a very simple example of the use of :meta rules,
based on one provided by Robert Krug. This example illustrates a
trick for avoiding undesired rewriting after applying a
metafunction or any other form of rewriting. To elaborate: in
general, the term t2 obtained by applying a metafunction to a term
t1 is then handed immediately to the rewriter, which descends
recursively through the arguments of function calls to rewrite t2
completely. But if t2 shares a lot of structure with t1, then it
might not be worthwhile to rewrite t2 immediately. (A rewrite of t2
will occur anyhow the next time a goal is generated.) The trick
involves avoiding this rewrite by wrapping t2 inside a call of
[hide], which in turn is inside a call of a user-defined
``unhiding'' function, unhide.
(defun unhide (x)
(declare (xargs :guard t))
x)
(defthm unhide-hide
(equal (unhide (hide x))
x)
:hints ((\"Goal\" :expand ((hide x)))))
(in-theory (disable unhide))
(defun my-plus (x y)
(+ x y))
(in-theory (disable my-plus))
(defevaluator evl evl-list
((my-plus x y)
(binary-+ x y)
(unhide x)
(hide x)))
(defun meta-fn (term)
(declare (xargs :guard (pseudo-termp term)))
(if (and (consp term)
(equal (length term) 3)
(equal (car term) 'my-plus))
`(UNHIDE (HIDE (BINARY-+ ,(cadr term) ,(caddr term))))
term))
(defthm my-meta-lemma
(equal (evl term a)
(evl (meta-fn term) a))
:hints ((\"Goal\" :in-theory (enable my-plus)))
:rule-classes ((:meta :trigger-fns (my-plus))))
Notice that in the following (silly) conjecture, ACL2 initially does
only does the simplification directed by the metafunction; a second
goal is generated before the commuativity of addition can be
applied. If the above calls of UNHIDE and HIDE had been stripped
off, then Goal' would have been the term printed in Goal'' below.
ACL2 !>(thm
(equal (my-plus b a)
ccc))
This simplifies, using the :meta rule MY-META-LEMMA and the :rewrite
rule UNHIDE-HIDE, to
Goal'
(EQUAL (+ B A) CCC).
This simplifies, using the :rewrite rule COMMUTATIVITY-OF-+, to
Goal''
(EQUAL (+ A B) CCC).
The discussion above probably suffices to make good use of this
(UNHIDE (HIDE ...)) trick. However, we invite the reader who wishes
to understand the trick in depth to evaluate the following form
before submitting the [thm] form above.
(trace$ (rewrite :entry (list (take 2 arglist))
:exit (list (car values)))
(rewrite-with-lemma :entry (list (take 2 arglist))
:exit (take 2 values)))
The following annotated subset of the trace output (which may appear
a bit different depending on the underlying Common Lisp
implementation) explains how the trick works.
2> (REWRITE ((MY-PLUS B A) NIL))>
3> (REWRITE-WITH-LEMMA
((MY-PLUS B A)
(REWRITE-RULE (:META MY-META-LEMMA)
1822
NIL EQUAL META-FN NIL META NIL NIL)))>
We apply the meta rule, then recursively rewrite the result, which is the
(UNHIDE (HIDE ...)) term shown just below.
4> (REWRITE ((UNHIDE (HIDE (BINARY-+ B A)))
((A . A) (B . B))))>
5> (REWRITE ((HIDE (BINARY-+ B A))
((A . A) (B . B))))>
The HIDE protects its argument from being touched by the rewriter.
<5 (REWRITE (HIDE (BINARY-+ B A)))>
5> (REWRITE-WITH-LEMMA
((UNHIDE (HIDE (BINARY-+ B A)))
(REWRITE-RULE (:REWRITE UNHIDE-HIDE)
1806 NIL EQUAL (UNHIDE (HIDE X))
X ABBREVIATION NIL NIL)))>
Now we apply UNHIDE-HIDE, then recursively rewrite its right-hand
side in an environment where X is bound to (BINARY-+ B A).
6> (REWRITE (X ((X BINARY-+ B A))))>
Notice that at this point X is cached, so REWRITE just returns
(BINARY-+ B A).
<6 (REWRITE (BINARY-+ B A))>
<5 (REWRITE-WITH-LEMMA T (BINARY-+ B A))>
<4 (REWRITE (BINARY-+ B A))>
<3 (REWRITE-WITH-LEMMA T (BINARY-+ B A))>
<2 (REWRITE (BINARY-+ B A))>
Subtopics
[Backchain-limit]
Limiting the effort expended on relieving hypotheses
[Case-split]
Like force but immediately splits the top-level goal on the
hypothesis
[Evaluator-restrictions]
Some restrictions on the use of evaluators in meta-level rules
[Extended-metafunctions]
State and context sensitive metafunctions
[Force]
Identity function used to force a hypothesis
[Meta-extract]
Meta reasoning using valid terms extracted from context or [world]
[Meta-implicit-hypothesis]
A potentially more efficient way of coding a hypothesis metafunction
[Set-skip-meta-termp-checks]
Skip output checks for [meta] functions and [clause-processor]s
[Set-skip-meta-termp-checks!]
Skip output checks non-[local]ly for [meta] functions and
[clause-processor]s
[Syntaxp]
Attach a heuristic filter on a rule
[Term-table]
A table used to validate meta rules")
(META-EXTRACT
(META)
"Meta reasoning using valid terms extracted from context or [world]
For this advanced topic, we assume familiarity with metatheorems and
metafunctions (see [meta]), as well as extended metafunctions (see
[extended-metafunctions]). The capability described here ---
so-called ``meta-extract hypotheses'' for a :[meta] or a
:[clause-processor] rule --- provides an advanced form of
meta-level reasoning that was initially designed largely by Sol
Swords, who also provided a preliminary implementation.
A meta rule or clause-processor rule may have so-called
``meta-extract'' hypotheses that take forms displayed below. Here
evl is the evaluator, obj is an arbitrary term, mfc is the
metafunction context (which is a variable other than the symbol
STATE that represents the metafunction context; see
[extended-metafunctions]), state is literally the symbol STATE, a
is the second argument of evl in both arguments of the conclusion
of the rule, and aa is an arbitrary term.
(evl (meta-extract-contextual-fact obj mfc state) a)
(evl (meta-extract-global-fact obj state) aa)) ; equivalent to the next form
(evl (meta-extract-global-fact+ obj state state) aa)
(evl (meta-extract-global-fact+ obj st state) aa)
The first form is only legal for :meta rules for which the
metafunction is an extended metafunction. The remaining forms are
legal for both :meta rules and :clause-processor rules.
Sol Swords has contributed a community book,
clause-processors/meta-extract-user.lisp, that uses a Skolemization
trick to allow one to use at most one meta-extract-global-fact+
hypothesis and at most one meta-extract-contextual-fact hypothesis.
These additional hypotheses may be necessary in order to prove a
proposed metatheorem or (for the second type of hypothesis above)
clause-processor rule, in particular when the correctness of the
metafunction depends on the correctness of utilities extracting
formulas from the logical [world] or (for the first type) facts
from the metafunction context (mfc). After the rule is proved,
however, the meta-extract hypotheses have no effect on how the rule
is applied during a proof. An argument for correctness of using
meta-extract hypotheses is given in the ACL2 source code within a
comment entitled ``Essay on Correctness of Meta Reasoning''. In the
documentation below, we focus primarily on :[meta] rules, since the
use of meta-extract-global-fact hypotheses in :[clause-processor]
rules is entirely analogous. (At the end, though, we discuss the
last of the four forms displayed above.) And for :meta rules we
focus not on the application of rules but, rather, on how the use
of meta-extract hypotheses allow you to prove correctness of
metafunctions that use facts from the logical [world] or the
metafunction context (mfc).
Below we describe properties of meta-extract-contextual-fact and
meta-extract-global-fact, but only after we illustrate their
utility with an example. But even before we present that example,
we first give a sense of how to think about these functions by
showing a theorem that one can prove about the first of them. If
this snippet doesn't help your intuition, then just skip over it
and start with the example.
(defevaluator evl evl-list
((binary-+ x y) (typespec-check x y)))
(thm (implies
(not (bad-atom (cdr (assoc-equal 'x alist))))
(equal (evl (meta-extract-contextual-fact (list :typeset 'x)
mfc
state)
alist)
(not (equal 0 ; indicates non-empty intersection
(logand (type-set-quote ; type-set of a constant
(cdr (assoc-equal 'x alist)))
(mfc-ts-fn 'x mfc state nil)))))))
The following example comes from the community book,
books/clause-processors/meta-extract-simple-test.lisp (after it
defines the evaluator), which presents very basic (and contrived)
examples that nevertheless illustrate meta-extract hypotheses.
(defthm plus-identity-2-meta
(implies (and (nthmeta-ev (meta-extract-global-fact '(:formula bar-posp)
state)
(list (cons 'u
(nthmeta-ev (cadr (cadr term))
a))))
(nthmeta-ev (meta-extract-contextual-fact
`(:typeset ,(caddr term)) mfc state)
a))
(equal (nthmeta-ev term a)
(nthmeta-ev (plus-identity-2-metafn term mfc state) a)))
:rule-classes ((:meta :trigger-fns (binary-+))))
The two hypotheses illustratate the two basic kinds of meta-extract
hypotheses: applications of the evaluator to a call of
meta-extract-global-fact and to a call of
meta-extract-contextual-fact. Here is the definition of the
metafunction used in the above rule, slightly simplified here from
what is found in the above book (but adequate for proving the two
events that follow it in the above book).
(defun plus-identity-2-metafn (term mfc state)
(declare (xargs :stobjs state :verify-guards nil))
(case-match term
(('binary-+ ('bar &) y)
(cond
((equal (meta-extract-formula 'bar-posp state)
'(POSP (BAR U)))
(if (ts= (mfc-ts y mfc state :forcep nil)
*ts-character*)
(cadr term)
term))
(t term)))
(& term)))
This metafunction returns its input term unchanged except in the case
that the term is of the form (binary-+ (bar x) y) and the following
two conditions are met, in which case it returns (bar x).
(1) (equal (meta-extract-formula 'bar-posp state)
'(POSP (BAR U)))
(2) (ts= (mfc-ts y mfc state :forcep nil)
*ts-character*)
So suppose that term is (list 'binary-+ (list 'bar x) y). We show how
the meta-extract hypotheses together with (1) and (2) imply that
the conclusion of the above :meta rule holds. Here is that
conclusion after a bit of simplification.
(equal (nthmeta-ev (list 'binary-+ (list 'bar x) y) a)
(nthmeta-ev (list 'bar x) a))
This equality simplifies as follows using the evaluator properties of
nthmeta-ev.
(equal (binary-+ (bar (nthmeta-ev x a))
(nthmeta-ev y a))
(bar (nthmeta-ev x a)))
Since a positive number plus a character is that number, it clearly
suffices to show:
(A) (posp (bar (nthmeta-ev x a)))
(B) (characterp (nthmeta-ev y a))
It remains then to show that these follow from (1) and (2) together
with the meta-extract hypotheses.
First consider (A). We show that it is just a simplification of the
first meta-extract hypothesis.
(nthmeta-ev (meta-extract-global-fact '(:formula bar-posp)
state)
(list (cons 'u
(nthmeta-ev (cadr (cadr term))
a))))
= {by our assumption that term is (list 'binary-+ (list 'bar x) y)}
(nthmeta-ev (meta-extract-global-fact '(:formula bar-posp)
state)
(list (cons 'u
(nthmeta-ev x a))))
= {by definition of meta-extract-global-fact, as discussed later}
(nthmeta-ev (meta-extract-formula 'bar-posp state)
(list (cons 'u
(nthmeta-ev x a))))
= {by (1)}
(nthmeta-ev '(posp (bar u))
(list (cons 'u
(nthmeta-ev x a))))
= {by evaluator properties of nthmeta-ev}
(posp (bar (nthmeta-ev x a)))
Now consider (B). We show that it is just a simplification of the
second meta-extract hypothesis.
(nthmeta-ev (meta-extract-contextual-fact
`(:typeset ,(caddr term)) mfc state)
a)
= {by our assumption that term is (list 'binary-+ (list 'bar x) y)}
(nthmeta-ev (meta-extract-contextual-fact (list ':typeset y) mfc state)
a)
= {by definition of meta-extract-contextual-fact, as discussed later}
(nthmeta-ev (list 'typespec-check
(list 'quote
(mfc-ts y mfc state :forcep nil))
y)
a)
= {by (2)}
(nthmeta-ev (list 'typespec-check
(list 'quote *ts-character*)
y)
a)
= {by evaluator properties of nthmeta-ev}
(typespec-check *ts-character* (nthmeta-ev y a))
= {by definition of typespec-check}
(characterp (nthmeta-ev y a))
Note the use of :forcep nil above. All of the mfc-xx functions take a
keyword argument :forcep. Calls of mfc-xx functions made on behalf
of meta-extract-contextual-fact always use :forcep nil, so in order
to reason about these calls in your own metafunctions, you will
want to use :forcep nil. We have contemplated adding a utility like
meta-extract-contextual-fact that allows forcing but returns a
tag-tree (see [ttree]), and may do so if there is demand for it.
Finally, we document what is provided logically by calls of
meta-extract-global-fact and meta-extract-contextual-fact. Of
course, you are invited to look at the definitions of these
function in the ACL2 source code, or by using :[pe]. Note that both
of these functions are non-executable (each of their bodies is
inside a call of [non-exec]); their purpose is purely logical, not
for execution. The functions return *t*, i.e., (quote t), in cases
that they provide no information.
First we consider the value of (meta-extract-global-fact obj state)
for various values of obj. When we refer below to concepts like
``body'' and ``evaluation'', we refer to these with respect to the
logical world of the input state.
Case obj = (list :formula FN):
The value reduces to the value of (meta-extract-formula FN state),
which returns the ``formula'' of FN in the following sense. If
FN is a function symbol with formals (X1 ... Xk), then the
formula is the [constraint] on FN if FN is constrained or
introduced by [defchoose], and otherwise is (equal (FN X1 ...
Xk) BODY), where BODY is the (unsimplified) body of the
definition of FN. Otherwise, if FN is the name of a theorem,
the formula is just what is stored for that theorem. Otherwise,
the formula is *t*.
Case obj = (list :lemma FN N):
Assume N is a natural number; otherwise, treat N as 0. If FN is a
function symbol with more than N associated lemmas ---
``associated'' in the sense of being either a :[definition]
rule for FN or a :[rewrite] rule for FN whose left-hand side
has a top function symbol of FN --- then the value is the Nth
such lemma (with zero-based indexing). Otherwise the value is
*t*.
Case obj = (list :fncall FN ARGLIST):
Assume that FN is a :[logic]-mode function symbol and that ARGLIST
is a true list of values of the same length as list of formal
parameters for FN (i.e., as the input arity of FN). Also assume
that the application of FN to actual parameter list ARGLIST
returns a result (mv nil x). Let (QARG1 ... QARGk) be the
result of quoting each element of ARGLIST, i.e., replacing each
y in ARGLIST by the two-element list (quote y). Then the value
is the term (equal (FN QARG1 ... QARGk) (quote x)).
For any other values of obj, the value is *t*.
Finally, the value of (meta-extract-contextual-fact obj mfc state) is
as follows for various values of obj. Note a difference from the
semantics of meta-extract-global-fact: below, the relevant logical
world is the one stored in the metafunction context, mfc, not in
the input state.
Case obj = (list :typeset TERM ...):
The value is the value of (typespec-check ts TERM), where ts is the
value of (mfc-ts TERM mfc state :forcep nil :ttreep nil), and
where (typespec-check ts val) is defined to be true when val
has type-set ts. (Exception: If val satisfies bad-atom then
typespec-check is true when ts is negative.)
Case obj = (list :rw+ TERM ALIST OBJ EQUIV ...):
We assume below that EQUIV is a symbol that represents an
equivalence relation, where nil represents [equal], t
represents [iff], and otherwise EQUIV represents itself (an
equivalence relation in the current logical [world]). For any
other EQUIV the value is *t*. Now let rhs be the value of
(mfc-rw+ TERM ALIST OBJ EQUIV mfc state :forcep nil :ttreep
nil). Then the value is the term (list 'equv (sublis-var ALIST
TERM) rhs), where equv is the equivalence relation represented
by EQUIV, and sublis-var is defined to substitute a
variable-binding alist into a term.
Case obj = (list :rw TERM OBJ EQUIV ...):
The value is the same as above but for an ALIST of nil, i.e., for
the case that obj is (list :rw+ TERM nil OBJ EQUIV ...).
Case obj = (list :ap TERM ...):
The value is (list 'not TERM) if (mfc-ap TERM mfc state :forcep nil)
is true, else is *t*.
Case obj = (list :relieve-hyp HYP ALIST RUNE TARGET BKPTR ...):
The value is (sublis-var alist hyp) --- see above for a discussion
of sublis-var --- if the following is true.
(mfc-relieve-hyp hyp alist rune target bkptr mfc state
:forcep nil :ttreep nil)
Otherwise the value is *t*.
If no case above applies, then the value is *t*.
We conclude by considering the fourth of the four forms above (and
implicitly, its special case represented by the third form above):
(evl (meta-extract-global-fact+ obj st state) aa)
The discussion above is for the function meta-extract-global-fact+,
but assumes that the logical [world]s of st and state are equal;
otherwise the value returned is *t*. Of course, since a call of
meta-extract-global-fact expands to a corresponding call of
meta-extract-global-fact+ in which the last two arguments are both
state, that condition holds automatically for that case. But the
state mentioned in the meta-extract hypotheses of a [meta] rule or
[clause-processor] rule is in essence an initial state. In the case
of a clause-processor rule, the clause-processor function may
modify that initial state (say, by printing or modifying some state
globals) without changing its world, and then pass that modified
state to fncall-term. While fncall-term may produce a different
result for this modified state than for the initial state, both are
valid: the state used for heuristic purposes, such as determining
whether guard-checking may cause an error. A useful instance of the
hypothesis displayed above will be one in which st is that modified
state.")
(META-EXTRACT-CONTEXTUAL-FACT (POINTERS)
"See [meta-extract].")
(META-EXTRACT-FORMULA (POINTERS)
"See [meta-extract].")
(META-EXTRACT-GLOBAL-FACT (POINTERS)
"See [meta-extract].")
(META-EXTRACT-GLOBAL-FACT+ (POINTERS)
"See [meta-extract].")
(META-EXTRACT-RW+-TERM (POINTERS)
"See [meta-extract].")
(META-IMPLICIT-HYPOTHESIS
(META)
"A potentially more efficient way of coding a hypothesis metafunction
We assume familiarity with [meta] rules. In this topic, we discuss a
relatively advanced capability of meta reasoning in ACL2 that can
increase its efficiency.
Introduction
In brief: if a metafunction application to a term, u, evaluates to a
result of the form (if TEST NEW-TERM u), then TEST is treated as an
``implicit hypothesis,'' which must rewrite to true in order for
the meta rule to simplify the input term. We now explain in more
detail.
Recall the general form of a meta rule:
(implies (and (pseudo-termp x) ; this hyp is optional
(alistp a) ; this hyp is optional
(ev (hyp-fn x ...) a) ; this hyp is optional
; meta-extract hyps may also be included (see below)
)
(equiv (ev x a)
(ev (fn x ...) a)))
When this rule is to be applied to a term, x, then (hyp-fn x ...) is
evaluated to produce a term, which must rewrite to true in order to
evaluate the call (fn x ...), which is then rewritten to a
replacement for x. But it may be that these calls of hyp-fn and fn
share a sub-computation. ACL2 provides the ``implicit hypothesis''
mechanism in order to share such a sub-computation. The next
section illustrates how this mechanism works. The final section
provides a precise specification of implicit hypotheses and how
they are used in metareasoning.
Example
The following example is trivial but illustrates the sort of
situation for which implicit hypotheses can be useful. First let us
introduce a function and an evaluator (see [defevaluator]).
(defun foo (x y)
(+ x y))
(defevaluator evl evl-list
((if x y z)
(foo x y)
(binary-+ x y)
(unary-- x)
(acl2-numberp x)
(not x)))
Let us write a meta function and associated hypothesis metafunction
that apply a common function, meta-helper, to a term, term, to
return one of two multiple values: (mv nil term) in the case that
there is no simplification; else (mv hyp new-term), where the
following is a theorem: `(implies ,hyp (equal ,term ,new-term)). Of
course, the following definition introduces a function whose calls
can be evaluated very quickly; but for purposes of this example,
let us pretend that calls of meta-helper take a great deal of time
to evaluate.
(defun meta-helper (term) ; PRETEND that his function is expensive to compute!
(declare (xargs :guard (pseudo-termp term)))
(case-match term
(('foo x ('foo y ('unary-- x)))
(declare (ignore x))
(mv `(acl2-numberp ,y)
y))
(& (mv nil term))))
We can now define our meta function and hypothesis metafunction and
prove a meta rule based on them.
(defun meta-fn (term)
(declare (xargs :guard (pseudo-termp term)))
(mv-let (hyp new-term)
(meta-helper term)
(if hyp new-term term)))
(defun meta-hyp-fn (term)
(declare (xargs :guard (pseudo-termp term)))
(mv-let (hyp new-term)
(meta-helper term)
(declare (ignore new-term))
(or hyp ''nil)))
(defthm meta-fn-correct
(implies (evl (meta-hyp-fn x) a)
(equal (evl x a)
(evl (meta-fn x) a)))
:rule-classes ((:meta :trigger-fns (foo))))
In order to see this meta rule in action, let us disable foo and try
a little test.
(in-theory (disable foo))
(defthm meta-fn-correct-test
(implies (acl2-numberp b)
(equal (foo a (foo b (- a)))
b)))
Happily, the test succeeds, with the summary showing that our meta
rule, meta-fn-correct, was indeed used in the proof. But if we
first submit the form (trace$ meta-fn meta-hyp-fn meta-helper), we
will see that meta-helper is called twice on the term (FOO A (FOO B
(UNARY-- A))): once on behalf of meta-fn and once on behalf of
meta-hyp-fn. This would be unfortunate if meta-helper were
expensive to compute.
So let us back up and try a different approach, which illustrates the
idea of using an ``implicit hypothesis'' in order to avoid
recomputation. This time, we avoid defining a hypothesis
metafunction, but instead we define meta-fn to return a term of the
form (if TEST NEW-TERM term). Here, TEST is `(acl2-numberp ,y); we
call this an ``implicit hypothesis.''
:ubt! meta-fn
(defun meta-fn (term)
(declare (xargs :guard (pseudo-termp term)))
(mv-let (hyp new-term)
(meta-helper term)
(if hyp ; the interesting case
`(if ,hyp ,new-term ,term)
term)))
There is nothing remarkable in the proof of the corresponding meta
rule.
(defthm meta-fn-correct
(equal (evl x a)
(evl (meta-fn x) a))
:rule-classes ((:meta :trigger-fns (foo))))
Let us test our new implementation. If we first evaluate the form
(trace$ meta-fn meta-helper), we will see that this time,
meta-helper is called only once on the term (FOO A (FOO B (UNARY--
A))).
(in-theory (disable foo))
(defthm meta-fn-correct-test
(implies (acl2-numberp b)
(equal (foo a (foo b (- a)))
b)))
Note that the following proof attempt fails but does not loop.
Naively, one might expect it to loop, since the false branch of the
IF term returned by meta-fn has the original (input) term as its
false branch. However, ACL2 notices the special form (if TEST
NEW-TERM term) of the term returned by calling meta-fn, and treats
this result as though TEST is the term returned by a hypothesis
metafunction and NEW-TERM is the term returned by the metafunction.
(thm ; FAILS but does not loop!
(equal (foo a (foo b (- a)))
b))
Suppose that instead we had defined meta-fn as follows, that is, with
the `then' and `else' branches swapped.
(defun meta-fn (term)
(declare (xargs :guard (pseudo-termp term)))
(mv-let (hyp new-term)
(meta-helper term)
(if hyp ; the interesting case ;
`(if (not ,hyp) ,term ,new-term)
term)))
Then the events above go through as before, up to the [thm] form. But
that form loops, because the generated IF term no longer has the
special form (if TEST NEW-TERM term). In the (likely rare) case
that really wishes to allow an unresolved case split for which one
branch is the original term, this swapping of branches is available
to defeat the recognition of an implicit hypothesis.
Precise specification
Consider a meta rule:
(implies (and (pseudo-termp x) ; this hyp is optional
(alistp a) ; this hyp is optional
(ev (hyp-fn x ...) a) ; this hyp is optional
; meta-extract hyps may also be included (see below)
)
(equiv (ev x a)
(ev (fn x ...) a)))
Recall that when this rule is applied to a term, term, then a list of
hypotheses is initially generated as follows, where each generated
hypothesis must be rewritten to a non-nil value in order for the
rule to fire.
1. If there is a hypothesis metafunction, hyp-fn, then let hyps be the
list of hypothesis terms returned by the call of hyp-fn on
term. More precisely, the term returned by the call of hyp-fn
is flattened into a list of ``hypothesis terms,'' so that for
example the (translated) conjunction (if a (if b c 'nil) 'nil)
generates the list (a b c) of hypothesis terms.
2. Otherwise, let hyps be nil.
When this rule is applied by calling fn on a term, term, we say that
a term, test, is an ``implicit hypothesis'' if the value returned
by that call of fn is a term of the form (if test new-term term):
that is, test is the test of the resulting if term and the input
term is the false branch of that if term. In this case, ACL2
recognizes test as an implicit hypothesis, which triggers two
changes made in how this meta rule is applied. First, hyps is
extended by the flattened list of hypotheses generated from test.
Second, instead of applying hyp-fn to the original term, term,
hyp-fn is applied to new-term.")
(MIN
(NUMBERS ACL2-BUILT-INS)
"The smaller of two numbers
(Min x y) is the smaller of the numbers x and y.
The [guard] for min requires its arguments to be rational ([real], in
ACL2(r)) numbers.
Min is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <min>
(defun min (x y)
(declare (xargs :guard (and (real/rationalp x)
(real/rationalp y))))
(if (< x y) x y))")
(MINIMAL-THEORY
(THEORIES THEORY-FUNCTIONS)
"A minimal theory to enable
This [theory] (see [theories]) enables only a few built-in functions
and executable counterparts. It can be useful when you want to
formulate lemmas that rather immediately imply the theorem to be
proved, by way of a :use hint (see [hints]), for example as
follows.
:use (lemma-1 lemma-2 lemma-3)
:in-theory (union-theories '(f1 f2) (theory 'minimal-theory))
In this example, we expect the current goal to follow from lemmas
lemma-1, lemma-2, and lemma-3 together with rules f1 and f2 and
some obvious facts about built-in functions (such as the
[definition] of [implies] and the :[executable-counterpart] of
[car]). The :[in-theory] hint above is intended to speed up the
proof by turning off all inessential rules.")
(MINUSP
(NUMBERS ACL2-BUILT-INS)
"Test whether a number is negative
(Minusp x) is true if and only if x < 0.
The [guard] of minusp requires its argument to be a rational ([real],
in ACL2(r)) number.
Minusp is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <minusp>
(defun minusp (x)
(declare (xargs :guard (real/rationalp x)))
(< x 0))")
(MISCELLANEOUS
(ACL2)
"A miscellany of documented functions and concepts (often cited in
more accessible [documentation])
Perhaps as the system matures this section will become more
structured.
Subtopics
[ACL2-customization]
File of initial commands for ACL2 to run at [startup]
[Case-split-limitations]
A list of two ``numbers'' limiting the number of cases produced at
once
[Default-defun-mode]
The default [defun-mode] of [defun]'d functions
[Gc$]
Invoke the garbage collector
[Gc-strategy]
The garbage collection strategy
[Gcl]
Tips on building and using ACL2 based on Gnu Common Lisp
[Hints]
Advice to the theorem proving process
[Ld]
The ACL2 read-eval-print loop, file loader, and [command] processor
[Local-incompatibility]
When non-local [events] won't replay in isolation
[Ordinals]
Ordinals in ACL2
[Reader]
Reading expressions in the ACL2 read-eval-print loop
[Set-case-split-limitations]
Set the case-split-limitations
[Set-gc-strategy]
Set the garbage collection strategy (CCL only)
[Set-prover-step-limit]
Sets the step-limit used by the ACL2 prover
[Specious-simplification]
Nonproductive proof steps
[Subversive-inductions]
Why we restrict [encapsulate]d recursive functions
[Subversive-recursions]
Why we restrict [encapsulate]d recursive functions
[Syntax]
The syntax of ACL2 is that of Common Lisp
[Term]
The three senses of well-formed ACL2 expressions or formulas
[Thm]
Prove a theorem
[Top-level]
Evaluate a top-level form as a function body
[Ttags-seen]
List some declared trust tags (ttags)
[Ttree]
Tag-trees
[Type-set]
How type information is encoded in ACL2
[With-prover-step-limit]
Limit the number of steps for proofs
[With-prover-time-limit]
Limit the time for proofs")
(MOD
(NUMBERS ACL2-BUILT-INS)
"Remainder using [floor]
ACL2 !>(mod 14 3)
2
ACL2 !>(mod -14 3)
1
ACL2 !>(mod 14 -3)
-1
ACL2 !>(mod -14 -3)
-2
ACL2 !>(mod -15 -3)
0
ACL2 !>
(Mod i j) is that number k that (* j (floor i j)) added to k equals
i.
The [guard] for (mod i j) requires that i and j are rational ([real],
in ACL2(r)) numbers and j is non-zero.
Mod is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <mod>
(defun mod (x y)
(declare (xargs :guard (and (real/rationalp x)
(real/rationalp y)
(not (eql y 0)))))
(- x (* (floor x y) y)))")
(MOD-EXPT
(NUMBERS ACL2-BUILT-INS)
"Exponential function
(mod-expt r i m) is the result of raising the number r to the integer
power i and then taking the residue mod m. That is, (mod-expt r i
m) is equal to (mod (expt r i) m).
The [guard] for (mod-expt r i m) is that r is a rational number and i
is an integer; if r is 0 then i is nonnegative; and m is a non-zero
rational number.
In some implementations (GCL Version 2.7.0 as of this writing), this
function is highly optimized when r and i are natural numbers, not
both zero, and m is a positive integer. For other Lisp
implementations, consider using function mod-expt-fast, defined in
the community book arithmetic-3/floor-mod/mod-expt-fast.lisp, which
should still provide significantly improved performance over this
function.
Function: <mod-expt>
(defun
mod-expt (base exp mod)
(declare (xargs :guard (and (real/rationalp base)
(integerp exp)
(not (and (eql base 0) (< exp 0)))
(real/rationalp mod)
(not (eql mod 0)))))
(mod (expt base exp) mod))")
(MODE (POINTERS)
"See [xargs] for keyword :mode.")
(MODELING_IN_ACL2
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Modeling in ACL2
[{IMAGE}]
{IMAGE}
Below we define mc(s,n) to be the function that single-steps n times
from a given starting state, s. In Common Lisp, ``mc(s,n)'' is
written (mc s n).
(defun mc (s n) ; To step s n times:
(if (zp n) ; If n is 0
s ; then return s
(mc (single-step s) (- n 1)))) ; else step single-step(s)
n-1 times.
This is an example of a formal model in ACL2.
[{IMAGE}]")
(MODELS_IN_ENGINEERING
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Models in Engineering
{IMAGE}
Frequently, engineers use mathematical models. Use of such models
frequently lead to
better designs,
faster completion of acceptable products, and
reduced overall cost,
because models allow the trained user to study the design before it
is built and analyze its properties. Usually, testing and analyzing
a model is cheaper and faster than fabricating and refabricating
the product.
{IMAGE}")
(MODELS_OF_COMPUTER_HARDWARE_AND_SOFTWARE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Models of Computer Hardware and Software
[{IMAGE}]
{IMAGE}
Computing machines, whether hardware or software or some
combintation, are frequently modeled as ``state machines.''
To so model a computing machine we must represent its states as
objects in our mathematical framework.
Transitions are functions or relations on state objects.
In what language shall we define these objects, functions, and
relations?
The mathematical languages we were taught in high school
algebra,
geometry,
trignometry, and
calculus
are often inappropriate for modeling digital systems. They primarily
let us talk about numbers and continuous functions.
To see what kind of expressive power we need, take a closer look at
what a typical state contains.
[{IMAGE}]")
(MONITOR
(BREAK-REWRITE)
"To monitor the attempted application of a rule name
Example:
(monitor '(:rewrite assoc-of-app) 't)
:monitor (:rewrite assoc-of-app) t
(monitor '(:r assoc-of-app) t)
:monitor (:r assoc-of-app) t
:monitor assoc-of-app t
:monitor (:definition app) (equal (brr@ :target) '(app c d))
:monitor (:linear rule3) t
In the example above, the first four forms are equivalent. Those are
equivalent to the fifth form if the event assoc-of-app corresponds
to a rewrite rule, or more precisely, to a single [rune], (:rewrite
assoc-of-app).
General Forms:
(monitor x term)
(monitor x term)
where x is a runic designator other than a theory name (see
[theories]) and term is a term, called the ``break condition.'' If
x is not a symbol then it must designate a rune corresponding to a
rule of class :[rewrite], :[definition], or :[linear]. If x is a
symbol then it represents all such runes that it designates, in and
there must be at least one such. (Thus, x cannot name an event that
generates only rules of classes other than those three.)
When a [rune] is [monitor]ed any attempt to apply it may result in an
interactive break in an ACL2 ``[wormhole] [state].'' There you will
get a chance to see how the application proceeds. See
[break-rewrite] for a description of the interactive loop entered.
Whether an interactive break occurs depends on the value of the
break condition expression associated with the [monitor]ed [rune].
NOTE: Some :rewrite rules are considered ``simple abbreviations'';
see [simple]. These can be be monitored, but only at certain times
during the proof. Monitoring is carried out by code inside the
rewriter but abbreviation rules may be applied by a special purpose
simplifier inside the so-called preprocess phase of a proof. If you
desire to monitor an abbreviation rule, a warning will be printed
suggesting that you may want to supply the hint :DO-NOT
'(PREPROCESS); see [hints]. Without such a hint, an abbreviation
rule can be applied during the preprocess phase of a proof, and no
such application will cause an interactive break.
To remove a [rune] from the list of [monitor]ed [rune]s, use
unmonitor. To see which [rune]s are [monitor]ed and what their
break conditions are, evaluate (monitored-runes).
Monitor, unmonitor and monitored-runes are macros that expand into
expressions involving state. While these macros appear to return
the list of [monitor]ed [rune]s this is an illusion. They all print
[monitor]ed [rune] information to the comment window and then
return [error-triple]s instructing ld to print nothing. It is
impossible to return the list of [monitor]ed [rune]s because it
exists only in the [wormhole] [state] with which you interact when
a break occurs. This allows you to change the [monitor]ed [rune]s
and their conditions during the course of a proof attempt without
changing the [state] in which the the proof is being constructed.
Unconditional break points are obtained by using the break condition
t. We now discuss conditional break points. The break condition,
expr, must be a term that contains no free variables other than
state and that returns a single non-state result. In fact, the
result should be nil, t, or a true list of commands to be fed to
the resulting interactive break. Whenever the system attempts to
use the associated rule, expr is evaluated in the [wormhole]
interaction [state]. A break occurs only if the result of
evaluating expr is non-nil. If the result is a true list, that list
is appended to the front of standard-oi and hence is taken as the
initial user commands issued to the interactive break.
In order to develop effective break conditions it must be possible to
access context sensitive information, i.e., information about the
context in which the [monitor]ed [rune] is being tried. The [brr@]
macro may be used in break conditions to access such information as
the term being rewritten and the current governing assumptions.
This information is not stored in the proof [state] but is
transferred into the [wormhole] [state] when breaks occur. The
macro form is (brr@ :sym) where :sym is one of several keyword
symbols, including :target (the term being rewritten), :unify-subst
(the substitution that instantiates the left-hand side of the
conclusion of the rule so that it is the target term), and
:[type-alist] (the governing assumptions). See [brr@].
For example,
ACL2 !>:monitor (:rewrite assoc-of-app)
(equal (brr@ :target) '(app a (app b c)))
will monitor (:rewrite assoc-of-app) but will cause an interactive
break only when the target term, the term being rewritten, is (app
a (app b c)).
Because break conditions are evaluated in the interaction
environment, the user developing a break condition for a given
[rune] can test candidate break conditions before installing them.
For example, suppose an unconditional break has been installed on a
[rune], that an interactive break has occurred and that the user
has determined both that this particular application is
uninteresting and that many more such applications will likely
occur. An appropriate response would be to develop an expression
that recognizes such applications and returns nil. Of course, the
hard task is figuring out what makes the current application
uninteresting. But once a candidate expression is developed, the
user can evaluate it in the current context simply to confirm that
it returns nil.
Recall that when a break condition returns a non-nil true list that
list is appended to the front of standard-oi. For example,
ACL2 !>:monitor (:rewrite assoc-of-app) '(:go)
will cause (:rewrite assoc-of-app) to be [monitor]ed and will make
the break condition be '(:go). This break condition always
evaluates the non-nil true list (:go). Thus, an interactive break
will occur every time (:rewrite assoc-of-app) is tried. The break
is fed the command :go. Now the command :go causes break-rewrite to
(a) evaluate the attempt to apply the lemma, (b) print the result
of that attempt, and (c) exit from the interactive break and let
the proof attempt continue. Thus, in effect, the above :monitor
merely ``traces'' the attempted applications of the [rune] but
never causes an interactive break requiring input from the user.
It is possible to use this feature to cause a conditional break where
the effective break condition is tested after the lemma has been
tried. For example:
ACL2 !>:monitor (:rewrite lemma12)
'(:unify-subst
:eval$ nil
:ok-if (or (not (brr@ :wonp))
(not (equal (brr@ :rewritten-rhs) '(foo a))))
:rewritten-rhs)
causes the following behavior when (:rewrite lemma12) is tried. A
break always occurs, but it is fed the commands above. The first,
:unify-subst, causes break-rewrite to print out the unifying
substitution. Then in response to :eval$ nil the lemma is tried but
with all [rune]s temporarily [unmonitor]ed. Thus no breaks will
occur during the rewriting of the hypotheses of the lemma. When the
attempt has been made, control returns to break-rewrite (which will
print the results of the attempt, i.e., whether the lemma was
applied, if so what the result is, if not why it failed). The next
command, the :ok-if with its following expression, is a conditional
exit command. It means exit break-rewrite if either the attempt was
unsuccessful, (not (brr@ :wonp)), or if the result of the rewrite
is any term other than (foo a). If this condition is met, the break
is exited and the remaining break commands are irrelevant. If this
condition is not met then the next command, :rewritten-rhs, prints
the result of the application (which in this contrived example is
known to be (foo a)). Finally, the list of supplied commands is
exhausted but break-rewrite expects more input. Therefore, it
begins prompting the user for input. The end result, then, of the
above :monitor command is that the [rune] in question is
elaborately traced and interactive breaks occur whenever it
rewrites its target to (foo a).
We recognize that the above break condition is fairly arcane. We
suspect that with experience we will develop some useful idioms.
For example, it is straightforward now to define macros that
monitor [rune]s in the ways suggested by the following names:
trace-rune, break-if-target-is, and break-if-result-is. For
example, the last could be defined as
(defmacro break-if-result-is (rune term)
`(monitor ',rune
'(quote (:eval :ok-if
(not (equal (brr@ :rewritten-rhs) ',term))))))
(Note however that the submitted term must be in translated form.)
Since we don't have any experience with this kind of control on
lemmas we thought it best to provide a general (if arcane)
mechanism and hope that the ACL2 community will develop the special
cases that we find most convenient.")
(MONITORED-RUNES
(BREAK-REWRITE)
"Print the [monitor]ed [rune]s and their break conditions
Example and General Form:
:monitored-runes
This macro prints a list, each element of which is of the form (rune
expr), showing each [monitor]ed [rune] and its current break
condition.")
(MSG
(IO ACL2-BUILT-INS)
"Construct a ``message'' suitable for the ~@ directive of [fmt]
See [fmt] for background on formatted printing with ACL2.
We document msg precisely below, but first, we give an informal
introduction and illustrate with an example. Suppose you are
writing a program that is to do some printing. Typically, you will
either pass the ACL2 state around (see [programming-with-state])
and use formatted printing functions that take the state as an
argument (see [fmt])), or else you might avoid using state by
calling the utility, [cw], to do you printing. Alternatively, you
might print error messages upon encountering illegal situations;
see [er]. But there are times where instead of printing
immediately, you may prefer to pass messages around, for example to
accumulate them before printing a final message. In such cases, it
may be desirable to construct ``message'' objects to pass around.
For example, consider the following pair of little programs. The
first either performs a computation or prints an error, and the
second calls the first on two inputs.
(defun invert1 (x)
(if (consp x)
(cons (cdr x) (car x))
(prog2$ (cw \"ERROR: ~x0 expected a cons, but was given ~x1.~|\"
'invert1 x)
nil)))
(defun invert2 (x1 x2)
(list (invert1 x1) (invert1 x2)))
For example:
ACL2 !>(invert1 '(3 . 4))
(4 . 3)
ACL2 !>(invert1 'a)
ERROR: INVERT1 expected a cons, but was given A.
NIL
ACL2 !>(invert2 '(3 . 4) '(5 . 6))
((4 . 3) (6 . 5))
ACL2 !>(invert2 'a 'b)
ERROR: INVERT1 expected a cons, but was given A.
ERROR: INVERT1 expected a cons, but was given B.
(NIL NIL)
ACL2 !>
Notice that when there are errors, there is no attempt to explain
that these are due to a call of invert2. That could be fixed, of
course, by arranging for invert2 to print its own error; but for
complicated programs it can be awkward to coordinate printing from
many sources. So let's try a different approach. This time, the
first function returns two results. The first result is an ``error
indicator'' --- either a message object or nil --- while the second
is the computed value (only of interest when the first result is
nil). Then the higher-level function can print a single error
message that includes the error message(s) from the lower-level
function, as shown below.
(defun invert1a (x)
(if (consp x)
(mv nil
(cons (cdr x) (car x)))
(mv (msg \"ERROR: ~x0 expected a cons, but was given ~x1.~|\"
'invert1a x)
nil)))
(defun invert2a (x1 x2)
(mv-let (erp1 y1)
(invert1a x1)
(mv-let (erp2 y2)
(invert1a x2)
(if erp1
(if erp2
(cw \"~x0 failed with two errors:~| ~@1 ~@2\"
'invert2a erp1 erp2)
(cw \"~x0 failed with one error:~| ~@1\"
'invert2a erp1))
(if erp2
(cw \"~x0 failed with one error:~| ~@1\"
'invert2a erp2)
(list y1 y2))))))
For example:
ACL2 !>(invert2a '(3 . 4) '(5 . 6))
((4 . 3) (6 . 5))
ACL2 !>(invert2a '(3 . 4) 'b)
INVERT2A failed with one error:
ERROR: INVERT1A expected a cons, but was given B.
NIL
ACL2 !>(invert2a 'a 'b)
INVERT2A failed with two errors:
ERROR: INVERT1A expected a cons, but was given A.
ERROR: INVERT1A expected a cons, but was given B.
NIL
ACL2 !>
If you study the example above, you might well understand msg. But we
conclude with precise documentation.
General Form:
(msg str arg1 ... argk)
where str is a string and k is at most 9.
This macro returns a pair suitable for giving to the fmt directive
~@. Thus, suppose that #\\c is bound to the value of (msg str arg1
... argk), where c is a character and k is at most 9. Then the fmt
directive ~@c will print out the string, str, in the context of the
alist in which the successive fmt variables #\\0, #\\1, ..., #\\k are
bound to the successive elements of (arg1 ... argk).")
(MUST-BE-EQUAL
(MBE ACL2-BUILT-INS)
"Attach code for execution
The form (must-be-equal logic exec) evaluates to logic in the ACL2
logic but evaluates to exec in raw Lisp. The point is to be able to
write one definition to reason about logically but another for
evaluation. Please see [mbe] and see [mbt] for appropriate macros
to use, rather than calling must-be-equal directly, since it is
easy to commute the arguments of must-be-equal by accident.
In essence, the guard for (must-be-equal x y) is (equal x y).
However, note that must-be-equal is a macro: (must-be-equal logic
exec) expands to (mbe1 exec logic), which expands to a call of
[return-last].")
(MUTUAL-RECURSION
(EVENTS PROGRAMMING DEFUN)
"Define some mutually recursive functions
Example:
(mutual-recursion
(defun evenlp (x)
(if (consp x) (oddlp (cdr x)) t))
(defun oddlp (x)
(if (consp x) (evenlp (cdr x)) nil)))
General Form:
(mutual-recursion def1 ... defn)
where each defi is a call of [defun], [defund], [defun-nx], or
defund-nx.
When mutually recursive functions are introduced it is necessary to
do the termination analysis on the entire clique of definitions.
Each [defun] form specifies its own measure, either with the
:measure keyword xarg (see [xargs]) or by default to [ACL2-count].
When a function in the clique calls a function in the clique, the
measure of the callee's actuals must be smaller than the measure of
the caller's formals --- just as in the case of a simply recursive
function. But with mutual recursion, the callee's actuals are
measured as specified by the callee's [defun] while the caller's
formals are measured as specified by the caller's [defun]. These
two measures may be different but must be comparable in the sense
that [o<] decreases through calls.
If you want to specify :[hints] or :guard-hints (see [xargs]), you
can put them in the [xargs] declaration of any of the [defun]
forms, as the :[hints] from each form will be appended together, as
will the [guard-hints] from each form.
You may find it helpful to use a lexicographic order, the idea being
to have a measure that returns a list of two arguments, where the
first takes priority over the second. Here is an example.
(include-book \"ordinals/lexicographic-ordering\" :dir :system)
(encapsulate
()
(set-well-founded-relation l<) ; will be treated as LOCAL
(mutual-recursion
(defun foo (x)
(declare (xargs :measure (list (acl2-count x) 1)))
(bar x))
(defun bar (y)
(declare (xargs :measure (list (acl2-count y) 0)))
(if (zp y) y (foo (1- y))))))
The [guard] analysis must also be done for all of the functions at
the same time. If any one of the [defun]s specifies the
:[verify-guards] xarg to be nil, then [guard] verification is
omitted for all of the functions. Similarly, if any one of the
[defun]s specifies the :non-executable xarg to be t, or if any of
the definitions uses [defun-nx] or defund-nx, then every one of the
definitions will be treated as though it specifies a
:non-executable xarg of t.
Technical Note: Each defi above must be a call of [defun], [defund],
[defun-nx], or defund-nx. In particular, it is not permitted for a
defi to be an arbitrary form that macroexpands into a [defun] form.
This is because mutual-recursion is itself a macro, and since
macroexpansion occurs from the outside in, at the time
(mutual-recursion def1 ... defk) is expanded the defi have not yet
been macroexpanded.
Suppose you have defined your own [defun]-like macro and wish to use
it in a mutual-recursion expression. Well, you can't. (!) But you
can define your own version of mutual-recursion that allows your
[defun]-like form. Here is an example. Suppose you define
(defmacro my-defun (&rest args) (my-defun-fn args))
where my-defun-fn takes the arguments of the my-defun form and
produces from them a [defun] form. As noted above, you are not
allowed to write (mutual-recursion (my-defun ...) ...). But you can
define the macro my-mutual-recursion so that
(my-mutual-recursion (my-defun ...) ... (my-defun ...))
expands into (mutual-recursion (defun ...) ... (defun ...)) by
applying my-defun-fn to each of the arguments of
my-mutual-recursion.
(defun my-mutual-recursion-fn (lst)
(declare (xargs :guard (alistp lst)))
; Each element of lst must be a consp (whose car, we assume, is always
; MY-DEFUN). We apply my-defun-fn to the arguments of each element and
; collect the resulting list of DEFUNs.
(cond ((atom lst) nil)
(t (cons (my-defun-fn (cdr (car lst)))
(my-mutual-recursion-fn (cdr lst))))))
(defmacro my-mutual-recursion (&rest lst)
; Each element of lst must be a consp (whose car, we assume, is always
; MY-DEFUN). We obtain the DEFUN corresponding to each and list them
; all inside a MUTUAL-RECURSION form.
(declare (xargs :guard (alistp lst)))
(cons 'mutual-recursion (my-mutual-recursion-fn lst))).
Subtopics
[Defuns]
An alternative to [mutual-recursion]
[Mutual-recursion-proof-example]
A small proof about mutually recursive functions
[Set-bogus-mutual-recursion-ok]
Allow unnecessary ``mutual recursion''")
(MUTUAL-RECURSION-PROOF-EXAMPLE
(TUTORIAL5-MISCELLANEOUS-EXAMPLES MUTUAL-RECURSION)
"A small proof about mutually recursive functions
Sometimes one wants to reason about mutually recursive functions.
Although this is possible in ACL2, it can be a bit awkward. This
example is intended to give some ideas about how one can go about
such proofs.
For an introduction to mutual recursion in ACL2, see
[mutual-recursion].
We begin by defining two mutually recursive functions: one that
collects the variables from a [term], the other that collects the
variables from a list of [term]s. We actually imagine the [term]
argument to be a pseudo-termp; see [pseudo-termp].
(mutual-recursion
(defun free-vars1 (term ans)
(cond ((atom term)
(add-to-set-eq term ans))
((fquotep term) ans)
(t (free-vars1-lst (cdr term) ans))))
(defun free-vars1-lst (lst ans)
(cond ((atom lst) ans)
(t (free-vars1-lst (cdr lst)
(free-vars1 (car lst) ans)))))
)
Now suppose that we want to prove the following theorem.
(defthm symbol-listp-free-vars1-try-1
(implies (and (pseudo-termp x)
(symbol-listp ans))
(symbol-listp (free-vars1 x ans))))
Often ACL2 can generate a proof by induction based on the structure
of definitions of function symbols occurring in the conjecture. In
this case, ACL2 chooses to use an induction scheme suggested by
(symbol-listp ans), and sadly, that doesn't work. If one were doing
this proof with pencil and paper, one would be more likely to prove
a combination of the conjecture above and an analogous conjecture
about free-vars1-lst. Feel free to try a pencil and paper proof! Or
you can read on, to see how one can get ACL2 to do such a proof
after all.
The trick is to define a function that suggests an appropriate
induction. The induction suggested is based on the if-then-else
structure of the function's definition, where inductive hypotheses
are generated for recursive calls --- below we explain how that
works for this function.
(defun symbol-listp-free-vars1-induction (x ans)
(if (atom x)
; then we just make sure x and ans aren't considered irrelevant:
(list x ans)
(list (symbol-listp-free-vars1-induction (car x) ans)
(symbol-listp-free-vars1-induction (cdr x) ans)
(symbol-listp-free-vars1-induction (cdr x)
(free-vars1 (car x) ans)))))
The if-then-else structure of this function generates two cases. In
one case, (atom x) is true, and the theorem to be proved should be
proved under no additional hypotheses except for (atom x); in other
words, (atom x) gives us the base case of the induction. In the
other case, (not (atom x)) is assumed together with three instances
of the theorem to be proved, one for each recursive call. So, one
instance substitutes (car x) for x; one substitutes (cdr x) for x;
and the third substitutes (cdr x) for x and (free-vars1 (car x)
ans) for ans. If you think about how you would go about a hand
proof of the theorem to follow, you'll likely come up with a
similar scheme.
We now prove the two theorems together as a conjunction, because the
inductive hypotheses for one are sometimes needed in the proof of
the other (even when you do this proof on paper!).
(defthm symbol-listp-free-vars1
(and (implies (and (pseudo-termp x)
(symbol-listp ans))
(symbol-listp (free-vars1 x ans)))
(implies (and (pseudo-term-listp x)
(symbol-listp ans))
(symbol-listp (free-vars1-lst x ans))))
:hints
((\"Goal\" :induct (symbol-listp-free-vars1-induction x ans))))
The above works, but we conclude by illustrating a more efficient
approach, in which we restrict to appropriate inductive hypotheses
for each case.
(ubt 'symbol-listp-free-vars1-induction)
(defun symbol-listp-free-vars1-induction (flg x ans)
; Flg is nil if we are ``thinking'' of a single term.
(if (atom x) ; whether x is a single term or a list of terms
(list x ans)
(if flg ; i.e., if x is a list of terms
(list (symbol-listp-free-vars1-induction nil (car x) ans)
(symbol-listp-free-vars1-induction t
(cdr x)
(free-vars1 (car x) ans)))
(symbol-listp-free-vars1-induction t (cdr x) ans))))
We now state the theorem as a conditional, so that it can be proved
nicely using the [induction] scheme that we have just coded. The
prover will not store an [if] [term] as a [rewrite] rule, but
that's OK (provided we tell it not to try), because we're going to
derive the corollaries of interest later and make them into
[rewrite] rules.
(defthm symbol-listp-free-vars1-flg
(if flg
(implies (and (pseudo-term-listp x)
(symbol-listp ans))
(symbol-listp (free-vars1-lst x ans)))
(implies (and (pseudo-termp x)
(symbol-listp ans))
(symbol-listp (free-vars1 x ans))))
:hints
((\"Goal\" :induct (symbol-listp-free-vars1-induction flg x ans)))
:rule-classes nil)
And finally, we may derive the theorems we are interested in as
immediate corollaries.
(defthm symbol-listp-free-vars1
(implies (and (pseudo-termp x)
(symbol-listp ans))
(symbol-listp (free-vars1 x ans)))
:hints ((\"Goal\" :by (:instance symbol-listp-free-vars1-flg
(flg nil)))))
(defthm symbol-listp-free-vars1-lst
(implies (and (pseudo-term-listp x)
(symbol-listp ans))
(symbol-listp (free-vars1-lst x ans)))
:hints ((\"Goal\" :by (:instance symbol-listp-free-vars1-flg
(flg t)))))
You may find [community-books] that help you to automate this kind of
reasoning about mutually recursive functions. See for example
[make-flag].")
(MV
(BASICS ACL2-BUILT-INS)
"Returning a multiple value
Mv is the mechanism provided by ACL2 for returning two or more
values. Logically, (mv x1 x2 ... xn) is the same as (list x1 x2 ...
xn), a list of the indicated values. However, ACL2 avoids the cost
of building this list structure, with the cost that mv may only be
used in a certain style in definitions: if a function ever returns
using mv (either directly, or by calling another function that
returns a multiple value), then this function must always return
the same number of values.
For more explanation of the multiple value mechanism, see [mv-let].
Also see [mv-list] for a way to convert a multiple value into an
ordinary list.
ACL2 does not support the Common Lisp construct values, whose logical
meaning seems difficult to characterize. Mv is the ACL2 analogue of
that construct.
Subtopics
[Mv-let]
Calling multi-valued ACL2 functions
[Mv-list]
Converting multiple-valued result to a single-valued list
[Mv-nth]
The mv-nth element (zero-based) of a list
[Mv?]
Return one or more values
[Mv?-let]
Calling possibly multi-valued ACL2 functions")
(MV-LET
(MV ACL2-BUILT-INS)
"Calling multi-valued ACL2 functions
Example Form:
(mv-let (x y z) ; local variables
(mv 1 2 3) ; multi-valued expression
(declare (ignore y)) ; optional declarations
(cons x z)) ; body
The form above binds the three ``local variables,'' x, y, and z, to
the three results returned by the multi-valued expression and then
evaluates the body. The result is '(1 . 3). The second local, y, is
[declare]d ignored. The multi-valued expression can be any ACL2
expression that returns k results, where k is the number of local
variables listed. Often however it is simply the application of a
k-valued function. Mv-let is the standard way to invoke a
multi-valued function when the caller must manipulate the vector of
results returned.
General Form:
(mv-let (var1 ... vark)
term
body)
or
(mv-let (var1 ... vark)
term
(declare ...) ... (declare ...)
body)
where the vari are distinct variables, term is a term that returns k
results and mentions only variables bound in the environment
containing the mv-let expression, and body is a term mentioning
only the vari and variables bound in the environment containing the
mv-let. Each vari must occur in body unless it is [declare]d
ignored or ignorable in one of the optional [declare] forms, unless
this requirement is turned off; see [set-ignore-ok]. The value of
the mv-let term is the result of evaluating body in an environment
in which the vari are bound, in order, to the k results obtained by
evaluating term in the environment containing the mv-let.
Here is an extended example that illustrates both the definition of a
multi-valued function and the use of mv-let to call it. Consider a
simple binary tree whose interior nodes are [cons]es and whose
leaves are non-[cons]es. Suppose we often need to know the number,
n, of interior nodes of such a tree; the list, syms, of symbols
that occur as leaves; and the list, ints, of integers that occur as
leaves. (Observe that there may be leaves that are neither symbols
nor integers.) Using a multi-valued function we can collect all
three results in one pass.
Here is the first of two definitions of the desired function. This
definition is ``primitive recursive'' in that it has only one
argument and that argument is reduced in size on every recursion.
(defun count-and-collect (x)
; We return three results, (mv n syms ints) as described above.
(cond ((atom x)
; X is a leaf. Thus, there are 0 interior nodes, and depending on
; whether x is a symbol, an integer, or something else, we return
; the list containing x in as the appropriate result.
(cond ((symbolp x) (mv 0 (list x) nil))
((integerp x)(mv 0 nil (list x)))
(t (mv 0 nil nil))))
(t
; X is an interior node. First we process the car, binding n1, syms1, and
; ints1 to the answers.
(mv-let (n1 syms1 ints1)
(count-and-collect (car x))
; Next we process the cdr, binding n2, syms2, and ints2.
(mv-let (n2 syms2 ints2)
(count-and-collect (car x))
; Finally, we compute the answer for x from those obtained for its car
; and cdr, remembering to increment the node count by one for x itself.
(mv (1+ (+ n1 n2))
(append syms1 syms2)
(append ints1 ints2)))))))
This use of a multiple value to ``do several things at once'' is very
common in ACL2. However, the function above is inefficient because
it [append]s syms1 to syms2 and ints1 to ints2, copying the list
structures of syms1 and ints1 in the process. By adding
``accumulators'' to the function, we can make the code more
efficient.
(defun count-and-collect1 (x n syms ints)
(cond ((atom x)
(cond ((symbolp x) (mv n (cons x syms) ints))
((integerp x) (mv n syms (cons x ints)))
(t (mv n syms ints))))
(t (mv-let (n2 syms2 ints2)
(count-and-collect1 (cdr x) (1+ n) syms ints)
(count-and-collect1 (car x) n2 syms2 ints2)))))
We claim that (count-and-collect x) returns the same triple of
results as (count-and-collect1 x 0 nil nil). The reader is urged to
study this claim until convinced that it is true and that the
latter method of computing the results is more efficient. One might
try proving the theorem
(defthm count-and-collect-theorem
(equal (count-and-collect1 x 0 nil nil) (count-and-collect x))).
Hint: the inductive proof requires attacking a more general theorem.
ACL2 does not support the Common Lisp construct multiple-value-bind,
whose logical meaning seems difficult to characterize. Mv-let is
the ACL2 analogue of that construct. Also see [mv] and see
[mv-list].")
(MV-LIST
(MV ACL2-BUILT-INS)
"Converting multiple-valued result to a single-valued list
Example Forms:
; Returns the list (3 4):
(mv-list 2 (mv 3 4))
; Returns a list containing the three values returned by var-fn-count:
(mv-list 3 (var-fn-count '(cons (binary-+ x y) z) nil))
General form:
(mv-list n term)
Logically, (mv-list n term) is just term; that is, in the logic
mv-list simply returns its second argument. However, the evaluation
of a call of mv-list on explicit values always results in a single
value, which is a (null-terminated) list. For evaluation, the term
n above (the first argument to an mv-list call) must
``essentially'' (see below) be an integer not less than 2, where
that integer is the number of values returned by the evaluation of
term (the second argument to that mv-list call).
We say ``essentially'' above because it suffices that the translation
of n to a term (see [trans]) be of the form (quote k), where k is
an integer greater than 1. So for example, if term above returns
three values, then n can be the expression 3, or (quote 3), or even
(mac 3) if mac is a macro defined by (defmacro mac (x) x). But n
cannot be (+ 1 2), because even though that expression evaluates to
3, nevertheless it translates to (binary-+ '1 '2), not to (quote
3).
Mv-list is the ACL2 analogue of the Common Lisp construct
multiple-value-list.
Function: <mv-list>
(defun mv-list (input-arity x)
(declare (xargs :guard t)
(ignore input-arity))
x)")
(MV-NTH
(MV ACL2-BUILT-INS)
"The mv-nth element (zero-based) of a list
(Mv-nth n l) is the nth element of l, zero-based. If n is greater
than or equal to the length of l, then mv-nth returns nil.
(Mv-nth n l) has a [guard] that n is a non-negative integer.
Mv-nth is equivalent to the Common Lisp function [nth] (although
without the guard condition that the list is a [true-listp]), but
is used by ACL2 to access the nth value returned by a multiply
valued expression. For example, the following are logically
equivalent:
(mv-let (erp val state)
(read-object ch state)
(value (list erp val)))
and
(let ((erp (mv-nth 0 (read-object ch state)))
(val (mv-nth 1 (read-object ch state)))
(state (mv-nth 2 (read-object ch state))))
(value (list erp val)))
To see the ACL2 definition of mv-nth, see [pf].
If EXPR is an expression that is multiply valued, then the form
(mv-nth n EXPR) is illegal both in definitions and in forms
submitted directly to the ACL2 loop. Indeed, EXPR cannot be passed
as an argument to any function (mv-nth or otherwise) in such an
evaluation context. The reason is that ACL2 code compiled for
execution does not actually create a list for multiple value
return; for example, the read-object call above logically returns a
list of length 3, but when evaluated, it instead stores its three
returned values without constructing a list. In such cases you can
use mv-nth to access the corresponding list by using mv-list,
writing (mv-nth n (mv-list k EXPR)) for suitable k, where mv-list
converts a multiple value result into the corresponding list; see
[mv-list].")
(MV?
(MV ACL2-BUILT-INS)
"Return one or more values
Mv? is designed to work with mv?-let, generalizing how [mv] works
with [mv-let] by allowing the binding of a single variable. For
example, the following form is legal.
(mv?-let (y)
(mv? (f x))
(declare (type integer y))
(g x y z))
The expression above is equivalent to the following expression,
because (mv? form) expands to form for any expression, form.
(let ((y (f x)))
(declare (type integer y))
(g x y z))
Logically, (mv? x) is the same as x, while (mv? v1 v2 ...) is the
same as (list v1 v2 ...). Also see [mv] and see [mv?-let].")
(MV?-LET
(MV ACL2-BUILT-INS)
"Calling possibly multi-valued ACL2 functions
Mv?-let is a macro that extends the macro [mv-let] by allowing a
single variable to be bound. Thus, the syntax is the same as that
of [mv-let] except that mv?-let is permitted to bind a single
variable to a form that produces a single value. The macros mv?-let
and [mv?] are provided to facilitate the writing of macros that
traffic in expressions that could return one or more (multiple)
values.
For example, the form
(mv?-let (y)
(f x)
(declare (type integer y))
(g x y z))
is equivalent to the following form.
(let ((y (f x)))
(declare (type integer y))
(g x y z))
Calls of mv?-let and of [mv-let] are equivalent when the first
argument contains at least two variables; see [mv-let] for
documentation. In the case of binding a single variable, the
general form is
(mv?-let (var)
term
(declare ...) ... (declare ...)
body)
and this is equivalent to the following form (see [let]).
(let ((var term))
(declare ...) ... (declare ...)
body)
Also see [mv?].")
(NAME
(EVENTS)
"Syntactic rules on logical names
Examples Counter-Examples
PRIMEP 91 (not a symbolp)
F-AC-23 :CHK-LIST (in KEYWORD package)
1AX *PACKAGE* (in the Lisp Package)
|Prime Number| 1E3 (not a symbolp)
Many different ACL2 entities have names, e.g., functions, macros,
variables, constants, packages, theorems, [theories], etc. Package
names are strings. All other names are symbols and may not be in
the \"KEYWORD\" package. Moreover, names of functions, macros,
constrained functions, and constants, other than those that are
predefined, must not be in the ``main Lisp package'' (which is
(\"LISP\" or \"COMMON-LISP\", according to whether we are following
CLTL1 or CLTL2). An analogous restriction on variables is given
below.
T, nil, and all names above except those that begin with ampersand
(&) are names of variables or constants. T, nil, and those names
beginning and ending with star (*) are constants. All other such
names are variables.
Note that names that start with ampersand, such as &rest, may be
lambda list keywords and are reserved for such use whether or not
they are in the CLTL constant lambda-list-keywords. (See pg 82 of
CLTL2.) That is, these may not be used as variables. Unlike
constants, variables may be in the main Lisp package as long as
they are in the original list of imports from that package to ACL2,
the list *common-lisp-symbols-from-main-lisp-package*, and do not
belong to a list of symbols that are potentially ``global.'' This
latter list is the value of *common-lisp-specials-and-constants*.
Our restrictions pertaining to the main Lisp package take into
account that some symbols, e.g., lambda-list-keywords and boole-c2,
are ``special.'' Permitting them to be bound could have harmful
effects. In addition, the Common Lisp language does not allow
certain manipulations with many symbols of that package. So, we
stay away from them, except for allowing certain variables as
indicated above.")
(NAME_THE_FORMULA_ABOVE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Name the Formula Above
When the theorem prover explicitly assigns a name, like *1, to a
formula, it has decided to prove the formula by induction.")
(NAT-LISTP
(NUMBERS LISTS ACL2-BUILT-INS)
"Recognizer for a true list of natural numbers
The predicate nat-listp tests whether its argument is a true list of
natural numbers.
Function: <nat-listp>
(defun nat-listp (l)
(declare (xargs :guard t))
(cond ((atom l) (eq l nil))
(t (and (natp (car l))
(nat-listp (cdr l))))))")
(NATP
(NUMBERS ACL2-BUILT-INS)
"A recognizer for the natural numbers
The natural numbers is the set of all non-negative integers,
{0,1,2,3,...}. Natp returns t if and only its argument is a natural
number, and nil otherwise.
The community book [arithmetic/natp-posp] has some lightweight rules
for reasoning about posp and natp, and is included in the
[arithmetic-1] library. For a somewhat heavier and more
comprehensive alternative, you may wish to instead see the
[arith-equivs] book.
Function: <natp>
(defun natp (x)
(declare (xargs :guard t))
(and (integerp x) (<= 0 x)))")
(NESTED-STOBJS
(STOBJ)
"Using [stobj]s that contain stobjs
For this topic we assume that you already understand the basics of
single-threaded objects in ACL2. See [stobj], and in particular,
see [defstobj]. The latter topic mentions briefly that a stobj
field can itself be a stobj or an array of stobjs. That discussion
is the subject of the present [documentation] topic.
Our presentation is in four sections. First we augment the
documentation for [defstobj] by explaining how stobjs may be
specified for fields in a new stobj definition. Then we explain an
aliasing problem, which accounts for a prohibition against making
direct calls to accessors and updaters involving stobj fields of
stobjs. Next, we introduce an ACL2 primitive, stobj-let, which
provides the only way to read and write stobj components of stobjs.
The final section provides precise documentation for stobj-let.
See also ACL2 community book demos/modeling/nested-stobj-toy-isa.lisp
for a worked example, which applies nested stobj structures to the
problem of defining interpreters. A variety of small additional
examples may be found in ACL2 community book
misc/nested-stobj-tests.lisp. For further discussion, you are
welcome to read the ``Essay on Nested Stobjs'', a long comment in
ACL2 source file other-events.lisp. However, this documentation
topic is intended to be self-contained for those familiar with
[stobj]s.
SECTION: Extension of [defstobj] to permit [stobj]s within stobjs
Recall that the :type keyword of a [defstobj] field descriptor can be
a ``type-indicator'' that specifies the type of the field as a
type-spec (see [type-spec]). For example, the following specifies
an integer field and a field that is an array of bytes.
(defstobj st
(int-field :type integer :initially 0)
(ar-field :type (array unsigned-byte (10)) :initially 0))
But the :type of a stobj field descriptor may instead be based on a
stobj. For example, the following sequence of three [events] is
legal. The first field descriptor of top, named sub1-field,
illustrates one new kind of value for :type: the name of a
previously-introduced stobj, which here is sub1. The second field
descriptor of top, named sub2-ar-field, illustrates the other new
kind of value for :type: an array whose elements are specified by
the name of a previously-introduced stobj, in this case, the stobj
sub2.
(defstobj sub1 fld1)
(defstobj sub2 fld2)
(defstobj top
(sub1-field :type sub1)
(sub2-ar-field :type (array sub2 (10))))
The :initially keyword is illegal for fields whose :type is a stobj
or an array of stobjs. Each such initial value is provided by a
corresponding call of the stobj creator for that stobj. In
particular, in the case of an array of stobjs, the stobj creator is
called once for each element of the array, so that the array
elements are distinct. For example, each element of sub2-ar-field
in the example above is initially provided by a separate call of
create-sub2. Each initial element is thus unique, and in particular
is distinct from the initial global value of the stobj. Similarly,
the initial global stobj for sub1 is distinct from the initial
sub1-field field of the global stobj for top, as these result from
separate calls of create-sub1.
When a stobj is used in a field of another stobj, we may refer to the
former field as a ``child stobj'' and the latter stobj as a
``parent stobj''. So in the example above, sub1-field is a child
stobj of type sub1 for parent stobj top, and sub2-ar-field is an
array of child stobjs of type sub2 for parent stobj top. A child
stobj has the same structural shape as the global stobj of its
type, but as explained above, these are distinct structures. We
follow standard terminology by saying ``isomorphic'' to indicate
the same structural shape. So for example, (the value of)
sub1-field is isomorphic to sub1, though these are distinct
structures.
ACL2 enforces the following restriction, which can allow for greater
efficiency in the raw Lisp code generated for stobj-let forms, as
per the discussion below about clearing memoization tables. If the
parent stobj is introduced by [defstobj] using keyword argument
:non-memoizable t, then this is required to have been the case for
every child stobj as well.
SECTION: An aliasing problem
Before introducing stobj-let below, we provide motivation for this
ACL2 primitive.
Consider the following [events].
(defstobj child fld)
(defstobj parent
(fld2 :type child))
Now suppose we could evaluate the following code, to be run
immediately after admitting the two [defstobj] events above.
(let* ((child (fld2 parent))
(child (update-fld 3 child)))
(mv child parent))
Now logically there is no change to parent: parent is passed through
unchanged. We can indeed prove that fact!
(thm (equal (mv-nth 1
(let* ((child (fld2 parent))
(child (update-fld 3 child)))
(mv child parent)))
parent))
But recall that stobjs are updated with destructive assignments. That
is, we really are updating (fld2 parent) to be the new value of
child, whether this is explained logically or not. Thus, evaluation
of the above [let*] form does in fact change the actual global
stobj, parent.
(Aside: Here is an explanation involving raw Lisp, for those who
might find this useful. We escape to raw Lisp and execute the
following; note that *the-live-parent* is the Lisp variable
representing the global value of parent.
(let ((parent *the-live-parent*))
(let* ((child (fld2 parent))
(child (update-fld 4 child)))
(mv child parent)))
Then, in raw Lisp, (fld (fld2 *the-live-parent*)) evaluates to 4,
illustrating the destructive update. End of Aside.)
Such aliasing can permit a change to a child stobj to cause a
logically-inexplicable change to the parent stobj. Similarly,
unfettered accessing of stobj fields can result in logically
inexplicable changes to the child stobj when the parent stobj is
changed. Thus, ACL2 disallows direct calls of stobj accessors and
updaters for fields whose :type is a stobj or an array of stobjs.
Instead, ACL2 provides stobj-let for reading and writing such
fields in a sound manner.
SECTION: Accessing and updating stobj fields of stobjs using
stobj-let
ACL2 provides a primitive, stobj-let, to access and update stobj
fields of stobjs, in a manner that avoids the aliasing problem
discussed above. In this section we provide an informal
introduction to stobj-let, using examples, to be followed in the
next section by precise documentation.
We begin by returning to a slight variant of the example above.
(defstobj child fld)
(defstobj parent
(fld2 :type child)
fld3)
The following form returns the result of updating the fld2 field of
parent, which is a stobj isomorphic to child, to have a value of 3.
Below we explain the terms ``bindings'', ``producer variables'',
``producer'', and ``consumer'', as well as how to understand this
form.
(stobj-let
((child (fld2 parent))) ; bindings
(child) ; producer variable(s)
(update-fld 3 child) ; producer
(update-fld3 'a parent)) ; consumer
The four lines under ``stobj-let'' just above can be understood as
follows.
* Bindings:
Bind child to (fld2 parent).
* Producer variable(s) and producer:
Then bind the variable, child, to the value of the producer,
(update-fld 3 child).
* Implicit update of parent:
Update fld2 of parent with the producer variable, child.
* Consumer:
Finally, return (update-fld3 'a parent).
Thus, the logical expansion of the stobj-let form above is the
following expression, though this is approximate (see below).
(let ((child (fld2 parent))) ; bindings
(let ((child (update-fld 3 child))) ; bind producer vars to producer
(let ((parent (update-fld2 child parent))) ; implicit update of parent
(update-fld3 'a parent))))
The bindings always bind distinct names to child stobjs of a unique
parent stobj, where the child stobj corresponds to the :type
associated with the indicated accessor in the [defstobj] form for
the parent stobj. Thus in this case, for the unique binding,
variable child is bound to the stobj of `type' child for accessor
fld2 of the parent stobj, parent. We refer to child from the
bindings as a ``stobj-let-bound variable''. Note also that the
``implicit extra step'' mentioned above is generated by
macroexpansion of stobj-let; it logically updates the parent with
new child values, just before calling the consumer. Implementation
note for those using [memoization]: destructive updating in raw
Lisp lets us omit this implicit extra step, though the raw Lisp
code generated for stobj-let will clear the memoization table for
every function taking the parent stobj as an input, if any child
stobj bound in the bindings is among the producer variables ---
unless the parent stobj was introduced by [defstobj] using keyword
argument :non-memoizable t.
The form above is equivalent to the form displayed just below, which
differs only in specifying an explicit stobj updater corresponding
to the stobj accessor, fld2. Here we show the default updater name,
whose name has \"UPDATE-\" prepended to the name of the accessor. But
if the :RENAMING field of the defstobj event specified a different
updater name corresponding to fld2, then that would need to be
included where we have added update-fld2 below.
(stobj-let
((child (fld2 parent) update-fld2)) ; bindings, including updater(s)
(child) ; producer variables
(update-fld 3 child) ; producer
(update-fld3 'a parent)) ; consumer
You can experiment using :[trans1] to see the single-step
macroexpansion of a stobj-let form in the logic. For example, here
is how that works for a stobj-let form that binds three fields and
updates two of them. Notice that because more than one field is
updated, an [mv-let] form is generated to bind the two fields to
their values returned by the producer, rather than a [let] form as
previously generated. First, let's introduce some events.
(defstobj child1 child1-fld)
(defstobj child2 child2-fld)
(defstobj child3 child3-fld)
(defstobj mom
(fld1 :type child1)
(fld2 :type child2)
(fld3 :type child3))
; Silly stub:
(defun update-last-op (op mom)
(declare (xargs :stobjs mom))
(declare (ignore op))
mom)
(defun new-mom (mom)
(declare (xargs :stobjs mom))
(stobj-let
((child1 (fld1 mom))
(child2 (fld2 mom))
(child3 (fld3 mom)))
(child1 child3)
(let* ((child1 (update-child1-fld 'one child1))
(child3 (update-child3-fld 'three child3)))
(mv child1 child3))
(update-last-op 'my-compute mom)))
Now let's look at the single-step macroexpansion of the above
stobj-let form.
ACL2 !>:trans1 (stobj-let
((child1 (fld1 mom))
(child2 (fld2 mom))
(child3 (fld3 mom)))
(child1 child3)
(let* ((child1 (update-child1-fld 'one child1))
(child3 (update-child3-fld 'three child3)))
(mv child1 child3))
(update-last-op 'my-compute mom))
(PROGN$
(LET
((CHILD1 (FLD1 MOM))
(CHILD2 (FLD2 MOM))
(CHILD3 (FLD3 MOM)))
(DECLARE (IGNORABLE CHILD1 CHILD2 CHILD3))
(MV-LET
(CHILD1 CHILD3)
(CHECK-VARS-NOT-FREE (MOM)
(LET* ((CHILD1 (UPDATE-CHILD1-FLD 'ONE CHILD1))
(CHILD3 (UPDATE-CHILD3-FLD 'THREE CHILD3)))
(MV CHILD1 CHILD3)))
(LET* ((MOM (UPDATE-FLD1 CHILD1 MOM))
(MOM (UPDATE-FLD3 CHILD3 MOM)))
(CHECK-VARS-NOT-FREE (CHILD1 CHILD2 CHILD3)
(UPDATE-LAST-OP 'MY-COMPUTE MOM))))))
ACL2 !>
If you try to evaluate a stobj-let form directly in the top-level
loop, rather than from within a function body, you will get an
error. The example above illustrates how stobj-let may be used in
function bodies; here is another example, presented using an edited
log.
ACL2 !>(defstobj child fld)
Summary
Form: ( DEFSTOBJ CHILD ...)
Rules: NIL
Time: 0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
CHILD
ACL2 !>(defstobj parent
(fld2 :type child)
fld3)
Summary
Form: ( DEFSTOBJ PARENT ...)
Rules: NIL
Time: 0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
PARENT
ACL2 !>(defun f (parent)
(declare (xargs :stobjs parent))
(stobj-let
((child (fld2 parent))) ; bindings
(child) ; producer variables
(update-fld 3 child) ; producer
(update-fld3 'a parent))) ; consumer
[[output omitted]]
F
ACL2 !>(f parent)
<parent>
ACL2 !>(defun check-f (parent)
; returns the value of the field of the child stobj
(declare (xargs :stobjs parent))
(stobj-let
((child (fld2 parent))) ; bindings
(val) ; producer variables
(fld child) ; producer
val)) ; consumer
[[output omitted]]
CHECK-F
ACL2 !>(check-f parent)
3
ACL2 !>
Notice that the second function defined above, check-f, uses a
stobj-let form that returns an ordinary value: it reads a value
from a child stobj, but does not write to the child stobj, as
indicated by the lack of a child stobj among the producer
variables. So for that stobj-let form, there is no implicit extra
step.
We labeled a stobj-let expansion above as ``approximate'' for two
reasons, which we give here informally. (Now you know how to apply
:[trans1] to that stobj-let call to see the precise expansion.)
First, stobj-let declares the stobj-let-bound variables to be
ignorable for the top let bindings. Second, and more importantly,
stobj-let imposes the following restrictions on the producer and
consumer, to avoid the aliasing problem: it disallows references to
the parent stobj in the producer and it also disallows references
to any bound stobj (i.e., bound in the bindings) in the consumer.
We conclude this section with examples based on a slight variation of
the nested stobj example from the first section above. These events
can also be found in ACL2 community book
misc/nested-stobj-tests.lisp, immediately under the following
comment:
; As promised in :doc stobj-let, we begin with an example from that :doc.
Note that some lemmas were needed in order to complete the [guard]
proof for the function update-top, which may be found in the above
file; they are omitted below.
First we introduce three stobjs.
(defstobj kid1 fld1)
(defstobj kid2 fld2)
(defstobj mom
(kid1-field :type kid1)
(kid2-ar-field :type (array kid2 (5)))
last-op)
The next function takes a given index and a mom stobj, and swaps the
value stored in the stobj in mom's kid2-ar-field array at that
index with the value stored in the stobj in mom's kid1-field field.
(defun mom-swap-fields (index mom)
(declare (xargs :stobjs mom
:guard (and (natp index)
(< index (kid2-ar-field-length mom)))))
(stobj-let
((kid1 (kid1-field mom))
(kid2 (kid2-ar-fieldi index mom)))
(kid1 kid2)
(let* ((val1 (fld1 kid1))
(val2 (fld2 kid2))
(kid1 (update-fld1 val2 kid1))
(kid2 (update-fld2 val1 kid2)))
(mv kid1 kid2))
(update-last-op 'swap mom)))
Function mom.kid1-fld1 stores a given value in the given mom's
kid1-fld1 field.
(defun mom.kid1-fld1 (val mom)
(declare (xargs :stobjs mom))
(stobj-let
((kid1 (kid1-field mom)))
(kid1)
(update-fld1 val kid1)
(update-last-op val mom)))
We next combine the two functions above, according to an op argument,
as indicated by the following definition.
(defun update-mom (op mom)
(declare (xargs :stobjs mom))
(cond ((and (consp op)
(eq (car op) 'swap)
(natp (cdr op))
(< (cdr op) (kid2-ar-field-length mom)))
(mom-swap-fields (cdr op) mom))
(t (mom.kid1-fld1 op mom))))
The following checker function uses a stobj-let form like the ones
above, a major difference being that the producer variable is not a
stobj, since the producer does not modify any stobjs.
(defun check-update-mom (index val1 val2 last-op mom)
(declare (xargs :stobjs mom
:mode :program
:guard
(or (null index)
(and (natp index)
(< index (kid2-ar-field-length mom))))))
(and (equal (last-op mom) last-op)
(stobj-let
((kid1 (kid1-field mom))
(kid2 (kid2-ar-fieldi index mom)))
(val) ; producer variables
(and (equal val1 (fld1 kid1))
(equal val2 (fld2 kid2)))
val)))
Now let us run our update function to populate some fields within the
mom stobj.
(let* ((mom ; set mom to (3 (x0 x1 x2 x3 x4))
(update-mom 3 mom))
(mom ; set mom to (x1 (x0 3 x2 x3 x4))
(update-mom '(swap . 1) mom))
(mom ; set mom to (7 (x0 3 x2 x3 x4))
(update-mom 7 mom))
(mom ; set mom to (x0 (7 3 x2 x3 x4))
(update-mom '(swap . 0) mom))
(mom ; set mom to (5 (7 3 x2 x3 x4))
(update-mom 5 mom))
(mom ; set mom to (7 (5 3 x2 x3 x4))
(update-mom '(swap . 0) mom)))
mom)
Are the above values of 7, 5, and 3 as expected, with a last
operation being a swap? Yes!
ACL2 !>(and (check-update-mom 0 7 5 'swap mom)
(check-update-mom 1 7 3 'swap mom))
T
ACL2 !>
Notice that above, we never tried to access two different entries of
the array. This can be done, but we need to bind two different
stobjs to those fields. Fortunately, congruent stobjs make this
possible; see [defstobj], in particular the discussion of congruent
stobjs. Since we want to bind two stobjs to values in the array
that are isomorphic to the stobj kid2, we introduce a stobj
congruent to kid2.
(defstobj kid2a fld2a :congruent-to kid2)
Then we can define our swapping function as follows. The [guard]
proof obligation includes the requirement that the two indices be
distinct, again to avoid an aliasing problem.
(defun mom-swap-indices (i1 i2 mom)
(declare (xargs :stobjs mom
:guard (and (natp i1)
(< i1 (kid2-ar-field-length mom))
(natp i2)
(< i2 (kid2-ar-field-length mom))
(not (equal i1 i2)))))
(stobj-let
((kid2 (kid2-ar-fieldi i1 mom))
(kid2a (kid2-ar-fieldi i2 mom)))
(kid2 kid2a)
(let* ((val2 (fld2 kid2))
(val2a (fld2 kid2a))
(kid2 (update-fld2 val2a kid2))
(kid2a (update-fld2 val2 kid2a)))
(mv kid2 kid2a))
mom))
The aforementioned community book, misc/nested-stobj-tests.lisp,
contains a corresponding checker immediately following this
definition.
SECTION: Precise documentation for stobj-let
General Form:
(stobj-let
BINDINGS
PRODUCER-VARIABLES
PRODUCER
CONSUMER)
where PRODUCER-VARIABLES is a non-empty true list of legal variable
names without duplicates, PRODUCER and CONSUMER are expressions,
and BINDINGS is a list subject to the following requirements.
BINDINGS is a non-empty true list of tuples, each of which has the
form (VAR ACCESSOR) or (VAR ACCESSOR UPDATER). There is a stobj
name, ST, previously introduced by [defstobj] (not [defabsstobj]),
such that each accessor is of the form (ACC ST) or (ACCi I ST),
with the same stobj name (ST) for each binding. In the case (ACC
ST), ACC is the accessor for a non-array field of ST. In the case
(ACCi I ST), ACCi is the accessor for an array field of ST, and I
is either a variable, a natural number, a list (quote N) where N is
a natural number, or a symbol introduced by [defconst]. If UPDATER
is supplied, then it is a symbol that is the name of the stobj
updater for the field of ST accessed by ACCESSOR. If UPDATER is not
supplied, then for the discussion below we consider it to be,
implicitly, the symbol in the same package as the function symbol
of ACCESSOR (i.e., ACC or ACCi), obtained by prepending the string
\"UPDATE-\" to the [symbol-name] of that function symbol. Finally,
ACCESSOR has a [signature] specifying a return value that is either
ST or is stobj that is congruent to ST.
If the conditions above are met, then the General Form expands to the
one of the following expressions, depending on whether the list
PRODUCER-VARIABLES has one member or more than one member,
respectively. (But see below for extra code that may be inserted if
there are stobj array accesses in BINDINGS.) Here we write
STOBJ-LET-BOUND-VARS for the list of variables VAR discussed above,
i.e., for (strip-cars BINDINGS). And, we write UPDATES for the
result of mapping through PRODUCER-VARIABLES and, for each variable
VAR that has a binding (VAR ACCESSOR UPDATER) in BINDINGS (where
UPDATER may be implicit, as discussed above), collect into UPDATES
the tuple (ST (UPDATER VAR ST)).
For PRODUCER-VARIABLES = (PRODUCER-VAR):
(let BINDINGS
(declare (ignorable . STOBJ-LET-BOUND-VARIABLES))
(let ((PRODUCER-VAR PRODUCER))
(let* UPDATES
CONSUMER)))
Otherwise:
(let BINDINGS
(declare (ignorable . STOBJ-LET-BOUND-VARIABLES))
(mv-let PRODUCER-VARS
PRODUCER
(let* UPDATES
CONSUMER)))
Moreover, ACL2 places restrictions on the resulting expression: ST
must not occur free in PRODUCER, and every variable in
STOBJ-LET-BOUND-VARIABLES must not occur free in CONSUMER.
Stobj-let forms can be evaluated using ordinary objects in theorem
contexts, much as any form. They can also, of course, appear in
function bodies. However, a stobj-let form cannot be evaluated
directly in the top-level loop or other top-level contexts for
execution (such as during [make-event] expansion).
Finally, let FORM denote the form displayed above (either case). We
explain how FORM is actually replaced by an expression of the form
(PROGN$ ... FORM). This expression generates an extra [guard] proof
obligation, which guarantees that no aliasing occurs from binding
two stobj-let-bound variables to the same array access. So fix a
stobj array accessor ACCi for which some stobj is bound to (ACCi I
ST) in BINDINGS; we define an expression ACCi-CHECK as follows.
Collect up all such index expressions I, where if I is of the form
(quote N) then replace I by N. If the resulting list of index
expressions for ACCi consists solely of distinct numbers, or if it
is of length 1, then no extra check is generated for ACCi.
Otherwise, let ACCi-CHECK be the form (chk-no-duplicatesp (list I1
... Ik)), where I1, ..., Ik are the index expressions for ACCi.
Note: chk-no-duplicatesp is a function that returns nil, but has a
[guard] that its argument is an [eqlable-listp] that satisfies
[no-duplicatesp]. Finally, FORM is replaced by (PROGN$ CHK1 ...
CHKn FORM), where the CHKm range over all of the above ACCi-CHECK.")
(NEVER-MEMOIZE
(MEMOIZE)
"Mark a function as unsafe to memoize.
Logically, this function just returns nil. But execution of
(never-memoize fn) records that fn must never be memoized, so that
any attempt to memoize fn will fail.
Any function can be marked as unsafe to memoize; in fact, fn need not
even be defined at the time it is marked.
This is useful for prohibiting the memoization of functions that are
known to involve destructive functions like nreverse.")
(NFIX
(NUMBERS ACL2-BUILT-INS)
"Coerce to a natural number
Nfix simply returns any natural number argument unchanged, returning
0 on an argument that is not a natural number. Also see [ifix], see
[rfix], see [realfix], and see [fix] for analogous functions that
coerce to an integer, a rational number, a real, and a number,
respectively.
Nfix has a [guard] of t.
Function: <nfix>
(defun nfix (x)
(declare (xargs :guard t))
(if (and (integerp x) (>= x 0)) x 0))")
(NIL-GOAL
(DEBUGGING)
"How to proceed when the prover generates a goal of nil
At the end of a failed proof, one typically sees so-called ``key
checkpoints'' (see [set-gag-mode]). These may be annotated as
follows.
[NOTE: A goal of NIL was generated. See :DOC nil-goal.]
This [documentation] topic gives some ideas about how to think about
the situation described by that message: some goal has reduced to
nil.
Suppose then that you see the above NOTE. If you look back at the
proof log, even with [gag-mode] enabled, you will see a message
saying that a goal of NIL ``has been generated''. This may indicate
that the original goal is not a theorem, since most of the prover's
activity is to replace a goal by an equivalent conjunction of its
child subgoals. However, if some ancestor of the nil goal has
undergone a process other than simplification or destructor
elimination --- fertilization (heuristic use of equalities),
generalization, or elimination of irrelevance --- then it is quite
possible that the prover got to the nil goal by replacing a goal by
a stronger (and perhaps false) conjunction of child subgoals.
At present, if you are using [gag-mode] (the default) then you will
need to issue the command :[pso] (``Print Saved Output'') if you
want to see whether the situation above has occurred. However, that
might not be necessary. A good rule of thumb is that if the nil
goal is under more than one level of induction (e.g., with a prefix
``*i.j'' such as ``Subgoal *1.1/2.2''), then there is some
likelihood that the situation above did indeed occur, and you can
spend your time and energy looking at the key checkpoints printed
in the summary to see if they suggest useful [rewrite] rules to
prove. On the other hand, if the nil goal is at the top level (e.g.
with a name not starting with ``*'', such as ``Subgoal 3.2''), then
the original conjecture is probably not a theorem. If you do not
quickly see why that is the case, then you might find it useful to
issue the command :[pso] to see which case reduced to nil, in order
to get insight about how the theorem might be falsified.")
(NINTH
(NTH ACL2-BUILT-INS)
"Ninth member of the list
See any Common Lisp documentation for details.")
(NO-DUPLICATESP
(LISTS ACL2-BUILT-INS)
"Check for duplicates in a list
General Forms:
(no-duplicatesp x)
(no-duplicatesp x :test 'eql) ; same as above (eql as equality test)
(no-duplicatesp x :test 'eq) ; same, but eq is equality test
(no-duplicatesp x :test 'equal) ; same, but equal is equality test
(no-duplicatesp lst) is true if and only if no member of lst occurs
twice in lst. The optional keyword, :TEST, has no effect logically,
but provides the test (default [eql]) used for comparing elements
of lst.
The [guard] for a call of no-duplicatesp depends on the test. In all
cases, the argument must satisfy [true-listp]. If the test is
[eql], then the argument must satisfy [eqlable-listp]. If the test
is [eq], then the argument must satisfy [symbol-listp].
See [equality-variants] for a discussion of the relation between
no-duplicatesp and its variants:
(no-duplicatesp-eq x lst) is equivalent to (no-duplicatesp x lst
:test 'eq);
(no-duplicatesp-equal x lst) is equivalent to (no-duplicatesp x lst
:test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function no-duplicatesp-equal.
Function: <no-duplicatesp-equal>
(defun no-duplicatesp-equal (l)
(declare (xargs :guard (true-listp l)))
(cond ((endp l) t)
((member-equal (car l) (cdr l)) nil)
(t (no-duplicatesp-equal (cdr l)))))")
(NO-DUPLICATESP-EQ (POINTERS)
"See [no-duplicatesp].")
(NO-DUPLICATESP-EQUAL (POINTERS)
"See [no-duplicatesp].")
(NO-THANKS (POINTERS)
"See [hints] for keyword :no-thanks.")
(NON-EXEC
(GUARD ACL2-BUILT-INS)
"Mark code as non-executable
Non-exec is a macro such that logically, (non-exec x) is equal to x.
However, the argument to a call of non-exec need not obey the usual
syntactic restrictions for executable code, and indeed, evaluation
of a call of non-exec will result in an error. Moreover, for any
form occurring in the body of a function (see [defun]) that is a
call of non-exec, no guard proof obligations are generated for that
form.
The following example, although rather contrived, illustrates the use
of non-exec. One can imagine a less contrived example that
efficiently computes return values for a small number of fixed
inputs and, for other inputs, returns something logically
``consistent'' with those return values.
(defun double (x)
(case x
(1 2)
(2 4)
(3 6)
(otherwise (non-exec (* 2 x)))))
We can prove that double is compliant with Common Lisp (see [guard])
and that it always computes (* 2 x).
(verify-guards double)
(thm (equal (double x) (* 2 x)))
We can evaluate double on the specified arguments. But a call of
non-exec results in an error message that reports the form that was
supplied to non-exec.
ACL2 !>(double 3)
6
ACL2 !>(double 10)
ACL2 Error in TOP-LEVEL: ACL2 has been instructed to cause an error
because of an attempt to evaluate the following form (see :DOC non-
exec):
(* 2 X).
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
ACL2 !>
During proofs, the error is silent; it is ``caught'' by the proof
mechanism and generally results in the introduction of a call of
[hide] during a proof.
Also see [defun-nx] for a utility that makes every call of a function
non-executable, rather than a specified form. The following
examples contrast non-exec with [defun-nx], in particular
illustratating the role of [non-exec] in avoiding guard proof
obligations.
; Guard verification fails:
(defun-nx f1 (x)
(declare (xargs :guard t))
(car x))
; Guard verification succeeds after changing the guard above:
(defun-nx f1 (x)
(declare (xargs :guard (consp x)))
(car x))
; Guard verification succeeds:
(defun f2 (x)
(declare (xargs :guard t))
(non-exec (car x)))
; Evaluating (g1) prints \"Hello\" before signaling an error.
(defun g1 ()
(f1 (cw \"Hello\")))
; Evaluating (g2) does not print before signaling an error.
(defun g2 ()
(non-exec (cw \"Hello\")))
; Evaluating (h1) gives a guard violation for taking reciprocal of 0.
(defun h1 ()
(f1 (/ 1 0)))
; Evaluating (h2) does not take a reciprocal, hence there is no guard
; violation for that; we just get the error expected from using non-exec.
(defun h2 ()
(non-exec (/ 0)))")
(NON-EXECUTABLE (POINTERS)
"See [xargs] for keyword :non-executable.")
(NON-LINEAR-ARITHMETIC
(LINEAR)
"Non-linear Arithmetic
This documentation topic is divided into two parts. We first discuss
the practical aspect of how to use the non-linear arithmetic
extension to ACL2, and then the theory behind it. We assume that
the reader is familiar with the material in [linear-arithmetic] and
that on :[linear] rules.
We begin our discussion of how to use non-linear arithmetic with a
simple example. Assume that we wish to prove:
(thm
(implies (and (rationalp x)
(rationalp y)
(rationalp z)
(< 0 y)
(< x (* y z)))
(< (floor x y) z)))
Note that (floor x y) <= (/ x y). Note also that if we divide both
sides of x < (* y z) by y, since 0 < y, we obtain (/ x y) < z. By
chaining these two inequalities together, we get the inequality we
desired to prove.
We now proceed with our example session:
(skip-proofs
(progn
; Since the truth of this theorem depends on the linear properties
; of floor, we will need the linear lemma:
(defthm floor-bounds-1
(implies (and (rationalp x)
(rationalp y))
(and (< (+ (/ x y) -1)
(floor x y))
(<= (floor x y)
(/ x y))))
:rule-classes ((:linear :trigger-terms ((floor x y)))))
; We now disable floor, so that the linear lemma will be used.
(in-theory (disable floor))
; We create five rewrite rules which we will use during non-linear
; arithmetic. The necessity for these is due to one of the differences in
; ACL2's behaviour when non-linear arithmetic is turned on. Although
; the conclusions of linear lemmas have always been rewritten before
; they are used, now, when non-linear arithmetic is turned on, the
; conclusions are rewritten under a different theory than under ``normal''
; rewriting. This theory is also used in other, similar, circumstances
; described below.
(defthm |arith (* -1 x)|
(equal (* -1 x)
(- x)))
(defthm |arith (* 1 x)|
(equal (* 1 x)
(fix x)))
(defthm |arith (* x (/ x) y)|
(equal (* x (/ x) y)
(if (equal (fix x) 0)
0
(fix y))))
(defthm |arith (* y x)|
(equal (* y x)
(* x y)))
(defthm |arith (fix x)|
(implies (acl2-numberp x)
(equal (fix x)
x))))
) ; End skip-proofs.
; We disable the above rewrite rules from normal use.
(in-theory (disable |arith (* -1 x)|
|arith (* 1 x)|
|arith (* x (/ x) y)|
|arith (* y x)|
|arith (fix x)|))
; We create an arithmetic-theory. Note that we must give a quoted
; constant for the theory --- none of the normal [theory-functions]
; are applicable to in-arithmetic-theory.
(in-arithmetic-theory '(|arith (* -1 x)|
|arith (* 1 x)|
|arith (* x (/ x) y)|
|arith (* y x)|
|arith (fix x)|))
; We turn non-linear arithmetic on.
(set-non-linearp t)
; We can now go ahead and prove our theorem.
(thm
(implies (and (rationalp x)
(rationalp y)
(rationalp z)
(< 0 y)
(< x (* y z)))
(< (floor x y) z)))
The above example illustrates the two practical requirements for
using non-linear arithmetic in ACL2. First, one must set up an
arithmetic-theory. Usually, one would not set up an
arithmetic-theory on one's own but would instead load a library
book or books which do so. Second, one must turn the non-linear
arithmetic extension on. This one must do explicitly --- no book
can do this for you.
For a brief discussion of why this is so, even though
(set-non-linearp t) is an embeddable event, see
[ACL2-defaults-table] (in particular, the final paragraph). (Note
that (set-non-linearp t) modifies the acl2-defaults-table.) Also
see [set-non-linearp], see [embedded-event-form], and see [events].
You can also enable non-linear arithmetic with the hint :nonlinearp
t. See [hints]. We, in fact, recommend the use of a hint which will
enable nonlinear arithmetic only when the goal has stabilized under
rewriting. Using [default-hints] can make this easier.
(defun nonlinearp-default-hint (stable-under-simplificationp hist pspv)
(cond (stable-under-simplificationp
(if (not (access rewrite-constant
(access prove-spec-var pspv :rewrite-constant)
:nonlinearp))
'(:computed-hint-replacement t :nonlinearp t)
nil))
((access rewrite-constant
(access prove-spec-var pspv :rewrite-constant)
:nonlinearp)
(if (not (equal (caar hist) 'SETTLED-DOWN-CLAUSE))
'(:computed-hint-replacement t :nonlinearp nil)
nil))
(t nil)))
(set-default-hints '((nonlinearp-default-hint stable-under-simplificationp
hist pspv)))
This has proven to be a helpful strategy which allows faster proof
times.
We now proceed to briefly describe the theory behind the non-linear
extension to ACL2. In [linear-arithmetic] it was stated that,
``[L]inear polynomial inequalities can be combined by
cross-multiplication and addition to permit the deduction of a
third inequality....'' That is, if
0 < poly1,
0 < poly2,
and c and d are positive rational constants, then
0 < c*poly1 + d*poly2.
Similarly, given the above,
0 < poly1*poly2.
In the linear arithmetic case, we are taking advantage of the facts
that multiplication by a positive rational constant does not change
the sign of a polynomial and that the sum of two positive
polynomials is itself positive. In the non-linear arithmetic case,
we are using the fact that the product of two positive polynomials
is itself positive.
For example, suppose we have the three assumptions:
p1: 3*x*y + 7*a < 4
p2: 3 < 2*x or p2': 0 < -3 + 2*x
p3: 1 < y or p3': 0 < -1 + y,
and we wish to prove that a < 0. As described elsewhere (see
[linear-arithmetic]), we proceed by assuming the negation of our
goal:
p4: 0 <= a,
and looking for a contradiction.
There are no cancellations which can be performed by linear
arithmetic in the above situation. (Recall that two polynomials are
cancelled against each other only when they have the same largest
unknown.) However, p1 has a product as its largest unknown, and for
each of the factors of that product there is a poly that has that
factor as a largest unknown. When non-linear arithmetic is enabled,
ACL2 will therefore multiply p1' and p2' obtaining
p5: 0 < 3 + -2*x + -3*y + 2*x*y.
The addition of this polynomial will allow cancelation to continue
and, in this case, we will prove our goal. Thus, just as ACL2 adds
two polynomials together when they have the same largest unknown of
opposite signs in order to create a new ``smaller'' polynomial; so
ACL2 multiplies polynomials together when the product of their
largest unknowns is itself the largest unknown of another
polynomial. As the use of :[linear] lemmas to further seed the
arithmetic database may allow cancellation to proceed, so may the
use of non-linear arithmetic.
This multiplication of polynomials is the motivation for an
arithmetic-theory distinct from than the normal one. Because this
may be done so often, and because the individual factors have
presumably already been rewritten, it is important that this be
done in an efficient way. The use of a small, specialized, theory
helps avoid the repeated application of rewrite rules to already
stabilized terms.
Subtopics
[Set-non-linearp]
To turn on or off non-linear arithmetic reasoning")
(NONLINEARP (POINTERS)
"See [hints] for keyword :nonlinearp.")
(NONNEGATIVE-INTEGER-QUOTIENT
(NUMBERS ACL2-BUILT-INS)
"Natural number division function
Example Forms:
(nonnegative-integer-quotient 14 3) ; equals 4
(nonnegative-integer-quotient 15 3) ; equals 5
(nonnegative-integer-quotient i j) returns the integer quotient of
the integers i and (non-zero) j, i.e., the largest k such that (* j
k) is less than or equal to i. Also see [floor], see [ceiling] and
see [truncate], which are derived from this function and apply to
rational numbers.
The [guard] of (nonnegative-integer-quotient i j) requires that i is
a nonnegative integer and j is a positive integer.
Function: <nonnegative-integer-quotient>
(defun nonnegative-integer-quotient (i j)
(declare (xargs :guard (and (integerp i)
(not (< i 0))
(integerp j)
(< 0 j))))
(if (or (= (nfix j) 0) (< (ifix i) j))
0
(+ 1
(nonnegative-integer-quotient (- i j)
j))))")
(NONTAUTOLOGICAL_SUBGOALS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Prover output omits some details
The theorem prover's proof output is intended to suggest an outline
of the reasoning process employed by its proof engine, which is
virtually always more than is necessary for the ACL2 user. In
particular, the output often omits subgoals that are sufficiently
trivial, including tautologies.")
(NORMALIZE (POINTERS)
"See [xargs] for keyword :normalize.")
(NORMED
(HONS)
"Normed objects are ACL2 Objects that are \"canonical\" or \"unique\" in a
certain sense.
In Common Lisp, we can tell whether an ACL2 object is normed or not,
but there is no way for an ordinary ACL2 function to see whether an
object is normed. Hence, whether or not an object is normed is an
implementation-level concept.
The fundamental property of normed objects is that if A and B are
both normed, then (equal A B) holds if and only if (eql A B) holds.
For strings and conses, (eql A B) holds only when (eq A B), so any
normed conses or strings are [equal] precisely when they are [eq].
The potential benefits of having normed objects include:
constant-time equality comparisons, reduced memory usage, fast
association lists, and function memoization.
Note that in our implementation, all symbols, characters, and numbers
are automatically normed, and whenever a cons is normed its car and
cdr must also be normed.
The Meaning of Normed in Common Lisp.
Recall that the ACL2 Objects are certain \"good\" Common Lisp symbols,
characters, strings, and numbers, and the conses which can be
recursively formed from these good atoms.
Not all properties of these objects are visible in the ACL2 logic. An
example of an invisible property is the pointer identity of an
object. For example, suppose we write the following.
(defconst *x* (cons 1 2))
(defconst *y* (cons 1 2))
In Common Lisp, [cons] is guaranteed to provide a new pair that is
distinct from any previously created pair, so we know that *x* and
*y* will be distinct objects and we will be able to tell them apart
from one another using eq. But this difference is not visible in
the ACL2 logic, and no ACL2 function can tell *x* apart from *y*.
The normed-ness of an object is a similarly invisible property. In
Common Lisp, invisible to ACL2, we maintain a data structure called
a \"Hons Space\" that records which objects are normed. So, being
normed is not an intrinsic property of an object, but instead is
determined by whether the object is mentioned in this Hons Space.
Notes about Garbage Collection.
The Hons Space includes tables with pointers to every normed cons and
string. One consequence of this is that normed objects cannot be
reclaimed by Lisp's ordinary garbage collector, even after they
have become unreachable from the perspective of an ACL2 program.
For CCL and GCL users only, [hons-wash] is a special kind of garbage
collection that allows normed conses to be reclaimed. For other
Lisps, the only option is to occasionally, manually clear out these
Hons Space tables with [hons-clear].")
(NOT
(BASICS ACL2-BUILT-INS)
"Logical negation
Not is the ACL2 negation function. The negation of nil is t and the
negation of anything else is nil.
Not is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <not>
(defun not (p)
(declare (xargs :guard t))
(if p nil t))")
(NOTE-2-0
(RELEASE-NOTES)
"ACL2 Version 2.0 (July, 1997) Notes
This is the first version of ACL2 released under the copyright of the
University of Texas (UT). Future releases of ACL2 will be made from
UT rather than Computational Logic, Inc. (CLI). Version 2.0 is just
Version 1.9 as released by CLI, with a few bugs fixed.
A bug causing an infinite loop was fixed in functional instantiation.
The bug manifested itself when two conditions occurred
simultaneously: First, the functional substitution replaces a
function symbol, e.g., FOO, with a LAMBDA expression containing a
free variable (a variable not among in the LAMBDA formals). And,
second, in one of the constraints being instantiated there is a
call of the function symbol FOO within the scope of another LAMBDA
expression. Unless you used such a functional substitution, this
bug fix will not affect you.
Less important notes:
The implementation of PRINC$ was changed so that it was no longer
sensitive to the external setting of *print-base* and other Common
Lisp special variables.
Typographical errors were fixed in the documentation.")
(NOTE-2-1
(RELEASE-NOTES)
"ACL2 Version 2.1 (December, 1997) Notes
The identity function [case-split] has been added. It is similar to
[force] but causes an immediate split of the top-level goal on
whether the indicated hypothesis is true.
Less important notes:
Minor bugs in the documentation were fixed.")
(NOTE-2-2
(RELEASE-NOTES)
"ACL2 Version 2.2 (August, 1998) Notes
Important changes:
A bug was fixed in the compile command, :comp. The compiled code
produced by :comp in previous versions could be wildly incorrect
because of a confusion between the printer and the reader regarding
what was the current Lisp *package*. This bug could manifest itself
only if you used the :comp command to compile previously uncompiled
functions while the current package was different from \"ACL2\". What
happened in that situation depended upon what symbols were imported
into your current package. The most likely behavior is that the
compiler would break or complain or the resulting compiled code
would call functions that did not exist.
There have been no other important changes to the code.
However, this release contains some useful new books, notably those
on the books subdirectories cli-misc and ihs. Both have README
files. The ihs books provide support for integer hardware
specifications. These books were crucial to Bishop Brock's
successful modeling of the Motorola CAP. We thank Bishop for
producing them and we thank all those who worked so hard to get
these books released. We highly recommend the ihs books to those
modeling ALUs and other arithmetic components of microprocessors or
programming languages.
In previous versions of ACL2, the arithmetic books, found on
books/arithmetic/, included the addition of several unproved axioms
stating properties of the rationals that we believed could be
derived from our ``official'' axioms but which we had not
mechanically proved. The axioms were found in the book
rationals-with-axioms.lisp, which was then used in the uppermost
arithmetic books top.lisp and top-with-meta.lisp. John Cowles has
now provided us with ACL2 proofs of those ``axioms'' and so in this
release you will find both rationals-with-axioms.lisp and
rationals-with-axioms-proved.lisp. The former is provided for
compatibility's sake. The latter is identical but contains defthms
where the former contains defaxioms. The top-most books have been
rebuilt using ``-axioms-proved'' book. Thanks John.
Less important notes:
Bishop Brock found a bug in translated-acl2-unwind-protectp4. Jun
Sawada reported a bug in linear arithmetic that caused us not to
prove certain trivial theorems concluding with (not (equal i j)).
We have fixed both.
We now prohibit definitions that call certain event commands such as
DEFTHM and TABLE because our Common Lisp implementations of them
differ from their ACL2 meanings (so that compiled books can be
loaded correctly and efficiently).
Minor bugs in the documentation were fixed.")
(NOTE-2-3
(RELEASE-NOTES)
"ACL2 Version 2.3 (October, 1998) Notes
Important changes:
Versions of ACL2 preceding this one contain a subtle soundness bug!
We found a flaw in our detection of [subversive-recursions]. The
bug allowed some subversive recursions to slip through undetected.
We believe it would have been difficult to have exploited this flaw
inadvertently. In particular, the following five conditions are
necessary.
(1) Introduce a constrained function, say f, via an encapsulate.
(2) In the same encapsulation, define a clique of mutually recursive
functions. This clique must be non-local and in :logic mode.
(3) In that mutually recursive clique, use the constrained function
f (perhaps indirectly) so that the termination argument for the
clique depends on properties of the witness for f. Thus, f or some
other function dependent upon f, must be used in an argument in a
recursive call or in a term governing a recursive call.
Furthermore, the use of f must be such that the termination proof
cannot be done without exploiting properties of the witness for f.
Other uses of the constrained functions in the clique are ok.
(4) Fail to include the exploited properties of f among the
constraints of the encapsulation.
(5) Later, outside the encapsulation, explicitly use a functional
instantiation in which f is replaced by a function not enjoying the
crucial properties.
See [subversive-recursions] for details.
Less important notes:
We have begun to write some introductory tutorial material for those
who wish to learn to program in ACL2. Most of this material is
HTML-based. See the Hyper-Card on the ACL2 home page.
The documentation of [verify-guards] was improved to explain why one
might wish to verify the ``guards'' of a defthm event. The missing
documentation was noticed by John Cowles.
A bug was fixed in cross fertilization. The bug caused the system to
report that it had substituted one term for another when in fact no
substitution occurred. The bug was noticed by Bill McCune.")
(NOTE-2-4
(RELEASE-NOTES)
"ACL2 Version 2.4 (August, 1999) Notes
Important changes:
We corrected a soundness bug in Version 2.3 related to the handling
of [immediate-force-modep]. The bad behavior was noticed by Robert
Krug. Thanks!
We corrected a bug that permitted [verify-guards] to accept a
function even though a subfunction had not yet had its guards
verified. Thanks to John Cowles for noticing this.
User defined single-threaded objects are now supported. See [stobj].
Less important notes:
We corrected a bug that prevented the intended expansion of some
recursive function calls.
We changed the handling of the primitive function [illegal], which is
logically defined to be nil but which is programmed to signal an
error, so that when it is evaluated as part of a proof, it does not
signal an error. The old handling of the function prevented some
guard proofs involving [the] or [let]s with internal declarations.
We corrected a bug that permitted some LOCAL DEFAXIOM events to slip
into certified books.
We corrected a bug that prevented the correct undoing of certain
DEFPKG forms.
Changes were made to support CMU Lisp. Pete Manolios helped with
these changes.
Changes were made to make the make files more compatible with Allegro
Common Lisp. Jun Sawada, who has been a great help with keeping
ACL2 up and running at UT on various platforms, was especially
helpful. Thanks Jun.")
(NOTE-2-5
(RELEASE-NOTES)
"ACL2 Version 2.5 (June, 2000) Notes
Important Changes:
Concurrent with the release of ACL2 Version 2.5 is the publication of
two books about ACL2. See the ``Books and Papers about ACL2 and Its
Applications'' on the ACL2 Home Page.
The books subdirectory now contains many new certifiable books,
including solutions to the exercises in the two published books and
full scripts for the case studies. See books/README.html.
Improved Unix Makefile support for book certification has also been
written. See books/README.html.
The list of symbols in *acl2-exports* has been considerably expanded.
If you have packages built by importing *acl2-exports* you might
want to look carefully at the new value of that constant. The new
value includes all :logic mode functions as of Version 2.5, as well
as all documented macros and all built-in theorem names.
[Include-book] and [certify-book] were modified to have some
additional keyword arguments. It is possible to certify a book
containing [defaxiom] and/or [skip-proofs] events and get warning
messages or errors signaled, according to the settings of these new
flags. In addition, it is possible to specify in include-book
whether the book must be certified (under penalty of error if not).
The default values of these new arguments cause warnings to be
printed rather than errors signaled.
The above change involved altering the form of certificate files.
When books certified under previous versions are included, more
warnings will be generated because these books are considered
possibly to contain defaxiom and/or skip-proofs events.
We anticipate further changes to this aspect of books and consider
the current mechanisms (for controlling whether warnings or errors
are signaled) just a prototype. See also the discussion below of
``soundness related'' warnings. Your suggestions are welcome.
A discrepancy between ACL2 and Common Lisp was fixed, having to do
with declare ignore. In past versions of ACL2, a formal parameter
of a defun was considered ignored if it was not used in the body,
the guard or the measure of the defun. That meant that a variable
used only in the guard could not be declared ignored in ACL2; but
some Common Lisp compilers would complain because the variable was
not used in the body. Now, ACL2 considers a variable ignored if it
is not used in the body.
ACL2 can now be built in releases 5.0 and later of Allegro Common
Lisp. (Other releases of Allegro Common Lisp and of other lisps
continue to be supported as well.) This includes Allegro Common
Lisp running on Windows 98 platforms. John Cowles helped us do some
testing and answered questions for us. Thanks John!
We incorporated Ruben Gamboa's changes to allow the building of a
variant, ACL2(r), of ACL2, in which the user can reason about the
real numbers using non-standard analysis. See [real]. Note that
ACL2(r) and ACL2 have different underlying theories, and books
certified in one system may not be included in the other. For
backward compatibility and to ensure a smooth transition, ACL2 is
built by default, not ACL2(r). This is a compile-time switch; see
the makefile for instructions. There should be no changes to ACL2
resulting from the capability of building ACL2(r) from the same
sources. Also see [acknowledgments] for more on the history of
ACL2(r).
A large number of bugs (some affecting soundness) were fixed, and
many small new features were added. See below.
Less Important Changes:
Some warnings are now considered ``soundness related,'' namely, those
that advise you that an uncertified book has been included or that
a book containing DEFAXIOM or SKIP-PROOFS events. (Technically,
DEFAXIOMs do not imperil soundness in the proof- theoretic sense,
though they may imperil the validity of theorems. But you sould
know when a book has added an axiom to your logic!) In previous
versions of ACL2, all warnings were inhibited if the token warning
was included in the argument to [set-inhibit-output-lst]. Now,
soundness related warnings are printed even if warnings have been
inhibited. To inhibit all warnings, supply the token warning! to
set-inhibit-output-lst.
Several bugs in [defstobj] were fixed, relating to the possibility
that some of the subfunctions introduced by the defstobj were
already defined.
:[Puff] no longer tries to expand [defstobj] events. Previously, the
attempt would cause a hard error.
A soundness bug was fixed. The bug might have been exercised if you
had an alternative definition (implies hyps (equiv (fn ...) body))
in which equiv is an equivalence relation other than EQUAL. In this
case, calls of fn might have been expanded to body in places that
were not equiv-hittable.
An obscure soundness bug was fixed. The bug was exercised only if you
had a metafunction with a computed hypothesis (i.e., a ``meta
hypothesis function''), the hypothesis contained a free variable,
i.e., a variable not involved in the term being rewritten, and the
free variable occurred in the output of the metafunction. The
possibility of this bug was brought to our attention by Robert
Krug.
We fixed a bug in the handling of hide related to the question of
whether a variable symbol occurs in a term. The old code did not
find the variable and could cause the system to throw away a
hypothesis about it on the grounds that it was never mentioned. Rob
Sumners helped discover this problem.
The handling of :[elim] rules was generalized, permitting arbitrary
known equivalence relations instead of merely equal in the
concluding equality.
The printing of runes (rule names; see [rune]) used has been made
\"deterministic,\" both in proof output and in proof attempt
summaries, by sorting the runes before printing.
The handling of free variables has been improved for hypotheses such
as (< 0 X), and more generally, any hypotheses involving a
comparison with 0 (even for example (< X 1) where X is known to be
an integer, which is handled as (<= X 0)). Thanks to Robert Krug
for bringing relevant examples to our attention.
A new value, :comp, has been implemented for the :load-compiled-file
keyword of [include-book]. If this value is supplied, then a
compiled file will always be loaded, even if that requires creating
the compiled file first.
The event include-book now generates a warning when a compiled file
is expected but not found (see [include-book]). Formerly, it only
did so when executed at the top level; it failed to generate the
warning when executed on behalf of a surrounding include-book
command.
Certain redefinition warnings generated by Allegro Common Lisp have
been eliminated.
A new key has been implemented for the [ACL2-defaults-table],
:bogus-mutual-recursion-ok, set with
:[set-bogus-mutual-recursion-ok]. Thanks to David Russinoff for
pointing out the utility of such a key.
A bug was fixed in [defun-sk] that prevented its generated events
from being accepted when guard verification is being performed.
Thanks to Bill Young for bringing this problem to our attention. A
second bug was brought to our attention by Pete Manolios, which was
causing certain [defun-sk] events to be rejected. That problem has
been fixed, and an \"Infected\" warning has also been eliminated.
The command [good-bye] now works with Allegro Common Lisp.
A low-level bug was fixed that could, for example, cause an error
such as \"Error: Expected 5 args but received 4 args\" when
interrupting a local event.
A bug has been fixed in the [proof-checker] related to definition
expansion. Thanks to Pete Manolios for bringing this to our
attention with a simple example.
A bug has been fixed related to the :[bdd] hint in the presence of
[equivalence] relations. Thanks to Pete Manolios for bringing this
to our attention with a simple example.
The functions [position] and [position-equal] formerly required the
second argument to be a true list. In accordance with Common Lisp,
we now also allow the second argument to be a string. This could
cause earlier proofs about these functions to fail unless
[true-listp] is known to hold where necessary.
Robert Krug wrote a patch, which has been incorporated, to prevent
certain infinite loops that can arise in linear arithmetic. Thanks,
Robert!
The macro [let*] no longer requires the bound variables to be
distinct.
An obscure bug was fixed related to congruence rules. The bug would
sometimes cause ACL2 to behave as though no rules (other than
equality) were available for some argument positions. Thanks to
Pete Manolios for bringing this bug to our attention.
Documentation topics have been added for [hard-error] and [prog2$],
and the documentation for [illegal] has been improved. Thanks to
Rob Sumners for a useful suggestion in the examples in
documentation for prog2$ and a fix in documentation for [sublis].
The event form [certify-book] was made more secure, in that it can
now catch attempts to write a book to disk during its
certification. Thanks to Rob Sumners for pointing out the
insecurity of the existing mechanism.
A Y2K problem was fixed with our applicative handling of dates.
Accessors and updaters for [stobj]s have been made more efficient
when the underlying lisp is Allegro Common Lisp, by the use of
appropriate simple array declarations.
A raw Lisp break had been possible when a certified book that had no
guard verification was included in a session after
([set-verify-guards-eagerness] 2). This has been fixed.
The keyword command :[comp] can now be used to compile only raw Lisp
functions, excluding executable counterparts, by supplying the
argument :raw.
Rewrite rule nth-of-character-listp was removed from source file
axioms.lisp since it is essentially subsumed by characterp-nth.
Printing has been sped up. In one example the improvement was over
50% in both Allegro and GCL.
We now allow printing in a \"downcase\" mode, where symbols are printed
in lower case. All printing functions except print-object$ now
print characters in lower case for a symbol when the ACL2 state
global variable print-case has value :downcase and vertical bars
are not necessary for printing that symbol. See [io] for a
discussion of the macros acl2-print-case and set-acl2-print-case.
The default printing remains unchanged, i.e., symbols are printed
in upper case when vertical bars are not required.
A low-level printing function (prin1$) was modified so that it is not
sensitive to various Common Lisp globals related to printing. So
for example, the function [fmt] is no longer sensitive to the value
of Common Lisp global *print-case*. (The preceding paragraph
explains how to control the case for printing in ACL2.)
The definition of [array1p] was fixed so that the :maximum-length of
an array must be strictly greater than the number specified in the
:dimensions field; they may no longer be equal. This was always the
intention; the documentation (see [arrays]) has remained unchanged.
The corresponding change was also made to [array2p]. Allegro Common
Lisp formerly caused an error when [compress1] was called on an
array where the numbers above were equal; now, we get a guard
violation instead, which is appropriate.
In the context of theories, a name now represents not just the
corresponding :definition [rune], as it has done in earlier
versions of ACL2, but also the corresponding :[induction] rune. See
[theories] for a discussion of runic designators. Most users will
rarely, if ever, notice this change. One situation where this
change will make a difference is after executing (in-theory
(current-theory 'foo)) followed by (in-theory (enable bar)), where
function bar is introduced after event foo, and bar is recursively
defined. The latter [in-theory] form now enables the rune
(:induction bar), which implies that the prover can use the
induction scheme stored at definition time for bar. Formerly, the
rune (:induction bar) was not enabled by (in-theory (enable bar)),
and hence the induction scheme for bar was ignored even when
explicit :induct hints were supplied.
You may now supply [xargs] keyword pair :normalize nil in order to
prevent certain definitions from ``hanging'' when there are many
if-subexpressions. see [defun].
We now translate type declarations of real into guards, as we have
already done for other types such as rational. For example,
(declare (type real x)) generates the [guard] (rationalp x). See
[type-spec].
The theorem prover now behaves reasonably under the combination of
specifying a value of t both for :[otf-flg] and for a hint
:do-not-induct. Previously, it aborted the first time it would have
otherwise pushed a goal for induction, but now, it will continue
and wait until all induction subgoals have been pushed before it
aborts.
We changed slightly the definition of [round]. However, we believe
that the new definition is equivalent to the old.
The definition of Common Lisp function [substitute] has been added.
The following changes have been made in the use of file names within
ACL2. We thank Warren Hunt and John Cowles for running some tests
of these changes on Macintosh and Windows 98 platforms
(respectively).
(1) Names of directories and files now use a syntax like that used
for Unix (trademark of AT&T), where directories are separated
using the ``/'' character even when the operating system is not
Unix or Linux. See [pathname]. ACL2 also continues to support
its notion of structured pathnames from Version 2.4 and before,
but might not do so in future releases and hence no longer
documents such syntax.
(2) The command :[set-cbd] may now take a relative pathname as an
argument.
(3) When the macro [ld] is given a file name as a value for
[standard-oi], then if that file name is a relative pathname it
refers to the result of prepending the connected book directory
(see [pathname], see [cbd], and see [set-cbd]) in order to
obtain an absolute pathname. Simiarly for the ld specials
[standard-co] and [proofs-co].
It is no longer necessary to issue :[set-state-ok] t if you include a
[stobj] declaration for [state], for example:
(declare (xargs :stobjs state))
See [declare-stobjs].
The [proof-checker] has been cleaned up a bit, including the
documentation and the capability (once again) to define pc-macro
commands (see [define-pc-macro]) and proof-checker meta commands
(see [define-pc-meta]).
Recall that events generate summaries that include a line beginning
with ``Warnings:'', which is followed (on the same line) by zero or
more brief strings that summarize the warnings generated by that
event. Formerly, this warnings summary for an [encapsulate] or
[include-book] event did not include the summary strings for
warnings generated by subsidiary events. This has been fixed.
Macro [cw] has been documented and now expands to a call of a
;[logic] mode function. See [cw] for a way to print to the screen
without having to involve the ACL2 [state]. Thanks to Rob Sumners
for suggesting that we document this useful utility.
Functions duplicates, add-to-set-equal, intersection-eq, evens, and
odds are now :[logic] mode functions.")
(NOTE-2-5{R}
(RELEASE-NOTES)
"ACL2 Version 2.5(r) (June, 2000) Notes
Important changes to non-standard version:
Please see [note-2-5] for changes to Version 2.5 of ACL2. We hope to
write more documentation for ACL2(r) in the future.")
(NOTE-2-6
(RELEASE-NOTES)
"ACL2 Version 2.6 (November, 2001) Notes
Because of the large number of modifications, we have divided up the
Version 2.6 notes into the following subtopics.
* New functionality (see [note-2-6-new-functionality])
* Changes in proof engine (see [note-2-6-proofs])
* Changes in rules and definitions (see [note-2-6-rules])
* Guard-related changes (see [note-2-6-guards])
* Proof-checker changes (see [note-2-6-proof-checker])
* System-level changes (see [note-2-6-system])
* Other (minor) changes (see [note-2-6-other])
Subtopics
[Note-2-6-guards]
ACL2 Version 2.6 Notes on Guard-related Changes
[Note-2-6-new-functionality]
ACL2 Version 2.6 Notes on New Functionality
[Note-2-6-other]
ACL2 Version 2.6 Notes on Other (Minor) Changes
[Note-2-6-proof-checker]
ACL2 Version 2.6 Notes on Proof-checker Changes
[Note-2-6-proofs]
ACL2 Version 2.6 Notes on Changes in Proof Engine
[Note-2-6-rules]
ACL2 Version 2.6 Notes on Changes in Rules and Constants
[Note-2-6-system]
ACL2 Version 2.6 Notes on System-level Changes")
(NOTE-2-6-GUARDS
(NOTE-2-6)
"ACL2 Version 2.6 Notes on Guard-related Changes
When you [declare] that a function treats certain formals as
:[stobj]s, the [guard] of the function is automatically extended to
include the corresponding stobj-recognizer calls. For example, if a
definition includes (declare (xargs :stobjs (ST))) then the guard
of the function is changed by the addition of the conjunct (ST-P
ST).
One impact of this is that if you use the built-in ACL2 [state] as a
formal parameter of a function, (STATE-P STATE) is added to the
guard. This may introduce a guard where there was none in previous
versions of the system. In older versions, therefore, no attempt
would be made to [verify-guards], while in the new version, we
would attempt guard verification. You may wish to add (declare
(xargs :verify-guards nil)) to such definitions.
A related change affects users who do not use stobjs or state. In
previous versions of the system --- as now --- a type declaration
extended the guard you provided explicitly. Thus, if you wrote
(declare (type integer n)) then (INTEGERP n) was added to your
guard. This is still the case and :stobjs recognizers are similarly
added. But in older versions of the system we ``added'' the
conjuncts without checking whether they were already present in the
guard you provided. This sometimes produced such guards as (and
(integerp n) (integerp n)) where the first was produced by your
type declaration and the second was your :guard. We now eliminate
redundant conjuncts; this may rearrange the order of the conjuncts.
The guard conjectures for functions using stobjs have been simplified
somewhat by taking advantage of the syntactic restrictions checked
for single-threaded objects.
The following functions have been modified so that character and
string arguments are restricted to standard characters. (See
[standard-char-p] and see [standard-char-listp].)
[upper-case-p] [lower-case-p] [char-upcase] [char-downcase]
string-downcase1 [string-downcase] string-upcase1
[string-upcase] [char-equal] string-equal1 [string-equal]
Also, function [standard-string-alistp] replaces function
string-alistp, with concomitant changes in the guard to
[assoc-string-equal], and in variable *acl2-exports*. Also, lemma
standard-string-alistp-forward-to-alistp replaces lemma
string-alistp-forward-to-alistp. There is a new lemma
standard-char-p-nth, which has also been added to *acl2-exports*.
The guard had been inadvertently omitted from the definition of the
function [substitute] (and its subroutine substitute-ac). This
omission has been corrected; also, the guard is slightly stronger
than the documentation had claimed (and that has been corrected).")
(NOTE-2-6-NEW-FUNCTIONALITY
(NOTE-2-6)
"ACL2 Version 2.6 Notes on New Functionality
A fundamental change is the provision of the ``nu-rewriter'' for
simplifying expressions composed of NTH, UPDATE-NTH, and
UPDATE-NTH-ARRAY applications and LET expressions and other calls
of non-recursive functions or LAMBDA expressions involving those
symbols. The nu-rewriter applies the obvious rewrite rule for (NTH
i (UPDATE-NTH j v s)) and the analogous rule for UPDATE-NTH-ARRAY.
See nu-rewriter. The nu-rewriter can be enabled with
set-nu-rewriter-mode.
A new flag has been added to the xargs of [defun] permitting the
declaration that the function is non-executable. The usage is
(declare (xargs :non-executable t)) and the effect is that the
function has no executable counterpart. On the positive side: the
function is permitted to use single-threaded object names and
functions arbitrarily, as in theorems rather than as in executable
definitions. Such functions are not permitted to declare any names
:[stobj]s but accessors, etc., may be used, just as in theorems.
A new flag has been added to permit the system to abbreviate output
by introducing LET* notation identifying common subterms. The
formula being proved is not affected; this flag changes its
displayed form only. See [set-let*-abstractionp].
A ``raw mode'' has been added, primarily for faster loading of
applications. see [set-raw-mode].
Functions [alphorder] and [lexorder] have been put in :[logic] mode.
Lexorder is now a total order ordering of the ACL2 universe, and
theorems are included to that effect. Thanks to Pete Manolios for
suggesting the idea and providing events to use, and to Rob Sumners
for assistance with some modifications. See also the new book
books/misc/total-order for an irreflexive total order.
The ACL2 user can now make system calls to the host operating system.
See [sys-call] and see [sys-call-status]. Thanks to Rob Sumners for
working out this idea with Pete Manolios and Robert Krug, who we
also thank, and for working out the implementation with us.
It is no longer required to use absolute [pathname]s in
[include-book] forms that have been executed before a
[certify-book]. Any relative pathname strings in such contexts will
be expanded into absolute pathnames before they are saved in the
[portcullis] of the [certificate] of the book being certified.
ACL2 can now be built on top of Allegro Common Lisp 6.0, and also on
Windows platforms on top of Allegro Common Lisp and GCL. Thanks to
Pete Manolios and Vinay K. Siddhavanahalli for their help with
Windows.
Rob Sumners has designed and provided an initial implementation for
two improvements to [defstobj] (also see [stobj]). First, array
fields can now be resized. Resize and length functions are provided
for array fields, which can be used to resize stobj array fields
dynamically. The recognizers for array fields have been simplified
to accommodate this change, so that they only check that each
element of the array field has the specified type. Second,
performance has been improved for stobjs with a large number of
fields, by changing their Common Lisp implementation to store the
fields in a simple vector instead of a list.
Now [stobj]s may be bound locally; see [with-local-stobj]. Thanks to
Rob Sumners, who encouraged us to implement this capability, was an
early user of it, and participated usefully in discussions on its
design.
New functions [fms!], [fmt!], and [fmt1!] are the same as their
respective functions without the ``!,'' except that the ``!''
functions are guaranteed to print forms that can be read back in
(at a slight readability cost).
We added [extended-metafunctions], metafunctions which allow [state]
and context sensitive rewriting to some extent. We thank Robert
Krug for pushing for and on this idea.
The documentation has been improved. In particular, a new
documentation topic provides a gentle introduction to ACL2 [arrays]
--- see [arrays-example] --- and additional documentation has been
provided for getting started with proof trees in emacs --- see
[proof-tree].
New Makefile targets fasl and o have been added to the books/
directory of the distribution. For example, you might first certify
books using an ACL2 built on top of GCL (which creates compiled
files with suffix o). Then, when standing in the books/ directory,
you might execute the command
make fasl ACL2=my-allegro-acl2
which will create compiled (.fasl) files for Allegro Common Lisp,
assuming that my-allegro-acl2 starts up an ACL2 built on that
Common Lisp.
The macro [let*] now allows variables to be declared ignored. See
[let*] and see [let].
The user may now control backchaining. This feature was designed and
primarily implemented by Robert Krug (though the authors of ACL2
are resposible for any errors); thanks, Robert! See
[backchain-limit].
It is now possible to ``slow down'' the rate at which case splits are
generated by the simplifier. See [set-case-split-limitations].
Accesses to [stobj]s using [nth] or [update-nth] are now displayed
using symbolic constants instead of numeric indices. For example,
given the event
(defstobj foo a b :renaming ((b c)))
then the term (nth 0 foo) will be displayed (for example, during
proofs) as (nth *a* foo) while (nth 1 foo) will be displayed as
(nth *c* foo). The [defstobj] event now correspondingly introduces
a [defconst] event for each field accessor function, introducing a
constant whose name is obtained from the accessor's name by
prefixing and suffixin a ``*,'' as in the example above: accessor a
generates (defconst *a* 0) and accessor c generates (defconst *c*
1). See [nth-aliases-table] for how to extend this feature for
alternate names of [stobj]s.
Computed hints have been improved. It is now possible to detect
within a computed hint whether the goal clause is stable under
simplification; it is also possible for a computed hint to change
the list of available hints. See [computed-hints].
It is now possible to provide ``default hints'' that are appended to
the hints explicitly provided. See [set-default-hints].
Using computed hints (see [computed-hints]) and default hints (see
[set-default-hints]) it is possible to implement a book that
supports ``priority phased simplification.'' Using this book you
can assign priorities to your rules and cause the theorem prover to
simplify each goal maximally under all the rules of one priority
before enabling rules of the next priority. See
books/misc/priorities.lisp.
The macro [defabbrev] has been improved to allow [declare] forms and
documentation strings and to do more error-checking. Thanks to Rob
Sumners for designing this enhancement and providing the first
implementation. See [defabbrev].
Further changes were made to support CMU Lisp. Wolfhard Buss helped
with these changes.
A new table was added that is used when printing proof output, so
that nests of right-associated calls of a binary function are
replaced by corresponding macro calls, as has been the case for
[binary-+] and [+], [binary-append] and [append], and so on. See
[add-binop].
Operators [logand], [logior], [logxor], and [logeqv] are now macros
(formerly, they were functions) that call corresponding binary
functions (e.g., binary-logand) defined in source file
\"axioms.lisp\". Thanks to Rob Sumners for this enhancement. Proof
output will however continue to show calls of [logand], [logior],
[logxor], and [logeqv].
Function ([allocate-fixnum-range] fixnum-lo fixnum-hi) sets aside
more \"permanent\" fixnums in GCL.
ACL2 now runs under CLISP. Thanks to Wolfhard Buss and Sam Steingold
for their assistance with the port.
Michael ``Bogo'' Bogomolny has created a search engine, accessible
from the ACL2 home page. For that purpose he modified the HTML
translator to create one file per topic (a good idea in any case).
Thanks, Bogo!
An emacs file of potential (but optional) use for ACL2 users may be
found in emacs/emacs-acl2.el. In particular, this file supports the
use of proof trees (see [proof-tree]).
Some [books] have been added or modified. In particular, Robert Krug
has contributed books/arithmetic-2/, which provides an alternative
to the existing collection of books about arithmetic,
books/arithmetic/. For a discussion of the distributed books see
the link to README.html in the installation instructions.")
(NOTE-2-6-OTHER
(NOTE-2-6)
"ACL2 Version 2.6 Notes on Other (Minor) Changes
Warning strings are now case-insensitive. See [set-inhibit-warnings].
ACL2 causes a warning when an [in-theory] hint or event causes a
0-ary function's definition to be disabled but its
:[executable-counterpart] to be enabled.
A minor modification has been made to [defstobj] that can have a
positive impact on performance in Allegro Common Lisp. (For Lisp
hackers: the stobj name was formerly declared special, and that was
disabling Allegro's tail-merging routing for compilation of some
recursive functions using stobjs.) The downside is that stobj names
can no longer be evaluated in raw Lisp. However, raw Lisp is not
the right place to be evaluating ACL2 forms anyhow; see
[set-raw-mode]. We thank Rob Sumners for bringing this issue to our
attention.
Before Version 2.6, there has been the following problem with
[defstub] and [encapsulate] in the case that the current package is
not the ACL2 package. If a [signature] was specified using the
symbol =>, then that symbol had have been imported into the current
package from the ACL2 package when the current package was defined.
There are no longer any package restrictions on the use of =>.
Thanks to John Cowles for bringing this problem to our attention.
Bugs in [defun-sk] have been fixed. Defun-sk forms introducing
functions of no arguments were failing to be admitted, for example:
(defun-sk always-p1 () (forall (x) (p1 x))). Thanks to John Cowles
for bringing this problem to our attention. Also, defun-sk failed
on an example in the documentation (see
[tutorial4-defun-sk-example]), as pointed out by Matyas Sustik;
this bug has been fixed as well.
The trace mechanism has been fixed to handle [stobj]s, and to avoid
the printing of so-called enabled structures.
The [brr] command :type-alist now produces more readable output.
An [include-book] of an uncertified book no longer loads an
associated compiled file.
We added a few checks to make sure that the underlying lisp is
suitable, for example checking that the reader is case-insensitive
and reads in symbols with upper-case names where appropriate.
We now warn when forcing (see [force]) or immediate force mode (see
[immediate-force-modep]) change state between enabled and disabled.
Also see [enable-immediate-force-modep] and see
[disable-immediate-force-modep] for information about these new
macros, which may be used to control immediate force mode.
We have eliminated the use of a low-level raw Lisp constant,
*most-recent-multiplicity*. Our test suite saw a speed-up of
approximately 2% as a result for an ACL2 image built on GCL (but no
significant speed-up for an ACL2 image built on Allegro Common
Lisp). We thank Rob Sumners for suggesting this improvement.
Fixnum declarations are now realized as (signed-byte 29) instead of
(signed-byte 27). We check that the underlying Common Lisp
recognizes objects of type (signed-byte 29) as fixnums, with the
exception of CLISP, which is said to have an efficient bignum
implementation.
A new documentation topic [functional-instantiation-example]
illustrates functional instantiation.
A bug has been fixed in the monitoring of runes (see [monitor]).
Thanks to Dave Greve for sending an example that clearly showed the
problem.
A warning is now issued when it is detected that a
:[type-prescription] rule may not be as strong as it appears
because it is not sufficient to prove itself by type reasoning.
An error is caused for rules of class :[meta] when the function
symbol IF is among the :trigger-fns. (IF was ignored anyhow; the
point of this change is to avoid misleading the user.)
A minor bug has been fixed in :[pr], evident for example if this
command was applied to IF.
A minor hole in :[set-bogus-mutual-recursion-ok] did not permit the
acceptance of [mutual-recursion] forms that include constant
function definitions. This has been fixed. Thanks to Eric Smith for
coming up with a simple example illustrating the problem.
The temporary files \"TMP.lisp\" and \"TMP1.lisp\" written out by :[comp]
are now written to the connected book directory (see [cbd]).
Previously, the Allegro compiler was not eliminating tail recursion
for executable counterparts of functions, because of the way one of
its flags had been set. As a result, calls of functions whose
guards had not been verified could run out of stack space when this
was not necessary. This situation has been fixed.
Executable counterparts could have slow array accesses. This has been
fixed (specifically, constants are no longer replaced with their
values in the definitions of executable counterparts).
Various improvements have been made to the documentation. Thanks in
particular to Eric Smith for pointing out a numbers of places where
fixes were in order.
File \"mcl-acl2-startup.lisp\" has been updated, thanks to feedback
from Philippe Georgelin.
Inefficiencies in GCL fixnum computations were remedied for macros +f
and *f. Thanks to Rob Sumners for pointing out this issue.")
(NOTE-2-6-PROOF-CHECKER
(NOTE-2-6)
"ACL2 Version 2.6 Notes on Proof-checker Changes
The proof-checker command =, when used with no arguments, now reports
which hypothesis is being used.
The output from [proof-checker] command type-alist has been improved.
A slight change has been made to the [proof-checker] for commands
promote, casesplit, equiv, and =, so that terms of the form (if x
nil y) are recognized as conjunctions, (and (not x) y). Thanks to
Pete Manolios for suggesting that we consider such a change.
There is a new [proof-checker] command print-all-concs that prints
all the conclusions of the unproved goals.
A new [proof-checker] command, runes, has been added. It reports the
[rune]s that have participated in the interactive proof up to the
current point.")
(NOTE-2-6-PROOFS
(NOTE-2-6)
"ACL2 Version 2.6 Notes on Changes in Proof Engine
Certain optimizations are performed when converting terms to clausal
form. For example, (< 0 1) is known to be t, (HARD-ERROR ctx str
alist) is known to be nil, and (INTEGERP n) is known to imply
(RATIONALP n).
In earlier versions of ACL2, the conversion of a term to clausal form
expanded LAMBDA applications. That may no longer occur. Some proofs
may slow down (or fail) because your LAMBDA-expressions are not
expanded away when you ``expected'' them to be.
Robert Krug found a soundness bug in our linear arithmetic package.
The bug was caused by the derivation of an equation from two
inequalities without taking adequate precautions to ensure that
both sides of the inequalities were numeric. Robert also kindly
provided a fix which we adopted. Thanks Robert!
We fixed a bug that could prevent the application of a metatheorem.
A bug has been fixed that had caused bogus forcing rounds (see
[forcing-round]). The bug could occur when the hypothesis of a rule
was forced (see [force]) before the prover decided to start over
and prove the original goal by induction. Thanks to Rob Sumners for
drawing our attention to this problem.
Some low-level fixes have been made that prevent certain infinite
loops, based on reports by users. We thank Yunja Choi, Matt
Wilding, and Pete Manolios for reporting such problems.
An obscure potential soundness hole has been fixed by redoing the way
evaluation takes place in the ACL2 loop and during theorem proving.
We expect that users will see no difference based on this change.
(Those interested in the details can see the long comment ``Essay
on Evaluation in ACL2'' in source file interface-raw.lisp.)
A small change was made in computation for a heuristic that controls
backchaining. This will speed up proofs dramatically in a very few
cases but should have a very small impact in general.
The simplifier has been modified to avoid eliminating hypotheses of
goals that can be established by contextual (specifically,
type-set) reasoning alone. We believe that this change will
generally strengthen ACL2's reasoning engine, although on rare
occasions a lemma that formerly was provable may require user
assistance. Thanks to Robert Krug for suggesting this change and
providing its implementation.
Case splits are now limited, by default. This may allow some proof
attempts to provide output where previously the prover would appear
to ``go out to lunch.'' For a more complete discussion, including
instructions for how users can control case splitting, see
[set-case-split-limitations].
A bug has been fixed in the handling of :[type-prescription] rules by
the [bdd] package. Thanks to Rob Sumners for discovering this bug
and supplying a helpful example.
ACL2 may now use the built-in induction scheme for a function symbol
even if that function symbol is disabled. Formerly, if a function
symbol was disabled then its induction scheme was only considered
if an explicit induction hint was supplied, other than :induct t.
We eliminated the rule-class linear-alias. This rule class was seldom
used and complicated the linear arithmetic decision procedure in
ways that made it difficult to extend to handle some non-linear
special cases. The only use of the rule-class that we know of was
in our own nqthm books, which were an attempt to provide an
embedding of the Nqthm logic and theorem prover into ACL2. But that
facility was also practically never used, as far as we know. So
both linear-alias rules and the nqthm books have been eliminated.
In earlier versions of ACL2, when the IF-form of (AND p q) was
assumed true -- as when rewriting the alpha expression in (IF (AND
p q) alpha beta) -- the assumption mechanism did not deduce that p
and q are true, only that their conjunction, in its IF-form, is
true. This has long been known as a deficiency in both ACL2 and the
earlier Nqthm but it was tedious to do better when one considered
the full range of IF-forms one might encounter in the test of
another IF. Rather than code all the cases, we just waited until
clausification got rid of them. Robert Krug developed a pretty nice
treatment of the general case and we added it in this version. This
also involved a surprising number of changes elsewhere in the
system because the improved handling of assumptions caused the
theorem prover often to ``erase'' hypotheses provided by :use hints
because it could simplify them to t. Thank you Robert!
In response to a suggestion from Robert Krug, we added mfc-ap so that
extended metafunctions can take advantage of linear arithmetic. See
[extended-metafunctions].
There is less delay in printing goals. In previous versions, a goal
was not printed until its subgoals were created (or the goal was
proved). Now, the goal is printed essentially as soon as it is
created.
A small technical change has been made in the function [term-order],
to give priority on the function symbol count over the weighting of
constants. So for example, while previously the term (f) preceded
the constant 2, that is no longer the case. If this change is
noticed at all, it will probably be noticed in how so-called
permutative rewrite rules are applied; see [loop-stopper]. Thanks
to Robert Krug for suggesting this improvement and providing part
of the implemtation.")
(NOTE-2-6-RULES
(NOTE-2-6)
"ACL2 Version 2.6 Notes on Changes in Rules and Constants
The following symbols have been added to the list constant
*common-lisp-specials-and-constants*: REPLACE, FILL, CHARACTER, =,
BREAK, and PRIN1. This was done in support of ports to Allegro 6.0
and Windows platforms (see [note-2-6-new-functionality]).
The list of symbols in *acl2-exports* has been modified, for example
to include show-accumulated-persistence and the legal arguments to
[set-inhibit-output-lst].
Functions [zp] and [zip] are now handled slightly differently. They
are are now disabled, but each comes with a :[rewrite] rule that
allows their expansion on non-variable terms, and also with a
:[compound-recognizer] rule that avoids the need for opening up
these functions when applied to variables. The resulting behavior
should be very similar to the behavior of previous versions, except
that case splits will be avoided when these functions are applied
to variables.
Function [standard-string-alistp] replaces function string-alistp.
For further discussion, see [note-2-6-guards].
Rules of class :[rewrite] whose conclusion is a term of the form
(equal lhs rhs) have always been stored in the expected way: lhs
rewrites to rhs. This way of storing :rewrite rules has been
extended to allow [=], [eq], or [eql] in place of [equal].
Rewrite rule nth-update-nth, in source file axioms.lisp, has been
strengthened.
A new rewrite rule equal-constant-+ has been added to the book
arithmetic/equalities. This should generally be a beneficial
change, but existing proofs involving the arithmetic books could
conceivably be affected.
Function [symbol-package-name] and constant *main-lisp-package-name*
have undergone small changes. This change should rarely be noticed
by users and is discussed elsewhere; see [note-2-6-system].
We mention here that proofs involving [stobj]s may need to be
modified because of changes in auxiliary functions generated by
[defstobj]. (These changes were made in support of a new resizing
capability, mentioned elsewhere in these release notes; see
[note-2-6-new-functionality].
In the distributed book directory books/arithmetic/, the book
rationals-with-axioms-proved.lisp has been renamed rationals.lisp.
(ACL2(r) only) Rewrite rules realp-+, realp-*, realp-unary--, and
realp-unary-/ have been added in analogy to existing rules
rationalp-+, rationalp-*, rationalp-unary--, and rationalp-unary-/.
Thanks to Jun Sawada for suggesting this change.
The definition of [aref1] has been modified slightly. Previously, if
*my-a* were an array then (aref1 'some-name *my-a* :header) would
evaluate to the cdr of the [header] of *my-a* rather than to its
[default]. See [arrays].
Changes have been made in the ihs books, based on suggestions from
Jun Sawada, that support its use with ACL2(r) (see [real]). The
primary change is to replace calls of [rationalp] with calls of
[real/rationalp], which should have no effect on users of standard
ACL2.")
(NOTE-2-6-SYSTEM
(NOTE-2-6)
"ACL2 Version 2.6 Notes on System-level Changes
We modified the tracking of [skip-proofs] events and the use of
[state] global ld-skip-proofsp in order to avoid some soundness
issues. For example, [skip-proofs] events buried in
locally-included books are now tracked. The ``Essay on
Skip-proofs'' in source file axioms.lisp gives several examples of
dicey behavior that is no longer supported.
We fixed a problem with some of the makefiles, so that recursive
invocations of `make' now use the version of `make' specified on
the command line.
Files were fixed to help non-Unix/Linux users with book
certification. Thanks to John Cowles for finding some problems and
suggesting fixes to books/certify-numbers.lisp,
books/arithmetic/certify.lsp, and books/cowles/certify.lsp. We
thank Scott Burson for noticing and fixing some other such
problems. Moreover, a bdd test was being ignored entirely in
Version 2.5; this problem has been fixed as well.
A minor change in system function save-acl2-in-allegro will allow
this function to continue to work in Allegro CL versions starting
(someday) with 10.0. Thanks to Art Flatau for suggesting such a
fix.
The books/case-studies/ directory has been removed. These books are
in support of the first (1998) ACL2 workshop, and are accessible
via the {ACL2 home page |
http://www.cs.utexas.edu/users/moore/acl2/}. Also, the
books/cli-misc directory has been renamed books/misc, and the
books/nqthm directory has been removed.
The notion of ACL2 version has been slightly modified to catch
unsoundness due to implementation dependencies. See [version].
Another change to eliminate such unsoundness is that built-in
symbols now have a [symbol-package-name] of \"COMMON-LISP\";
formerly, this string was \"LISP\" for ACL2 images built on GCL. See
[symbol-package-name]. At a low level, the (undocumented) constant
*main-lisp-package-name* is now \"COMMON-LISP\"; before, it was
\"LISP\" for GCL.")
(NOTE-2-6{R}
(RELEASE-NOTES)
"ACL2 Version 2.6(r) (November, 2001) Notes
Important changes to non-standard version: None since Version 2.5.
Please see [note-2-6] for changes to Version 2.6 of ACL2. We hope to
write more documentation for ACL2(r) in the future.")
(NOTE-2-7
(RELEASE-NOTES)
"ACL2 Version 2.7 (November, 2002) Notes
The Version_2.7 notes are divided into the subtopics below. Here we
give only a brief summary of a few of the changes that seem most
likely to impact existing proofs. Not included in this brief
summary, but included in the subtopics, are descriptions of
improvements (including bug fixes and new functionality) that
should not get in the way of existing proof efforts.
In particular, please see [note-2-7-new-functionality] for discussion
of a number of new features that you may find useful.
Acknowledgements and elaboration, as well as other changes, can be
found in the subtopics listed below.
Bug fixes (see [note-2-7-bug-fixes])
* Three soundness bugs were fixed. These bugs were probably rarely hit,
so users may well not notice these changes.
* [Certify-book] now requires :skip-proofs-ok t (respectively,
:defaxioms-okp t) if there are [skip-proofs] (respectively,
[defaxiom]) events in the book or any included sub-books.
* When :by hints refer to a definition, they now use the original body
of that definition rather than the simplfied (``normalized'')
body.
* When [ld] is applied to a stringp file name, it now temporarily sets
the connected book directory (see [cbd]) to the directory of
that file while evaluating forms in that file.
New functionality (see [note-2-7-new-functionality])
* ACL2 now works harder to apply :[rewrite] and :[linear] rules with
free variables in the hypotheses. See
[note-2-7-new-functionality], in particular its first two
paragraphs, for details. [Forward-chaining] also does more with
free variables.
Changes in proof engine (see [note-2-7-proofs])
* Some prover heuristics have changed slightly. Among other
consequences, this can cause subgoal [hints] to change. For
example, suppose that the Version_2.6 proof of a particular
theorem generated \"Subgoal 2\" and \"Subgoal 1\" while Version_2.7
only generates the second of these. Then a subgoal hint
attached to \"Subgoal 1\" in Version_2.6 would have to be
attached to \"Goal'\" in Version_2.7. (See [goal-spec].) The full
topic has details (see [note-2-7-proofs]).
Changes in rules and definitions (see [note-2-7-rules])
* The package name of a generated variable has changed for [defcong].
Guard-related changes (see [note-2-7-guards])
* [Guard] verification formerly succeeded in a few cases where it
should have failed.
* Guards generated from type declarations now use functions
signed-byte-p and unsigned-byte-p, now defined in source file
axioms.lisp and formerly defined rather similarly under
books/ihs/.
Proof-checker changes (see [note-2-7-proof-checker])
* See the above doc topic.
System-level changes (see [note-2-7-system])
* See the above doc topic.
Other changes (see [note-2-7-other])
* A new [table], [invisible-fns-table], takes the place of the handling
of invisible functions in the [ACL2-defaults-table],
* The [theory-invariant] event has been modified so that the default
action is an error rather than a warning.
* Proof output that reports destructor elimination no longer uses the
word ``generalizing''.
Again, please proceed to the subtopics for more thorough release
notes.
Subtopics
[Note-2-7-bug-fixes]
ACL2 Version 2.7 Notes on Bug Fixes
[Note-2-7-guards]
ACL2 Version 2.7 Notes on Guard-related Changes
[Note-2-7-new-functionality]
ACL2 Version 2.7 Notes on New Functionality
[Note-2-7-other]
ACL2 Version 2.7 Notes on Miscellaneous Changes
[Note-2-7-proof-checker]
ACL2 Version 2.7 Notes on Proof-checker Changes
[Note-2-7-proofs]
ACL2 Version 2.7 Notes on Changes in Proof Engine
[Note-2-7-rules]
ACL2 Version 2.7 Notes on Changes in Rules and Constants
[Note-2-7-system]
ACL2 Version 2.7 Notes on System-level Changes")
(NOTE-2-7-BUG-FIXES
(NOTE-2-7)
"ACL2 Version 2.7 Notes on Bug Fixes
Francisco J. Martin-Mateos emailed us a soundness bug (!) in our
handling of functional instantiation (for example see
[functional-instantiation-example]). We are grateful for that
email, which clearly illustrated the problem. It is included just
below the definition of push-clause in ACL2 source file prove.lisp,
where we have fixed the bug. This bug was fixed in a re-release of
Version 2.6 in February, 2002.
Rob Sumners emailed us a soundness bug (!) in function
commutative-p1, which is used by the ACL2 [bdd] package. We are
grateful for his help; his email gave a proof of nil and also
pointed to the problem function. This bug was fixed in a re-release
of Version 2.6 in February, 2002.
We discovered and fixed a soundness bug illustrated by the book
below, which was certifiable in Version 2.6 and ends in a proof of
nil. The event (verify-guards foo) should have been rejected,
because foo calls a function whose guards have not been verified,
namely, bar. However, ACL2 did not notice the call of function bar
in the body of foo because it was looking in the simplified
(normalized) body of foo rather than in the original body of foo.
During processing of the book below, the logical definition of zp
is used before (verify-guards foo), and (zp -3) reduces to t in the
logic. After (verify-guards foo), ACL2 simplifies (foo -3) by going
into raw Lisp, where (zp -3) is evaluated and reduces to nil.
(in-package \"ACL2\")
(defun bar (x)
(zp x))
(defthm zp-false-on-negatives
(implies (< x 0)
(bar x))
:rule-classes :type-prescription)
(defun foo (x)
(declare (xargs :guard (rationalp x)
:verify-guards nil))
(if (< x 0)
(if (bar x) 0 1) ; simplified body reduces this line to 0
17))
(defthm foo-of-minus-3-is-0
(equal (foo -3) 0)
:rule-classes nil)
(verify-guards foo)
(defthm foo-of-minus-3-is-1
(equal (foo -3) 1)
:rule-classes nil)
(defthm bug
nil
:rule-classes nil
:hints ((\"Goal\" :use (foo-of-minus-3-is-0 foo-of-minus-3-is-1))))
The above bug exploited the fact that [zp] has a different definition
in raw Lisp than in the logic for arguments that violate its
guard). The following example caused a hard error in raw Lisp,
though not a soundness error.
(in-package \"ACL2\")
(defun bar (x)
(cons (car x) (car x)))
(defun foo (x)
(declare (xargs :guard t
:verify-guards nil))
(if (bar x) x nil))
(verify-guards foo)
(defthm bug
(equal (foo 3) t)
:rule-classes nil)
We have made a minor change to the notion of the formula of a
function symbol, related to the change above, which however is
unlikely to be noticeable.
In order to make it harder to hit problems like the guard problem
above, we have slighly modified the raw Lisp definition of [zp].
A [break-rewrite] command, :ancestors, was broken, but has been
fixed. Thanks to Eric Smith for bringing the problem to our
attention, and to Robert Krug for supplying the final part of the
fix.
Some [proof-checker] commands caused errors when all goals have
already been proved. This has been fixed. Thanks to Matt Wilding
for reporting this bug.
Fixed a bug in :[comp]. When compiling uncompiled functions with very
large definitions, ACL2 was inserted a backslash (\\) character into
generated files.
Fixed the :type-alist :[brr] command (see [brr-commands]), whose
output was difficult to read when typed after an :eval..
Fixed some clumsy handling of errors when including an uncertified
book, for example, with the error message when including an
uncertified book with a bad [deftheory] event. Thanks to Eric Smith
for pointing out this problem.
Two modifications to [certify-book] now cause it to reflect natural
expectations with respect to soundness. First, it now has default
values of nil instead of t for keyword arguments :skip-proofs-okp
and :defaxioms-okp. Thanks to Robert Krug for suggesting this
change and the ACL2 seminar at the University of Texas for
discussing it. Second, when :skip-proofs-okp (respectively,
:defaxioms-okp) is nil, either explicitly or by default, then
[skip-proofs] commands (respectively, [defaxiom] events) are
disallowed inside any included books, regardless of the keyword
parameters passed to [include-book]. This had not been the case for
previous versions of ACL2, regardless of the values of
:skip-proofs-okp or :defaxioms-okp passed to [include-book].
Improved warnings and errors for [certify-book] and [include-book] to
mention the [portcullis] as a possible source of [skip-proofs] and
[defaxiom]s.
ACL2 formerly caused an error when [hints] in a :[corollary] were not
well-formed. This situation could arise as follows when certifying
a book. A lemma FOO is proved [local]ly to the book (or, is present
in a sub-book that is included locally). The :corollary of a
subsequent theorem, BAR, disables that rule in a hint. When BAR is
proved, this is not a problem. But [certify-book] makes a second
pass after processing the events in a book: it essentially does an
[include-book]. During the include-book pass, FOO is not known
(because it was [local]), and therefore ACL2 fails to process the
[disable] of FOO in an [in-theory] hint. The fix is that during
[include-book], [hints] are ignored in corollaries just as they
have been for the main theorem (or definition).
It was possible for guard verification to succeed where it should
have failed. We have fixed the bug (which was in source function
(ironically named!) fcons-term-smart). Thanks to Robert Krug for
sending us an example of bungled guard verification. It turns out
that this bug was also present in Version_2.6.
The [proof-checker] command = has been improved. Formerly, it could
fail to apply when certain [implies] terms were in the context.
Thanks to Pete Manolios for bringing this problem to our attention.
The command [add-binop] failed to work. This has been fixed. Thanks
to Rob Sumners for pointing out this problem. Also see
[note-2-7-other] for a discussion of how this and another [table]
are no longer part of the [ACL2-defaults-table].
Book certification could cause a segmentation fault in cases where
the certification world (see [certify-book]) has a very large
number of events. This has been fixed.
We now allow empty :use [hints] and empty hints, as requested by Eric
Smith. Examples:
(\"Goal\" :use ())
(\"Goal\")
A large [mutual-recursion] nest could cause a stack overflow when
executing either :pr FN, :pr! FN, or :monitor (:definition FN) t,
where FN is in that large mutual recursion nest. This has been
fixed (implementation detail: function actual-props has been made
tail-recursive). NOTE: If you just want the definition of FN, :[pf]
FN can be much faster than :[pr] FN if FN is in a large
[mutual-recursion].
Hard Lisp errors could occur when including uncertified books. This
has been fixed; ACL2 now does syntax-checking formerly omitted when
including uncertified books.
Previously, the evaluation of [defstobj] and [mutual-recursion] forms
could cause ``undefined'' warnings when the form was compiled. This
has been fixed. Thanks to Eric Smith for bring a mutual-recursion
example to our attention.
A bug has been fixed in the syntactic check for valid :[loop-stopper]
values. Formerly, valid :loop-stopper values were erroneously
restricted to lists of length at most 2 (a minor problem, since
these lists typically have length 1), and the function symbol(s)
need not have been defined in the current ACL2 [world]. Thanks to
Eric Smith for sending an example to demonstrate the latter
problem.
Functions definitions that are :non-executable (see [xargs]) had
never been recognized as redundant, but this has been fixed. Thanks
to Vernon Austel for pointing out this problem.
Compilation using :[comp] now compiles user-defined :[program] mode
functions. Formerly only :[logic] mode functions could be compiled
using :comp.
Handling of :by hints has been improved in essentially three ways.
The primary change is that now, when the current goal exactly
matches the supplied lemma instance, the subsumption test will
always succeeds (see [hints], in particular the discussion of :by).
Second, certain proof failures involving :by [hints] were failing
silently, with duplicate messages ``As indicated by the hint, this
goal is subsumed by....'' This could happen when the original goal
was among the goals generated by applying the hint. This problem
has been fixed by no longer considering this proof step to be
specious (see [specious-simplification]). Third and finally, when
the [lemma-instance] refers to a definition, the original body of
that definition is used rather than the simplfied (``normalized'')
body.
In addition to the obove, we now recognize more cases of specious
simplification (see [specious-simplification]). Thanks to Eric
Smith for bringing this issue to our attention.
Fixed building of ACL2 under CLISP so that (1) the appropriate ACL2
startup message is printed out when ACL2 starts up, and (2) the
lisp process supplied to make, e.g., LISP=/usr/bin/clisp, is the
one written out to the saved ACL2 file. Thanks to Dave Greve and
Noah Friedman for suggesting (2). Also, ACL2 now works with CLISP
2.30. We have accommodated a change in CLISP's handling of streams
and its package-locking mechanism, as well as certain non-standard
characters that formerly could cause CLISP 2.30 to break, even when
those characters are in comments.
Eliminated compiler warnings for CMU Lisp.
Fixed an incorrect error supplied when book certification proceeded
so quickly that the file write dates of the book (.lisp file) and
the corresponding compiled file are equal. Now that error only
occurs if the compiled file has a strictly earlier write date,
which probably should never happen.
Fixed an infinite loop when executing make clean-books (and hence
`make' with targets that call clean-books, namely,
certify-books-fresh, regression-fresh, and
regression-nonstd-fresh), which could occur when any subdirectories
of books/ are missing --- even workshops/, which is intended to be
optional. Thanks to Pete Manolios for pointing out this bug.
The [include-book] command now works properly even when filenames, or
their directories or parent directories (etc.) are links. Thanks to
Matt Wilding for pointing out this problem.
The commands :[puff] :[puff*] have been fixed. Formerly, there was a
bug when :puff or :puff* caused the execution of an [include-book]
for an absolute [pathname], P, that was other than the current
connected book directory (see [cbd]). When including P, any
subsidiary [include-book] with a relative pathname would be
erroneously considered relative to the current [cbd] rather than
relative to the directory of P. Thanks to Pete Manolios and Matt
Wilding for pointing out this problem.
It had been possible in a ``large'' ACL2 image to call
[verify-termination] successfully on built-in function [sys-call],
with undesirable results. This hole has been plugged. Thanks to Rob
Sumners for pointing out this problem. The new function [gc$] must
also stay in :[program] mode.
ACL2 no longer warns when certifying a book based on [local]
functions whose [guard]s have not yet been verified. Thanks to Pete
Manolios for pointing out this issue.
An occasional ``slow array warning'' had been possible during proofs.
The following sequence shows how to evoke that warning in previous
versions.
(in-theory (disable binary-append))
(in-theory (enable binary-append))
(in-theory (disable binary-append))
(ubt 2)
(thm (equal (car (cons x y)) x))
(See [note-2-7-other] for a discussion of a change to [compress1] in
support of this fix; however, users should not need to read that
discussion.)
The raw Lisp code for [defchoose] had a small bug, which was only
evidenced in CLISP implementations as far as we know. It has been
fixed.
When [ld] is applied to a stringp file name, it now temporarily sets
the connected book directory (see [cbd]) to the directory of that
file while evaluating forms in that file. To see the effect of this
change, imagine a subdirectory \"sub\" of the current directory, and
imagine executing (ld \"sub/foo.lisp\"), where file foo.lisp contains
the form (include-book \"bar\"). Presumably the intention was to
consider the file bar.lisp in the same directory, sub/, as
foo.lisp. Ld now honors that intention, but in previous versions
\"bar.lisp\" would have been a reference to a file in the current
directory, not in sub/.
For users of run-acl2 [perhaps there are none!]: A fix has been
provided by a Debian user via Camm Maguire so that acl2-mode anyone
using that?] will work in Xemacs, which apparently uses variable
lisp-mode-shared-map rather than shared-lisp-mode-map.
ACL2 has, for a long time (always?), had a mechanism for avoiding
re-proving [constraint]s generated by :functional-instance
[lemma-instance]s in :use and :by hints. But this mechanism had not
applied to defined (as opposed to constrained) functions. This has
been fixed. Thanks to Francisco J. Martin-Mateos (ChesKo) for
pointing out this problem by sending a clear example.")
(NOTE-2-7-GUARDS
(NOTE-2-7)
"ACL2 Version 2.7 Notes on Guard-related Changes
It was possible for guard verification to succeed where it should
have failed. See the discussion under [note-2-7-bug-fixes].
There have been changes in the guards generated from type
declarations for the following cases. Thanks to Dave Greve and Matt
Wilding for suggesting such changes.
(type (signed-byte n) val)
(type (unsigned-byte n) val)
(type (integer m n) val)
The following examples illustrate the changes.
(type (signed-byte 4) x)
==> [old] (AND (INTEGERP X) (<= -8 X) (<= X 7))
==> [new] (SIGNED-BYTE-P 4 X)
(type (unsigned-byte 4) x)
==> [old] (AND (INTEGERP X) (<= 0 X) (<= X 15))
==> [new] (UNSIGNED-BYTE-P 4 X)")
(NOTE-2-7-NEW-FUNCTIONALITY
(NOTE-2-7)
"ACL2 Version 2.7 Notes on New Functionality
ACL2 now has a more powerful technique for relieving a :[rewrite] or
:[linear] rule's hypothesis that contains free variables. A new
[documentation] section has been written describing the handling
free variables in rules; see [free-variables]. In brief, the
primary change is that when a free-variable match for the current
hypothesis fails to allow subsequent hypotheses to be relieved,
then additional matches may be attempted until they have all been
tried. Also see [rule-classes] (discussion of :match-free). Also
see [set-match-free-error], see [set-match-free-default], and see
[add-match-free-override] for interfaces provided to the user for
controlling the way ACL2 deals with free variables in hypotheses.
We thank Rob Sumners for several helpful discussions about the
designs of those interfaces, as well as Eric Smith and Robert Krug
for helpful related discussions. Robert Krug also found a
performance bug in a preliminary version, for which we are
grateful.
WARNING: Book certification attempts may take much longer now that,
by default, ACL2 looks for more free variable matches (see
paragraph just above). You can get the old behavior by inserting
the form
(set-match-free-default :once)
just after the initial [in-package] form. However, rules from
included books that have free variables can still slow down
certification. This can be fixed by inserting
(add-match-free-override :once t)
before the first event in the file that generates a proof.
[Forward-chaining] has been made more powerful in the presence of
free variables (see [free-variables]), thanks to a contribution by
Erik Reeber. Both before and now, when an attempt is made to
relieve (prove) a hypothesis of a :forward-chaining rule in the
case that at least one variable in that hypothesis is not yet
bound, ACL2 looks in the current context for an instance of that
hypothesis. If it finds one, then it binds the unbound variables
and continues to the next hyopothesis. What is new is that ACL2 can
now looks for multiple instances of that hypothesis. Consider the
following example; an explanation is below.
(encapsulate (((op * *) => *))
(local (defun op (x y) (< x y)))
(defthm transitivity-of-op
(implies (and (op x y) (op y z)) (op x z))
:rule-classes :forward-chaining))
; fails in Version_2.6; succeeds in in Version_2.7
(thm (implies (and (op a b) (op b c) (op b e)) (op a c)))
Before Version_2.7, the proof of the thm above fails. When the
:forward-chaining rule transitivity-of-op binds x to a and y to b,
it then looks for an instance of (op y z) in the current context,
with y bound to b but z unbound. It happens to find (op b e) before
(op b c), and it then adds (op a e) to the context. But starting
with Version_2.7, it continues to look for additional instances and
finds (op b c) in the context as well, chaining forward to (op a c)
and thus proving the theorem.
A new macro, [bind-free], provides a simple way to get much or most
of the power of [meta]functions. Thanks to Eric Smith for coming up
with the idea and to Robert Krug for providing an implementation
(which we modified only very slightly) and documentation. See
[bind-free] and see [bind-free-examples].
With the addition of [bind-free] (mentioned above), [syntaxp] has
become a macro, although that change should be transparent to the
user. More importantly, the argument of syntaxp may now refer to
variables mfc and state, giving syntaxp some of the power of
extended metafunctions; see [syntaxp] and see
[extended-metafunctions]. Thanks to Robert Krug for implementing
that extension. Also, the argument of [syntaxp] may now include
calls of :[program] mode functions. See [syntaxp] and see
[syntaxp-examples] (thanks to Robert Krug for updating the former
and creating the latter documentation).
The linear-arithmetic decision procedure (see [linear-arithmetic])
has now been extended so that ACL2 can reason about non-linear
arithmetic as well (see [non-linear-arithmetic] for how to turn on
this feature). We thank Robert Krug for the initial implementation
of this, and Eric Smith for finding a couple of bugs in it.
Some [trace] utilities have been made available in the ACL2 loop.
* Function [trace$] (and also [untrace$]) calls the corresponding
underlying Lisp routine trace (and untrace), which however
continues (as it has for some time) to be enhanced for GCL and
Allegro CL.
* Macro [open-trace-file] causes trace output to go to a specified
file. Macro [close-trace-file] causes trace output to go to the
screen (which is the default).
* Macro with-error-trace (or, wet for short) causes a backtrace to be
written out for many failures, including guard violations. See
[trace], see [trace$], and see :DOC wet [** NOTE: eliminated
after Version 3.3].
A new [theory], [minimal-theory] has been provided (see [theories]).
It can be particularly useful for speeding up proofs involving :use
[hints].
New [events] [defund] and [defthmd] behave exactly like [defun] and
[defthm], respectively, except that these new events disable the
new name.
The new macro [with-output] can be used to suppress output that would
normally result from evaluation of a form.
The form ([pstack]) can give the user an idea of what the prover has
been up to during a proof, or after a user-aborted proof. Moreover,
by evaluating (verbose-pstack t) (see [verbose-pstack]) one can get
[trace]-like information about prover functions, including time
summaries, printed to the screen during a proof. Thanks to Bill
Legato and Robert Krug for initiating this work and to Robert for
providing some initial implementation.
The new command :[comp-gcl] is identical in functionality, except
that it always leaves .c and .h files when compiling in GCL. Thanks
to Rob Sumners and Vernon Austel for suggesting such a capability.
The macro [e/d] provides a convenient way to [enable] some rules and
[disable] others. It was formerly in a book supplied with the
distribution, books/ihs/ihs-init.lisp, written by Bishop Brock (who
we thank for providing this useful macro).
New distributed books include those in books/ordinals/,
books/rtl/rel3/, and books/misc/simplify-defuns.lisp (which is
documented in books/misc/simplify-defuns.txt).
The :expand hint now accepts a special value, :LAMBDAS, that tells
the ACL2 rewriter to expand all lambda applications ([let]
expressions). See [hints].
A new function [zpf] has been added as fast test against 0 for
nonnegative fixnums.
A new macro [gc$] allows the user to call the garbage collector of
the underlying Common Lisp. Thanks to Rob Sumners for suggesting
this feature.
It is now possible to [monitor] [simple] (abbreviation) rules.
However, as a warning explains, they are still not considered
monitored during preprocessing; see [monitor]. Thanks to Robert
Krug for providing this improvement.
The second argument of [certify-book], if supplied, formerly had to
be either t or a non-negative integer. Now it can be the symbol ?,
in the ACL2 package, indicating that the usual check should be
suppressed on the number of commands that have been executed to
create the world in which [certify-book] was called.")
(NOTE-2-7-OTHER
(NOTE-2-7)
"ACL2 Version 2.7 Notes on Miscellaneous Changes
Made several minor [documentation] improvements. We are grateful to
Eric Smith for suggesting (most of) these.
Improved (show-bdd) (see [bdd]) to give more useful feedback when
there are ``leaf'' terms not known to be Boolean.
Sped up processing of large mutual-recursion nests. In one large
example the speedup was roughly two orders of magnitude.
Modified event printing so that if both 'prove and 'event are
inhibited, then events are no longer printed on behalf of
[certify-book], [encapsulate], or [defstobj]. Thanks to Eric Smith
for prompting consideration of such a change.
The following technical change was made to support with-error-trace
and wet (see [note-2-7-new-functionality]), but may be of interest
to those who do low-level programming using the ACL2 logical
[world]. The 'unnormalized-body property is now stored not only for
functions defined in :[logic] mode, but also for functions defined
by the user in :[program] mode. (:Program mode Functions built into
ACL2 still have their 'unnormalized-body property omitted, in order
to save space.)
The handling of ``invisible'' functions for purposes of controlling
rewriting (see [loop-stopper]) has been moved to a new table; see
[invisible-fns-table]. Macros that access and modify this table are
called ``...-invisible-fns-table'' in place of their former names,
``...-invisible-fns-alist.'' This feature was formerly implemented
in the [ACL2-defaults-table], which prevented a book from exporting
lists of invisible functions intended to work with the [rewrite]
rules developed in the book. Thanks to Eric Smith and Rob Sumners
for suggesting this change. See [set-invisible-fns-table] (formerly
set-invisible-fns-alist), and also see [add-invisible-fns] and see
[remove-invisible-fns], which provides ways to incrementally add to
and remove from this table, respectively. The handling of printing
binary function call nests using macros (See [add-binop]) has also
been moved out of the [ACL2-defaults-table] as suggested by Eric
and Rob, but this feature didn't work anyhow (see
[note-2-7-bug-fixes]). Incidentally, the symbols binop-table,
[add-binop], and [remove-binop] have all been added to the list
*acl2-exports* (see [ACL2-user]), [add-invisible-fns] and
[remove-invisible-fns] have been added to that list, and
set-invisible-fns-alist has been replaced in that list by
[set-invisible-fns-table]. Function invisible-fns-alistp is no
longer defined and has been removed from *acl2-exports*.
We now enforce the stated restriction on the pairings in
macro-aliases-table (see [macro-aliases-table]), namely, that it
associates names of macros with names of funcions (with respect to
the current ACL2 logical [world]). We make a similar requirement on
[invisible-fns-table].
The [theory-invariant] event has been modified so that the default
action is an error rather than a warning. Thanks to Eric Smith for
suggesting this change. Also, the value returned upon successful
execution of a [theory-invariant] event is now the key.
Proof output that reports destructor elimination no longer uses the
word ``generalizing''. This small change may help in browsing proof
output, since now ``generaliz'' takes you to true uses of
generalization. Thanks to Matyas Sustik for suggesting such a
change.
The command :[pl] now prints an abbreviated controller-alist for
;[definition] rules. Formerly the output from :pl could be
overwhelming when the supplied function was part of a large
[mutual-recursion] nest.
The defaults for keyword parameters of [certify-book] have changed.
See [note-2-7-bug-fixes], in particular, the discussion there of
two modifications to certify-book.
Technical changes have been made to [compress1] and [compress2] that
should usually be invisible to users. The next paragraph describes
them in detail, only for competeness (i.e., that description can be
ignored by most users). But first, here is an example showing an
effect on users. The slow array warning was not there previously.
Notice that the warning only arises if the event form is changed.
The solution is to be sure that redundant [defconst] forms are
syntactically identical.
ACL2 !>(defconst *a* (compress1 'demo
'((:header :dimensions (5)
:maximum-length 15
:default uninitialized
:name demo)
(1 . one)
(0 . zero))))
Summary
Form: ( DEFCONST *A* ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
*A*
ACL2 !>(aref1 'demo *a* 0)
ZERO
ACL2 !>(defconst *a* (compress1 'demo
'((:header :dimensions (5)
:maximum-length 15
:default uninitialized
:name demo)
(1 . one)
(0 . zero))))
This event is redundant. See :DOC redundant-events.
Summary
Form: ( DEFCONST *A* ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
:REDUNDANT
ACL2 !>(aref1 'demo *a* 0)
ZERO
ACL2 !>(defconst *a* (compress1 'demo
'((:header :dimensions (5)
:maximum-length 15
:default uninitialized
:name demo)
(0 . zero)
(1 . one))))
This event is redundant. See :DOC redundant-events.
Summary
Form: ( DEFCONST *A* ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
:REDUNDANT
ACL2 !>(aref1 'demo *a* 0)
**********************************************************
Slow Array Access! A call of AREF1 on an array named
DEMO is being executed slowly. See :DOC slow-array-warning
**********************************************************
ZERO
ACL2 !>
As before, the von Neumann structure stored in the 'acl2-array
property of the array name contains the array list object in its
[car]. However, previously it was the case that compress1 and
compress2 did not update that car when its new value would be equal
to its old value. This was done largely in support of some type-set
tables defined using [defconst] in type-set-b.lisp. The new
versions of [compress1] and [compress2] are simpler in that no such
exception is made in the case of equal lists, although instead the
entire compression process is short-circuited when the input array
list object is [eq] to the car of the 'acl2-array property. This
change was made because the equality test was causing a ``slow
array access'' warning to be printed in rare cases during proofs,
as described elswhere (see [note-2-7-bug-fixes]).
We no longer distribute documentation specific to Lucid Emacs. The
Info documentation in directory doc/EMACS/ works well both for Gnu
Emacs and XEmacs.
A little-advertised macro, value, has long been allowed for top-level
forms in [books]; see [embedded-event-form]. This has been replaced
by a new macro, value-triple. The two have the same semantics at
the top-level of books, where [state] is ``live''. However,
value-triple should be used at the top-level of a book, while value
should be used in function definitions (as before). This change
eliminates a warning put out by the Allegro Common Lisp compiler
for top-level value forms in [books].")
(NOTE-2-7-PROOF-CHECKER
(NOTE-2-7)
"ACL2 Version 2.7 Notes on Proof-checker Changes
Output from the [proof-checker] can now be inhibited by supplying the
symbol proof-checker in the list given to [set-inhibit-output-lst].")
(NOTE-2-7-PROOFS
(NOTE-2-7)
"ACL2 Version 2.7 Notes on Changes in Proof Engine
An improvement in the linear arithmetic heuristics has been provided
by Robert Krug. For information about this change, search for the
comment in add-linear-lemma (file rewrite.lisp) that begins as
follows.
; Previous to Version_2.7, we just went ahead and used the result of
Thanks, Robert! Also thanks to Eric Smith for providing a motivating
example.
The non-linear-arithmetic addition (see [non-linear-arithmetic]) led
to several small changes in the linear-arithmetic decision
procedure (see [linear-arithmetic]). Two of these changes could
affect existing proofs.
First, when we are setting up the initial arithmetic database (which
we call the ``pot-lst''), we have always scanned it to see if
there were any pairs of inequalities from which we could derive
a previously unknown equality. In some cases we added this
equality to the clause and in others we used it to rewrite the
clause, substituting one side of the equality for the other
throughout the clause. Previously, the heuristics that we used
to determine whether we performed the substitution differed
from those used in several other places in the code. This has
now been regularized, and similar heuristics are now used
throughout the code.
The second change to the linear-arithmetic decision procedure is that
we now explicitly add inequalities derived from type reasoning
to the pot-lst. Previously, we performed cancellations against
these inequalities without adding them to the pot-lst. This
change results in there being more inequalities in the pot-lst
than before, and so more chances for there to be a pair of
inequalities from which an equality can be derived. In effect,
certain simple consequences of the current goal (see
[type-set]) may now be added as hypotheses of the goal or used
to peform equality substitutions.
A slight improvement has been made to the way certain rewrite rules
are stored. It was already the case that a rewrite rule rule whose
conclusion C is not a call of a known equivalence relation (or
[eq], [eql], or [=]) is stored as (iff C t), except that if ACL2
can determine (using its [type-set] mechanism) that C is Boolean,
then the rule is stored as (equal C t). The iprovement is that if C
and C' are Boolean, then a rule stated as (iff C C') is stored as
(equal C C'). Thanks to Pete Manolios for providing an example that
led us to consider this improvement.
The heuristic use of equalities (fertilization) has been modified.
Previously, ACL2 would sometimes substitute using an equality but
keep the equality, and then undo the substitution by using the
equality again. Now, when ACL2 keeps an equality after using it, it
puts the equality inside a call of [hide]. Descendents of that goal
that are unchanged by simplification will have this call of [hide]
removed so that the equality can once again contribute to the
proof. This change can cause some proofs to succeed that otherwise
would fail. In the unlikely event that a proof fails that formerly
succeeded, the following hint on \"Goal\" may fix the problem (see
[hints]):
:expand ((:free (x) (hide x)))
We have refined the heuristics employed when an [if] form is assumed
true or false. Our previous attempt (see [note-2-6-proofs] for the
original announcement) was not as general as we had believed. We
have also improved some low-level code responsible for rewriting IF
expressions. In earlier versions of ACL2, it was possible to have
the truth or falsity of an IF expression explicitly recorded in the
type-alist, and yet not use this information during rewriting. This
problem has been corrected. Thanks to Robert Krug for noticing this
problem and implementing the fix.
We have sped up the rewriter in some cases where there are large
collections of mutually-recursive functions (see
[mutual-recursion]). (Implementation notes: technically, we have
modified the way function being-openedp operates on the fnstack,
and we have modified *current-acl2-world-key-ordering* as described
in the essay above its definition.)
[Forward-chaining] is now done in the preprocessing phase of proof
attempts (see the discussion of :DO-NOT --- see [hints]). This is
part of a technical change, made in support of translation of type
declarations to [guard]s (see [note-2-7-guards]). Previously,
whenever ACL2 checked for [built-in-clause]s, it then looked for a
contradiction using [type-set] reasoning if it did not find a
suitable built-in clause. The change is to perform forward-chaining
in such cases (i.e., when a built-in clause is not found).
A couple of changes have been made in the generation of goals for
[forcing-round]s. Thanks to Eric Smith for bringing issues to our
attention that led to these changes. For one, [guard]s are no
longer relevant in such goal generation. Formerly, the addition of
a guard could make a proof fail that otherwise succeeded. Secondly,
contextual information is now always kept when it involves a
constrained constant, i.e., a zero-ary function introduced in the
signature of an [encapsulate].")
(NOTE-2-7-RULES
(NOTE-2-7)
"ACL2 Version 2.7 Notes on Changes in Rules and Constants
The [defcong] macro has been slightly changed. The difference is that
the variable generated with suffix -EQUIV will now be in the same
package as the name of the variable from which it is generated,
rather than always belonging to the ACL2 package. Thanks to Hanbing
Liu for suggesting this change. (Note that a couple of books have
been modified to accommodate this change, e.g.,
books/finite-set-theory/set-theory.)
In Version_2.6, a change was made for rules of class :[rewrite] whose
conclusion is a term of the form (EQV lhs rhs), where EQV is [=],
[eq], or [eql]: the rule was stored as though EQV were [equal].
(See [note-2-6-rules].) This change has been extended to rules of
class :[definition].")
(NOTE-2-7-SYSTEM
(NOTE-2-7)
"ACL2 Version 2.7 Notes on System-level Changes
ACL2 now runs (once again) under LispWorks, specifically, LispWorks
4.2.0. However, we needed a patch, which presumably will be
unnecessary after 4.2.7. From LispWorks support:
Users with LispWorks4.2.7 should ask us at lisp-support@xanalys.com
for the transform-if-node patch. It will be helpful if they
quote (Lisp Support Call #11372) when doing so. Also, they must
send a bug form generated from their LispWorks image:
instructions at
http://www.lispworks.com/support/bug-report.html.
File books/Makefile-generic has been improved so that failed attempts
to certify a book will cause the `make' to fail. Previously, an
existing .cert file was left in place, and that sufficed for the
`make' to be considered a success. Now, the old .cert file is first
removed when recertification is found to be necessary.
A change has been made to source file acl2.lisp to accommodate GCL
2.4.3. (ACL2 Version 2.6 does not work with some versions of GCL
2.4.3.)
The error message has been improved when certain forms are typed to
raw Lisp and the ACL2 loop has never been entered (with ([lp])).
The following symbols in the ACL2 package have been made untouchable,
meaning that they are not available to the user: ev-fncall, ev,
ev-lst, ev-acl2-unwind-protect, ev-fncall!, and
user-stobj-alist-safe. The reason is that these functions can not
be called safely except under certain restrictions. If you want to
call the ACL2 evaluator, consider using the built-in system
functions trans-eval or simple-translate-and-eval.
CLISP Version_2.30 implements a notion of ``locking'' the \"LISP\"
package that is incompatible with building ACL2. (CLISP
Version_2.27 does not appear to have had this feature.) We have
gotten around this problem by unlocking the \"LISP\" package in ACL2
images built on such CLISPs.
Automatic proclaiming for GCL, which has (for a long time) been done
for functions in compiled books, has been improved. Formerly, the
only time a non-trivial output type (i.e., other than t) was
inferred was when macroexpansion produced an explicit call of
[the]. Now, [if] expressions can also generate non-t output types.
Consider the following example.
(defmacro the-fixnum (n)
(list 'the '(signed-byte 29) n))
(defmacro 1+f (x)
(list 'the-fixnum
(list '1+ (list 'the-fixnum x))))
(defun foo (x)
(declare (type (unsigned-byte 27) x))
(if (zp x)
0
(1+f (foo (1-f x)))))
Formerly, the proclaim forms for foo, before and after this
improvement, are as shown below.
(PROCLAIM '(FTYPE (FUNCTION ((UNSIGNED-BYTE 27)) T) FOO)) ;old
(PROCLAIM '(FTYPE (FUNCTION ((UNSIGNED-BYTE 27)) (SIGNED-BYTE 29)) FOO)) ;new
Compiler info messages sent to error stream were eliminated for
CMUCL.")
(NOTE-2-7{R}
(RELEASE-NOTES)
"ACL2 Version 2.7(r) (November, 2002) Notes
In source file axioms.lisp, in order for proofs to succeed, (make
proofs), the definitions of [ACL2-count] and explode-atom have been
modified slightly, and lemma standard-numberp-one [modified after
Version_3.4 to become standardp-one] has been given :rule-classes
nil.
All [skip-proofs] forms have been eliminated from the nonstd books,
thanks to Ruben Gamboa.
The directory books/sqrt/, which was intended for ACL2(r), has been
moved to books/nonstd/sqrt/ and added as appropriate to
books/nonstd/Makefile.
Please see [note-2-7] for changes to Version_2.7 of ACL2.")
(NOTE-2-8
(RELEASE-NOTES)
"ACL2 Version 2.8 (March, 2004) Notes
BRIEF SUMMARY.
The Version_2.8 notes are divided into the indicated subtopics. Here
we give only a brief summary of just a few of the major new
features and changes that seem most likely to impact existing
proofs. Not included in this brief summary, but included in the
subtopics, are descriptions of many improvements (including bug
fixes and new functionality) that should not get in the way of
existing proof efforts. In the description below we also omit
discussion of changes that will become clear by way of error
messages if they affect you.
In particular, please see [note-2-8-new-functionality] for discussion
of a number of new features that you may find useful.
Acknowledgements and elaboration, as well as other changes, can be
found in the subtopics listed below.
Some of the bug fixes (see [note-2-8-bug-fixes])
* Some soundness bugs were fixed.
* The handling of free variables in hypotheses (see [free-variables])
of rewrite and linear rules had a bug that prevented some
proofs from going through. Now that this bug has been fixed,
you may find some proofs running much more slowly than before.
You can use [accumulated-persistence] and
[add-match-free-override] to remedy this situation; see
[note-2-8-bug-fixes] for details.
* The [default-hints] in the current logical [world] are no longer
ignored by [verify-guards].
* Forms violating guard-checking such as (defconst *silly* (car 3)) are
now allowed in [books].
Some of the new functionality (see [note-2-8-new-functionality])
* WARNING: You may find that control-d (in emacs, control-c control-d)
can throw you completely out of Lisp where it had not formerly
done so.
* ACL2 now starts up inside the ACL2 loop --- that is, ([lp]) is
executed automatically --- when built on CLISP or Allegro CL.
This was already the case for GCL and CMUCL, and it still is
not true for LispWorks.
* See [note-2-8-ordinals] for a discussion of a significant change in
ordinal represtation, and in particular, for how to preserve
existing proofs that depend on the previous ordinal
representation.
* Macros [mbe] (``must be equal''), [mbt] (``must be true''), and
[defexec] have been introduced, which allow the user to attach
alternate executable definitions to functions.
* The user can now control multiple matching for free variables in
hypotheses for :[forward-chaining] rules, as has already been
supported for :[rewrite] and :[linear] rules.
* It is no longer necessary to specify (set-match-free-error nil) in
order to avoid errors when a rule with free variables in its
hypotheses is missing the :match-free field.
* The form (break-on-error) causes, at least for most Lisps, entry into
the Lisp debugger whenever ACL2 causes an error.
* A new [table] has been provided so that advanced users can override
the built-in untranslate functionality. See
[user-defined-functions-table].
* The [pstack] (`process [prover] stack'') mechanism, formerly denoted
checkpoints, has been improved. One of these improvements is to
show actual parameters with (pstack t) rather than formals.
* The [defstobj] event is now allowed to take an :inline argument,
which can speed up execution.
* Macro [cw-gstack] no longer takes arguments for the gstack or
[state]. To print terms in full rather than abbreviated:
(cw-gstack :evisc-tuple nil).
* The [include-book] event now has an additional (optional) keyword,
:dir. In particular, (include-book \"foo/bar\" :dir :system) will
include the indicated book after prepending the path of the
built-in books/ directory. You will probably not find :dir
:system to be useful if you move the executable image or
distributed books; see [include-book], in particular its
``soundness warning''.
* The printing of results in raw mode (see [set-raw-mode]) may now be
partially controlled by the user: see [add-raw-arity].
* For those using Unix/Linux `make': A cert.acl2 file can contain forms
to be evaluated before an appropriate [certify-book] command is
invoked automatically (not included in cert.acl2).
Some of the changes in the proof engine (see [note-2-8-proofs])
* ACL2 now prevents certain rewriting loops; see [rewrite-stack-limit].
* Small changes have been made to heuristics for controlling rewriting
during proofs by induction and in handling certain ``weak''
[compound-recognizer] rules.
* The handling of free variables in a hypothesis of a [rewrite] rule
(see [free-variables]) has been improved in the case that the
hypothesis is of the form (equiv x y), where equiv is a known
equivalence relation (see [equivalence]).
* We have modified how the ACL2 simplifier handles the application of a
defined function symbol to constant arguments, by avoiding the
introduction of [hide] when evaluation fails if the term can be
rewritten.
* The generation of \"Goal\" for recursive (and mutually-recursive)
definitions now uses the subsumption/replacement limitation
(default 500). See [case-split-limitations].
* Default hints now apply to hints given in definitions, not just
theorems. See [default-hints].
* Linear arithmetic now uses the conclusions of [forward-chaining]
rules, and [type-set] now uses a small amount of linear
reasoning when deciding inequalities.
Some of the changes in rules, definitions, and constants (see
[note-2-8-rules])
* See the above doc topic.
Guard-related changes are described in see [note-2-8-bug-fixes]
Some of the proof-checker changes (see [note-2-8-proof-checker])
* Added new [proof-checker] commands wrap1, wrap, and wrap-induct, to
combine multiple conjuncts or goals.
* The type-alist command now takes optional arguments that control
whether or not the governors and/or conclusion are used in
computing the context.
Some of the system-level changes (see [note-2-8-system])
* ACL2 now runs on OpenMCL and on MCL 5.0.
Some of the other changes (see [note-2-8-other])
* Emacs file emacs/emacs-acl2.el has been updated (see [note-2-8-other]
for details).
* When :pl is given a term other than a symbol, it will print all
rewrite rules that match that term.
* A new function, [pkg-witness], returns a symbol in the given package.
* The list constant *acl2-exports* has been extended.
* A new release of the rtl library has been included: books/rtl/rel4/.
See the README file in that directory.
Again, please proceed to the subtopics for more thorough release
notes.
Subtopics
[Note-2-8-bug-fixes]
ACL2 Version 2.8 Notes on Bug Fixes
[Note-2-8-guards]
ACL2 Version 2.8 Notes on Guard-related Changes
[Note-2-8-new-functionality]
ACL2 Version 2.8 Notes on New Functionality
[Note-2-8-ordinals]
ACL2 Version 2.8 Notes on Changes to the Ordinals
[Note-2-8-other]
ACL2 Version 2.8 Notes on Miscellaneous Changes
[Note-2-8-proof-checker]
ACL2 Version 2.8 Notes on Proof-checker Changes
[Note-2-8-proofs]
ACL2 Version 2.8 Notes on Changes in Proof Engine
[Note-2-8-rules]
ACL2 Version 2.8 Notes on Changes in Rules, Definitions, and
Constants
[Note-2-8-system]
ACL2 Version 2.8 Notes on System-level Changes")
(NOTE-2-8-BUG-FIXES
(NOTE-2-8)
"ACL2 Version 2.8 Notes on Bug Fixes
We have fixed a soundness bug in the tautology checker's handling of
expressions of the form (not (not x)). This bug has gone back at
least as far as Version_2.4. All of the regression tests passed
after the fix, without modification. So we hope that this bug has
rarely bitten anyone. Thanks to Qiang Zhang for sending us a proof
of nil that led us to this fix: (thm (equal (and p q) (not (or (not
p) (not q))))). And thanks to Matyas Sustik for an observation that
led to an improvement of our initial fix.
The preceding version (2.7) introduced a soundness bug in handling of
ACL2 [arrays], in which functions [compress1] and [compress2] were
returning the input alist rather than compressing it appropriately.
Here is a proof of nil that no longer succeeds, based on a bug
report from Warren Hunt, who we thank for bringing this problem to
our atttention.
(defthm bad
(not (let* ((ar2 (aset1 'my-array ar1 3 10))
(ar3 (compress1 'my-array ar2))
(ar4 (reverse (reverse ar2)))
(ar5 (compress1 'my-array ar4)))
(and (equal ar2 ar4)
(not (equal ar3 ar5)))))
:rule-classes nil)
(defthm contradiction
nil
:rule-classes nil
:hints ((\"Goal\" :use
((:instance bad
(ar1 (compress1 'my-array
'((3 . 5)
(:HEADER :DIMENSIONS (5)
:MAXIMUM-LENGTH 6
:DEFAULT 0
:NAME MY-ARRAY)))))))))
On a related note, a new function [flush-compress] can be used for
subtle control of under-the-hood raw Lisp support for fast array
access, although we expect it to be very rare that users need this
extra support.
Previous versions have had two soundness bugs that can occur when
using the [proof-checker]:
* The first bug pertains to the expand command, and hence x and x-dumb
commands (which call expand); see [proof-checker-commands]. The
bug can occur when applying the above commands when the current
term is a call of a constrained function symbol for which there
is a :[definition] rule. Now, the expand command will succeed
only when the function symbol of the current term is a defined
function symbol, in which case the original definition is
always used, in analogy to how the :expand hint works in the
prover; see [hints]. Thanks to John Erickson for sending an
example that led us to wonder if there might be a soundness
problem.
* The second bug pertains to the s command (and commands that call it,
e.g., s-prop). The proof-checker forms a context out of the
top-level hypotheses and the if-terms governing the current
term. If there is a contradiction in the top-level hypotheses,
the proof-checker can appropriately consider the goal to be
proved, and it does so. But formerly, the criterion was weaker:
the contradiction could involve the combination of the
top-level hypotheses and if-term governors. Thanks to Rob
Sumners for noticing this bug.
A soundness bug could be provoked in some Lisps by applying [defpkg]
to the empty string. This has been disallowed.
We fixed a soundness bug related to packages caused by a failure to
track axioms introduced [local]ly on behalf of [defpkg] events. See
[hidden-death-package].
We fixed a soundness bug caused by a failure to check that a
:[type-prescription] rule can be processed when proofs are skipped
or under a [defequiv] event. The former case can occur when
processing an [encapsulate] or [include-book] event, where the rule
could depend on a [local] :[compound-recognizer] rule preceding the
proposed :[type-prescription] rule under the same [encapsulate] or
[include-book] event. See [local-incompatibility] for such an
example.
We fixed a potential soundness bug relating to reclassifying a
:program mode function to :logic mode (as done by
[verify-termination] or the submission of an appropriate
``redundant'' definition) without adequate checking that [stobj]
usage was identical. Allegedly redundant definitions must now
preserve the stobjs declaration as well as the formals, body, guard
and type declarations. We thank Vernon Austel for pointing out this
problem.
It was possible to get a raw Lisp error by introducing a [local]ly
defined function with [guard] verification inhibited and then
subsequently introducing the same definition non-locally without
that inhibition. The following example will clarify.
(encapsulate nil
(local
(defun foo (x) (declare (xargs :guard t :verify-guards nil)) (car x)))
(defun foo (x) (declare (xargs :guard t)) (car x)))
; The following causes a raw lisp error because ACL2 runs the Common Lisp
; definition of foo, because it thinks that foo's guard of t was verified.
(thm (equal (foo 3) xxx))
Thanks to Jared Davis for bringing this problem to our attention. We
are particularly grateful to Jared because his example exploited
this bug by applying it to a function defined using [mbe]
(introduced in this same version, 2.8), in order to prove nil!
The sort of error message shown below can legitimately occur when
certifying a book in a certification world where there was an
[include-book] command with a relative pathname (see [pathname]).
However, it was occurring more often than necessary. This has been
fixed.
ACL2 Error in (CERTIFY-BOOK \"foo\" ...): The certification world has
include-book commands for book \"bar\" that correspond to
different full pathnames, namely \"/u/dir1/bar\" and
\"/u/dir2/bar\". ACL2 cannot currently certify a book in such a
world. To work around this problem, use an absolute pathname
for at least one of these books (see :DOC pathname).
Bugs were fixed in [with-output], in particular related to the use of
values :all. Also, documentation for with-output has been improved.
Thanks to Vernon Austel for pointing out the bugs.
Fixed a lisp error occurring when bash proof-checker command was
given illegal syntax, e.g., (bash ((\"Goal\" :in-theory (enable
binary-append)))) instead of (bash (\"Goal\" :in-theory (enable
binary-append))).
We added an appropriate guard to [find-rules-of-rune], which will
avoid hard lisp errors when this function is called on non-[rune]
arguments. Thanks to Eric Smith for pointing out this issue.
It was possible for a redundant [include-book] form (see
[redundant-events]) to leave a [command] in the ACL2 logical
[world] and to cause (re-)loading of a compiled file. These
behaviors have been fixed. In particular, if book1 has already been
included in the current ACL2 [world] and (include-book \"book1\")
occurs in book2, then the compiled file for book1 will not be
loaded again when book2 is included. Thanks to Dave Greve for
bringing our attention to these problems, and to Eric Smith for
bringing up a special case earlier (where \"//\" occurred in the book
name).
The summary printed at the end of a proof had not listed :[induction]
rules used in a proof. This has been corrected.
The use of proof trees in emacs redefined `control-c control-c' in
such a way that in telnet mode, the telnet session was interrupted
and perhaps could not be continued. This has been fixed.
Source function load-theory-into-enabled-structure contained a
guard-violating call of [compress1]. Thanks to Vernon Austel for
bringing this problem to our attention; even though this bug was
benign (as he pointed out), we like keeping the source code free of
guard violations.
A number of proof-checker atomic macros caused a hard error when all
goals have already been proved. This has been fixed. Thanks to John
Erickson for sending an example of the issue.
A bug has been fixed in [add-match-free-override]. Formerly, a
[table] [guard] violation occurred when calling
[add-match-free-override] more than once with first argument other
than :clear.
Defininitions of functions involving large constants could cause
stack overflows. This has been fixed, at least in some of the most
egregious cases (by making a source function fn-count-evg
tail-recursive). Thanks to Jared Davis for bringing this problem to
our attention.
Evaluation of computed hints could cause stack overflows. This has
been fixed. Thanks to Eric Smith for bringing this problem to our
attention.
Evaluation of :[monitor] on :[definition] [rune]s is now fast even if
the specified function is part of a very large [mutual-recursion]
nest. Thanks to Eric Smith for sending an example showing that this
wasn't always the case.
Fixed a bug in books/bdd/cbf.lisp that was causing certification of
distributed bdd books to fail when the connected book directory
(see [cbd]) differs from the current working directory. Thanks to
Scott Guthery for bringing this bug to our attention and supplying
a helpful log.
Duplicate rule names have been eliminated from warnings generated
upon the use of enabled :[rewrite] or :[definition] rules. Thanks
to Eric Smith for pointing out this problem.
The trace utilities (see [trace]), as modified for GCL and Allegro
Common Lisp, had failed to show more than the first return value
for so-called ``*1*'' functions (essentially,
[executable-counterpart] functions) when they were returning
multiple values (via [mv]). This has been fixed. Thanks to Erik
Reeber for pointing out this problem. Also, it is now possible to
refer to arglist in [trace$] forms when ACL2 is built on GCL, not
just when ACL2 is built on Allegro Common Lisp.
Uses of [hide] introduced during proofs by failed attempts to
evaluate constrained functions (see [hide]) are now tracked, so
that the [rune] (:DEFINITION HIDE) will show up in the summary.
The following bug, introduced back in Version 2.7, has been fixed.
The bug applied only to GCL and may well not have affected anyone.
But the function proclamation computed by ACL2 for compilation
usually had an output type of nil where it should have been t.
The macro [gc$] had a bug exhibited when it was supplied one or more
arguments. This has been fixed.
The macro [defabbrev] broke when supplied a string and no
documentation, e.g., (defabbrev foo () \"\"). Thanks to Rob Sumners
for noticing this problem and providing a fix, which we have
incorporated.
For ACL2 executables built on Allegro Common Lisp, a Lisp error
occurred when [trace$] was called on other than a defined function
symbol. Now ACL2 prints a more useful error message.
The proof-checker no longer accepts a ([verify]) command when some
function symbol in the original goal no longer exists in the
current ACL2 logical [world]. Thanks to John Erickson for bringing
this issue to our attention.
The function ld-redefinition-action may now be called by the user.
Thanks to Vernon Austel for suggesting that we remove this symbol
from the list of so-called untouchables.
The handling of free variables in hypotheses (see [free-variables])
of rewrite and linear rules had a bug that prevented some proofs
from going through. Here is a simple example, essentially provided
by Diana Moisuc, who we thank for bringing this issue to our
attention. The proof of the [thm] below had failed, but now will
succeed. This particular bug prevented, for example, the :all
behavior from occurring when the first hypothesis of the rule does
not have free variables. NOTE: Now that this bug has been fixed,
you may find some proofs running much more slowly than before. You
can use [accumulated-persistence] to locate rules that are slowing
down your proofs because of excessive attention to free variables,
and then execute [add-match-free-override] for those rules (or,
just change the rules themselves to specify :once in the
:[rule-classes]).
(defstub foo1 (* ) => *)
(skip-proofs
(defthm aux-foo1
(implies (and (integerp a)
(integerp i)
(equal (foo1 0) (list 0 i)))
(equal (foo1 a) (list 0 (+ a i))))
:rule-classes ((:rewrite :match-free :all))))
(thm
(implies (and (integerp i)
(integerp a)
(equal (foo1 0) (list 0 i)))
(equal (foo1 a) (list 0 (+ a i)))))
Formerly, creation of large arrays could cause an error in the
underlying Common Lisp implementation without helpful messages for
the user. Now, we check Common Lisp restrictions on arrays and
print a helpful error message if they are violated, namely: each
dimension must be less than the value of Common Lisp constant
array-dimension-limit, and the product of the dimensions must be
less than the value of Common Lisp constant array-total-size-limit.
Thanks to Warren Hunt for bringing this issue to our attention.
Note: this change also removes a former restriction of [stobj]
array fields to size smaller than 2^28-1, provided the underlying
Lisp can support larger arrays.
The [default-hints] in the current logical [world] were ignored by
[verify-guards]. This has been fixed. Thanks to Jared Davis for
pointing out this bug and sending a helpful example.
The [brr] mechanism has been cleaned up in order to avoid hard errors
and infinite loops that can arrive when typing interrupts
(control-c) or end-of-files (control-d) inside the [brr] loop.
Thanks to Dave Greve, Olga Matlin, Eric Smith, and Serita Van
Groningen for bringing this issue to our attention. As a byproduct,
if you type control-d (or if inside emacs, control-c control-d),
you may now quit entirely out of ACL2 and lisp (see [good-bye]) in
some cases where you formerly would not have, for example when
sitting at the ACL2 prompt (which formerly, in Allegro Common Lisp
for example, would merely take you into raw Lisp rather than
quitting everything).
We have eliminated structural flaws in the HTML documentation pages
that could make them unreadable in some browsers. Thanks to Bill
Young for bringing this issue to our attention and to Joe Hendrix
for diagnosing the problem.
The [proof-checker] could run very slowly after many instructions in
a given session. This has been fixed; thanks to Art Flatau for
bringing this problem to our attention. (Implementation detail: We
now keep tag-trees duplicate-free when we accumulate them into
state. This change could have minor speed advantages for some
top-level proofs too, not just in the proof-checker.)
The printing of accesses to stobjs using nth or update-nth has been
done using symbolic constants since ACL2 Version_2.6. However,
there was a bug that prevented this feature from working for
[update-nth] except at a top-level call. This has been fixed.
Thanks to Julien Schmaltz for bringing this problem to our
attention. For example, consider these events:
(defstobj st field0 field1)
(thm (equal (nth 1 (update-nth 0 17 st)) (car (cons xxx yyy)))
:hints ((\"Goal\" :in-theory (disable nth update-nth))))
Before the fix, the proof attempt of the above silly thm printed the
following.
(NTH 1 (UPDATE-NTH *FIELD0* 17 ST))
After the fix, we instead see the following.
(NTH *FIELD1* (UPDATE-NTH *FIELD0* 17 ST))
It is now possible to certify and subsequently include [books] that
require guard-checking to be off. For example, the book can contain
the form (defconst *silly* (car 3)) even though 3 fails to satisfy
the guard of [car]. Formerly, it was necessary to execute
:[set-guard-checking] nil before a [certify-book] or [include-book]
in order for such a form to be handled without error. Thanks to
Hanbing Liu for bringing this problem to our attention.
Fixed a [proof-checker] bug that could cause probably cause strange
error, ``Attempt to access the plist field''. Thanks to Bill Young
for bringing this problem to our attention.
Fixed a [proof-checker] bug that was failing to record applications
of rewrite rules using the proof-checker's :rewrite command,
causing the proof summary to omit mention of that rule (for
example, when using the proof-checker's :exit command to generate
an :instructions hint). Thanks to Bill Young for pointing out this
bug.
Modernized some of the proof-tree emacs and infix printing stuff,
thanks to suggestions made by Camm Maguire.")
(NOTE-2-8-GUARDS
(NOTE-2-8)
"ACL2 Version 2.8 Notes on Guard-related Changes
All the guard-related changes may be found elsewhere; in particular,
see [note-2-8-bug-fixes].")
(NOTE-2-8-NEW-FUNCTIONALITY
(NOTE-2-8)
"ACL2 Version 2.8 Notes on New Functionality
WARNING: You may find that control-d (in emacs, control-c control-d)
can throw you completely out of Lisp where it had not formerly done
so.
(CLISP and Allegro CL only) ACL2 now starts up inside the ACL2 loop
--- that is, ([lp]) is executed automatically --- when built on
CLISP or Allegro CL. This was already the case for GCL and CMUCL,
and it still is not true for LispWorks. Thanks to Joe Corneli for
bringing the CLISP command-line option \"-i\" to our attention, which
led to this CLISP change and inspired reconsideration of how to do
this for Allegro CL.
Pete Manolios and Daron Vroon have changed the representation of
ordinals in ACL2, defined algorithms for ordinal arithmetic, and
created a library of theorems to reason about ordinal arithmetic.
We thank them for these nice contributions. See [note-2-8-ordinals]
for details, in particular, for how to preserve existing proofs
that depend on the previous ordinal representation.
Sometimes users create rules of class :[rewrite] that cause an
infinite loop in the ACL2 rewriter. This has lead to Lisp stack
overflows and even segmentation faults. Now, the depth of calls of
functions in the ACL2 rewriter is limited, and under user control.
See [rewrite-stack-limit].
Macros [mbe] (``must be equal'') and [mbt] (``must be true'') have
been introduced, which allow the user to attach fast executable
definitions to (presumably slower) :[logic] mode functions. Thanks
to Vernon Austel for a key idea. Also provided is a macro
[defexec], which employs [mbe] but enforces the requirement that
the executable definition also terminates. Thanks to Jose Luis Ruiz
Reina for collaborating in the design and development of [defexec],
and for useful comments from a number of others as well in the
development of mbe including Joe Hendrix and Rob Sumners.
Definitions have been added for functions [rassoc-eq] and
[rassoc-equal], which are like [rassoc] but use different tests and
have different guards. (Compare [assoc-eq] and [assoc-equal], which
are in similar relation to [assoc].)
The user can now control multiple matching for free variables in
hypotheses for :[forward-chaining] rules, as has already been
supported for :[rewrite] and :[linear] rules. For :forward-chaining
rules, ``free variables'' are those in the hypotheses not bound by
a given trigger term. As for :rewrite and :linear rules,
free-variable matching may be limited to the first successful
attempt by specifying :match-free :once with :forward-chaining in
the :[rule-classes], and [add-match-free-override] may be used to
modify the behavior of an existing rule. Thanks to Erik Reeber for
most of the implementation of these new capabilities, as well as
significant assistance with a corresponding new documentation topic
(see [free-variables-examples-forward-chaining]).
It is no longer necessary to specify (set-match-free-error nil) in
order to avoid errors when a rule with free variables in its
hypotheses is missing the :match-free field. (This was already true
during book certification, but now it is the case in interactive
sessions as well.)
The form (break-on-error) causes, at least for most Lisps, entry into
the Lisp debugger whenever ACL2 causes an error. See
[break-on-error]. Thanks to John Erickson for providing
encouragement to provide this feature.
A new [table] has been provided so that advanced users can override
the built-in untranslate functionality. See
[user-defined-functions-table].
The [pstack] mechanism (formerly denoted checkpoints) has been
improved. The ``process [prover] stack,'' or pstack, is
automatically printed when proofs abort. Evaluation of function
calls on explicit arguments during proofs is now tracked. Actual
parameters are shown with (pstack t) rather than formals. Thanks to
Bill Legato for suggesting the first two of these improvements and,
in general, encouraging changes that make ACL2 easier to use.
The [defstobj] event is now allowed to take an :inline argument,
which can speed up execution. Thanks to Rob Sumners for suggesting
and implementing this new feature.
Macro [assert$] has been added in order to make it easy to write
assertions in one's code. Semantically, (assert$ test form) is the
same as form, but it causes a hard error (using [illegal]) if test
evaluates to nil.
Macro [cw-gstack] no longer takes arguments for the gstack or
[state]. However, it now takes a keyword argument (which is
optional), :evisc-tuple, that can be used to control how it prints
terms. In particular, cw-gstack abbreviates large terms by default,
but (cw-gstack :evisc-tuple nil) causes terms to be printed in
full. Thanks to Robert Krug and Eric Smith for requesting this
improvement.
The advanced user now has more control over the evisceration of
terms. See [ld-evisc-tuple], in particular the new paragraph on
``The printing of error messages and warnings.''
The [include-book] event now has an additional (optional) keyword,
:dir. The value of :dir should be a keyword that is associated with
an absolute directory pathname to be used in place of the current
book directory (see [cbd]) for resolving the first argument of
include-book to an absolute pathname. At start-up, the only such
keyword is :system, so that for example (include-book
\"arithmetic/top\" :dir :system) will include the book
\"arithmetic/top\" under the \"books/\" directory of your ACL2
installation. But you can associate ``projects'' with keywords
using [add-include-book-dir], e.g., (add-include-book-dir
:my-project \"/u/smith/project0/\"). See [add-include-book-dir] and
also see [delete-include-book-dir] and see [include-book]. Note:
You will probably not find :dir :system to be useful if the
distributed books are not placed in the path of their original
location, pointed to by :dir :system, which will often happen if
the executable image is obtained from another site. Also see
[include-book], in particular its ``soundness warning''.
The printing of results in raw mode (see [set-raw-mode]) may now be
partially controlled by the user: see [add-raw-arity]. Also,
newlines are printed when necessary before the value is printed.
For those using Unix/Linux `make': A cert.acl2 file can contain forms
to be evaluated before an appropriate [certify-book] command is
invoked automatically (not included in cert.acl2).
Jared Davis has contributed a new set of books for ordered finite set
theory to the standard distribution,
books/finite-set-theory/osets-0.81/. See the README file in that
directory. Thanks, Jared.
Robert Krug has contributed two related changes (thanks, Robert!) in
support of stronger arithmetic reasoning. First, one can now enable
and disable nonlinear arithmetic with a :nonlinearp hint, which
will override the default provided by [set-non-linearp] (initially,
nil). See [hints]. Second, [computed-hints] can now have access to
the HISTORY, PSPV, and CTX variables of the waterfall, which (for
example) allows the writing of a hint which will enable nonlinear
arithmetic on precisely those goals that are
stable-under-simplificationp. See [computed-hints].
Robert Krug has contributed a new set of arithmetic books to the
standard distribution, books/arithmetic-3/. See the README file in
that directory. Thanks, Robert.")
(NOTE-2-8-ORDINALS
(NOTE-2-8)
"ACL2 Version 2.8 Notes on Changes to the Ordinals
Please see [ordinals].")
(NOTE-2-8-OTHER
(NOTE-2-8)
"ACL2 Version 2.8 Notes on Miscellaneous Changes
Execution of [table] events has been sped up in many cases by
avoiding excessive consing.
ACL2 now warns if :[rewrite] (or :[definition]) rules contain free
variables on the right-hand side. Thanks to Dave Greve for raising
this issue.
Emacs file emacs/emacs-acl2.el has been updated to better comprehend
the notion of the ``ACL2 shell'', which is the buffer to which ACL2
forms are written by commands defined in the above file. Thus,
command control-t e has been modified always to write to the ACL2
shell (which is \"*shell*\" by default), and the following new
commands have been defined.
o control-t c
Set the ACL2 shell to the current buffer. o control-t b
Change to the ACL2 shell.
The commands :[pl] and :[pr] may now be given a macro name that
corresponds via the macro-aliases-table to a function name, so that
for example :pl append is treated the same as :pl binary-append. A
more interesting improvement, for :pl only, is that :pl may now
take any term. When :pl is given a term other than a symbol, it
will print all rewrite rules that match that term. Thanks to David
Russinoff, Robert Krug, and Bill Legato for getting this going.
A new function, [pkg-witness], returns a symbol in the given package.
The installation instructions have been updated, for example to give
more guidance on obtaining Lisp implementations and to mention the
acl2-help mailing list.
Jared Davis has suggested some symbols to be added to *acl2-exports*,
and we have done so. Thanks, Jared.
o MFC (used in [syntaxp] and [extended-metafunctions]; thanks also to
Robert Krug for this one) o ID, CLAUSE, WORLD, and
STABLE-UNDER-SIMPLIFICATIONP (used in [computed-hints]) o
[set-default-hints]
The command :[pe] has been improved so that when the event is inside
an included book, the path of included books (from the top-level
book down to the one containing the event) is shown. Thanks to Eric
Smith (perhaps among others) for pointing out the utility of this
improvement.
A new release of the rtl library has been included: books/rtl/rel4/.
See the README file in that directory.")
(NOTE-2-8-PROOF-CHECKER
(NOTE-2-8)
"ACL2 Version 2.8 Notes on Proof-checker Changes
Added new [proof-checker] commands wrap1, wrap, and wrap-induct. Wrap
replaces multiple goals by their conjunction: (wrap instr1 instr2
...) employs wrap1 so that the indicated instructions create only
at most one new goal. Wrap-induct is a simple example of the use of
wrap, so that induction creates only one goal (the conjunction of
the base and induction steps). Wrap1 can be used immediately after
a prover call (bash, prove, reduce, bdd, or induct) to collapse the
new goals into one. See [proof-checker-commands].
The [proof-checker] command = failed to work as expected when a
governing IF-test of the current term is T. This has been fixed (by
fixing source function conjuncts-of). Thanks to Yoann Padioleau for
bringing this problem to our attention.
The type-alist command now takes optional arguments that control
whether or not the governors and/or conclusion are used in
computing the context that is printed (see
[proof-checker-commands], specifically subtopic type-alist). Thanks
to Rob Sumners for suggesting this improvement.
The macro [toggle-pc-macro] has always taken an optional second
argument of atomic-macro or macro. However, this was not clearly
documented, and those two symbols had to be in the ACL2 package.
Both of these problems have been remedied. Thanks to John Erickson
for bringing the lack of documentation of the second argument to
our attention.")
(NOTE-2-8-PROOFS
(NOTE-2-8)
"ACL2 Version 2.8 Notes on Changes in Proof Engine
ACL2 now prevents certain rewriting loops; see [rewrite-stack-limit].
During the computation of [constraint]s for functional instantiation,
(prog2$ term1 term2) and (the type term2) are now treated as term2.
A change has been made in heuristics for controlling rewriting during
proofs by induction. Formerly, during induction proofs, ACL2
suppressed rewriting of certain ``induction hypothesis'' terms, and
forced expansion of certain ``induction conclusion'' terms, until
rewriting had stabilized. This meddling with the rewriter is still
turned off when rewriting has stabilized, but it is now turned off
earlier once an ancestor has been through the rewriter and the
current goal is free of ``induction conclusion'' terms. Thanks to
Dave Greve and Matt Wilding for providing an example and associated
analysis that led us to look for a heuristic modification.
A change has been made in the heuristics for handling certain
``weak'' [compound-recognizer] rules when building contexts. Those
who want to dig deeply into this change are welcome to look at the
code following the call of most-recent-enabled-recog-tuple in the
code for function assume-true-false in the ACL2 sources.
The handling of free variables in a hypothesis of a [rewrite] rule
(see [free-variables]) has been improved in the case that the
hypothesis is of the form (equiv x y), where equiv is a known
equivalence relation (see [equivalence]). Previously, if the
rewriter was attempting to rewrite the hypothesis (equiv x y) of a
rewrite rule, in a context where x' is an instance of x, then the
rewriter could fail to notice a term (equiv x' y') true in the
current context where y' is an instance of y, in the case that x'
precedes y' in the [term-order]. This has been remedied. This
improvement applies regardless of whether x, y, or (we believe)
both are already fully instantiated in the present context. Thanks
to Joe Hendrix for bringing up an example and to Vernon Austel for
providing another, simple example.
A very minor change has been made to the rewriter in the case that an
equality appears on the left-hand side of a :[rewrite] rule.
Formerly, when such an equality (equal x y) was commuted to (equal
y x) in order for the rule to match the current term, then all
equalities on the instantiated right-hand side of the rule were
commuted, except for those occurring inside another equality. The
instantiated right-hand side is no longer modified. It seems very
unlikely that this change will cause proofs to fail, though we
cannot completely rule out that possibility.
We have modified how the ACL2 simplifier handles the application of a
defined function symbol to constant arguments in certain cases,
which we now describe. As before, ACL2 attempts to simplify such a
function application by evaluation, provided the
:[executable-counterpart] of the function is enabled. And as
before, if that evaluation fails due to a subroutine call of a
constrained function (introduced by [encapsulate]), ACL2 may wrap a
call of hide around this function application. (See [hide].) But
now, ACL2 attempts to apply definitions and rewrite rules in the
case that this evaluation fails, and only if the resulting term is
unchanged does ACL2 wrap [hide] around this function application.
Thanks to Matt Wilding for bringing up the idea of this
modification.
The generation of \"Goal\" for recursive (and mutually-recursive)
definitions now uses the subsumption/replacement limitation
(default 500). See [case-split-limitations].
Default hints now apply to hints given in definitions, not just
theorems. See [default-hints].
Thanks to Robert Krug for implementing the following two improvements
involving linear arithmetic reasoning: linear arithmetic now uses
the conclusions of [forward-chaining] rules, and [type-set] now
uses a small amount of linear reasoning when deciding inequalities.")
(NOTE-2-8-RULES
(NOTE-2-8)
"ACL2 Version 2.8 Notes on Changes in Rules, Definitions, and
Constants
The [theory] [minimal-theory] has been changed by adding the
[definition] [rune] for [mv-nth] to the theory. A corresponding
change has been made to the theory warning mechanism, which was
failing to warn if the definition of mv-nth is disabled, even
though calls of mv-nth can be expanded by special-purpose code in
the rewriter. Thanks to Serita Van Groningen for pointing out this
problem with the theory warning mechanism.
The [defevaluator] event has been modified so that in the body of the
evaluator function, to add a new case (ATOM X) (returning nil) has
been inserted immediately after the case (EQ (CAR X) 'QUOTE). This
is a no-op semantically but may speed up proofs. Thanks to Warren
Hunt for suggesting this change.
A new form of :[compound-recognizer] rule is now allowed:
(if (fn x) concl1 concl2)
This is equivalent to an existing form:
(and (implies (fn x) concl1)
(implies (not (fn x)) concl2))
Thanks to Josh Purinton for bringing this to our attention.
Rewrite rules realpart-+ and imagpart-+ have been added in order to
simplify the [realpart] and [imagpart] (respectively) of a sum.
They follow from a theorem add-def-complex that equates a sum with
the complex number formed by adding real and imaginary parts. All
three of these theorems may be found in source file axioms.lisp.
Thanks to Eric Smith for raising a question leading to these
additions, as well as to Joe Hendrix and Vernon Austel for helpful
suggestions.")
(NOTE-2-8-SYSTEM
(NOTE-2-8)
"ACL2 Version 2.8 Notes on System-level Changes
ACL2 now runs on OpenMCL, ``an opensourced Common Lisp
implementation, derived from Digitool's Macintosh Common Lisp
product.'' Thanks to Greg Wright and Robert Krug for doing most of
the work for this port.
When ([lp]) is first executed, the underlying raw Lisp package will
change to \"ACL2\" (if that is not already the current package in raw
Lisp). This is a minor change that will probably not be noticed,
since up to now it has probably been the case that the ACL2
executable starts up with \"ACL2\" as the underlying raw Lisp
package. But this change was made because we have been informed
that ACL2 executables based on OpenMCL need not start up with
\"ACL2\" as the underlying raw Lisp package.
ACL2 now runs on MCL 5.0. Thanks to Pascal Costanza for updates to
the instructions in file mcl-acl2-startup.lisp and for an update to
the ACL2 sources (parameter *compiled-file-extension*).")
(NOTE-2-8{R}
(RELEASE-NOTES)
"ACL2 Version 2.8(r) (March, 2003) Notes
The Makefile has been modified by adding a new target, clean-links.
This can be used in order to remove all soft links, which is useful
if the directory is copied or moved to a new location or if there
are file system changes that cause problems with link pathnames.
Please also see [note-2-8] for changes to Version_2.8 of ACL2.")
(NOTE-2-9
(RELEASE-NOTES)
"ACL2 Version 2.9 (October, 2004) Notes
Table of Contents
* BUG FIXES
* NEW FUNCTIONALITY
* CHANGES IN PROOF ENGINE
* GUARD-RELATED CHANGES
* PROOF-CHECKER CHANGES
* SYSTEM-LEVEL CHANGES
* BOOK CHANGES
* MISCELLANEOUS CHANGES
BUG FIXES.
We fixed a soundness bug due to a conflict between user-supplied
package names and internal package names (obtained by prepending a
Lisp constant, *1*-package-prefix*) and user-supplied package
names. For example, the form (defpkg \"ACL2_*1*_MYPKG\" ()) is no
longer legal. Thanks to Robert Krug for asking a question that led
directly to the discovery of this bug.
We fixed a soundness bug that allows :[logic] mode functions to call
:[program] mode functions. The fix furthermore prevents functions
with [guard]s verified from calling functions with guards not
verified. We had thought we already prevented all this, but there
was a problem with the interaction of [local] definitions and
redundancy checking (see [redundant-events]).
We fixed a soundness bug that could occur when built-in functions
were called during macroexpansion (a hole in so-called
``safe-mode'').
Fixed a minor bug in system functions genvar1 and genvar, where [eq]
had been used in place of [eql]. This bug was discovered during the
plugging of a hole in safe-mode, mentioned just above.
We fixed handling of the :inline keyword for [defstobj], which
previously could cause raw Lisp errors in OpenMCL and CMU Common
Lisp. Thanks to John Matthews for bringing this issue to our
attention.
Calls of [include-book] could result in a state for which some
function definitions were not compiled that should have been. The
result could be performance degradation or even stack overflows.
This situation could arise in the following two ways.
o Inclusion of a book with an absolute pathname that differs from the
absolute pathname at certification time, presumably because of
the use of soft links. Thanks to Bob Boyer and Warren Hunt for
bringing a stack overflow to our attention that led us to this
fix.
o Large [mutual-recursion] nests (more than 20 functions) are
executed in a superior book.
We fixed some performance bugs that can increase the speed of
[include-book] calls by a factor of close to 2. Thanks to Eric
Smith for asking if we could speed up [include-book] processing; we
have done so in the past, but primarily focusing on large
[mutual-recursion] nests (which have nothing in particular to do
with the current improvements). Also, thanks to Rob Sumners for a
very useful remark early in the process that kept us from drawing
an incorrect conclusion at that point.
We fixed :[pl] so that it can be run on a form that returns multiple
values, which it could not do previouslly. Thanks to Eric Smith for
pointing out this problem.
Fixed a bug in the Allegro ACL2 trace utility (see [trace$]) that was
causing ``10>'' to be printed as ``9>'', ``11>'' to be printed as
``10 >'', ``12>'' to be printed as ``11 >'', and so on.
Fixed a [proof-checker] bug that was preventing the use of the DV
command (or a numerical command) on [let] expressions. Thanks to
Bill Young for pointing out this problem.
Fixed a bug in a comment on how to set ACL2_BOOKS_DIR in the
makefile. Thanks to Dave Greve for pointing out this problem.
Fixed a potential soundness bug in the linear arithmetic routines.
Thanks to Jared Davis for noticing this problem and to Robert Krug
for implementing the fix. (Technical details: We had been assuming
that polynomials were being normalized -- see the definition of
good-polyp in linear-a.lisp -- but this assumption was false.)
When the macro [open-trace-file] is opened twice in succession, it
now automatically closes the first trace output channel before
opening another.
It is now possible to use `make' to build ACL2 on Windows systems
that support `make'. Thanks to Pete Manolios and Mike Thomas for
pointing out the problem, to Jared Davis and Mike for helping us to
analyze the problem, and to Jared for testing the fix.
Fixed a bug in the [guard] of [with-output] that was causing a
needless guard violation.
NEW FUNCTIONALITY.
The new events [add-default-hints] and [remove-default-hints] allow
one to append to or subtract from the current list of default
hints. The event [set-default-hints] continues to set the list of
default hints, discarding the previous value of the
[default-hints]. Note that [set-default-hints] is still [local] to
the [encapsulate] or book in which it occurs, and
[add-default-hints] has the same property, although neither is
implemented any longer using the [ACL2-defaults-table]. New events
[add-default-hints!], [remove-default-hints!], and
[set-default-hints!] are the same as [add-default-hints],
[remove-default-hints], and [set-default-hints], respectively,
except that the former three events are not [local] to their
enclosing [encapsulate] or book. Thanks to Jared Davis for
suggesting these enhancements.
OpenMCL's tracing routines have been modified in a similar manner as
those of Allegro CL. Thanks to Robert Krug for providing this
enhancement.
Guard-checking can now be caused to happen on recursive calls. See
``GUARD-RELATED CHANGES'' below for details.
Advanced users can now inhibit compilation of so-called ``*1*
functions'' with the :comp command; see [comp]. Thanks to Rob
Sumners for suggesting this enhancement.
Added new legal argument hard? for the [er] macro, which is now
documented. See [er]. Thanks to Rob Sumners for a discussion
leading to this change. Also, the three legal first arguments to
[er] --- hard, hard?, and soft --- may now be in any package
(thanks to Jared Davis for bringing this issue to our attention).
We have removed the requirement that for a rule's hypothesis
(bind-free term var-list), at least one variable must occur free in
term. For example, the expression (bind-free (bind-divisor a b)
(x)) was legal because a and b occur free in (bind-divisor a b);
but (bind-free (foo (bar)) (x)) was not legal. The latter is no
longer disallowed. (Technical note: this allows [bind-free] to be
used to create explicit substitutions in metafunction hypotheses.)
The following two enhancements have been implemented for rules of
class :[meta]. Thanks to Eric Smith for requesting more control of
reasoning with :[meta] rules, which led to these enhancements, and
to him and Robert Krug for helpful discussions.
o It is now possible to control backchaining in rules of class
:[meta] by providing a :backchain-limit-lst argument, as was
already allowed for rules of class :[rewrite] and :[linear].
See [rule-classes]. However, unlike those other two rule
classes, the value for :backchain-limit-lst is prohibited from
being a non-empty list; it must be either nil or a non-negative
integer.
o (For advanced users.) It is now legal for hypothesis metafunctions
to generate, in essense, calls of [syntaxp] and [bind-free],
handled essentially as they are handled in hypotheses of
:[rewrite] and :[linear] rules. We say ``essentially''
primarily because both [syntaxp] and [bind-free] are actually
macros, but hypothesis metafunctions must generate translated
terms (see [term]). The enterprising advanced user can call
:[trans] to see examples of translated terms corresponding to
calls of [syntaxp] and [bind-free].
A new command :[trans!] has been added, which is like :[trans] except
that :[trans!] ignored issues of single-threadedness. See [trans!].
Thanks to Eric Smith for suggesting this addition.
The :[pf] command now works when the argument is the name of a macro
associated with a function by [macro-aliases-table].
CHANGES IN PROOF ENGINE.
The simplifier has been changed slightly in order to avoid using
[forward-chaining] facts derived from a literal (essentially, a
top-level hypothesis or conclusion) that has been rewritten. As a
practical matter, this may mean that the user should not expect
forward-chaining to take place on a term that can be rewritten for
any reason (generally function expansion or application of rewrite
rules). Formerly, the restriction was less severe: forward-chaining
facts from a hypothesis could be used as long as the hypothesis was
not rewritten to t. Thanks to Art Flatau for providing an example
that led us to make this change; see the comments in source
function rewrite-clause for details.
The rewriter has been modified to work slightly harder in relieving
hypotheses. Thanks to Eric Smith for providing an example that
inspired the following, which illustrates the issue. Suppose we
introduce functions foo and bar with the (non-[local]) properties
shown below.
(encapsulate
(((foo *) => *)
((bar *) => *))
(local (defun foo (x) (declare (ignore x)) t))
(local (defun bar (x) (declare (ignore x)) t))
(defthm foo-holds
(implies x
(equal (foo x) t)))
(defthm bar-holds-propositionally
(iff (bar x) t)))
Consider what happens when ACL2's rewriter is used to prove the
following theorem.
(thm (foo (bar y)))
With ACL2's inside-out rewriting, (bar y) is first considered, but
rewrite rule bar-holds-propositionally does not apply because the
context requires preserving equality, not mere Boolean (iff)
equivalence. Then the rewriter moves its attention outward and sees
the term (foo (bar y)). It attempts to apply the rule foo-holds, in
a context created by binding its variable x to the term (bar y). It
then attempts to relieve the hypothesis x of rule foo-holds in that
context. Before this change, ACL2 basically assumed that since
rewriting was inside out, then (bar y) had already been rewritten
as much as possible, so the rewrite of x in the aforementioned
context (binding x to (bar y)) simply returned (bar y), and the
attempt to relieve the hypothesis of foo-holds failed. The change
is essentially for ACL2's rewriter to make a second pass through
the rewriter when the attempt fails to rewrite a variable to t,
this time using the fact that we are in a Boolean context. (We
mention that source function rewrite-solidify-plus implements this
idea, for those who want to dig deeply into this issue.) In our
example, that means that the rewriter considers (bar y) in a
Boolean context, where it may apply the rule
bar-holds-propositionally to relieve the hypothesis successfully.
When ([set-non-linearp] t) has been executed, [non-linear-arithmetic]
can now be applied in some cases for which it previously was not.
Thanks to Robert Krug for supplying this modification and to Julien
Schmaltz for providing a motivating example.
We modified the rewriter to avoid certain infinite loops caused by an
interaction of the opening of recursive functions with equality
reasoning. (This change is documented in detail in the source code,
in particular functions rewrite-fncall and fnstack-term-member.)
Thanks to Fares Fraij for sending us an example that led us to make
this change.
The :[executable-counterpart] of function [hide] is now disabled when
ACL2 starts up. This removes an anomoly, for example that
(thm (not (equal 1 (* (hide 0) a))))
succeeded while
(thm (equal (foo (equal 1 (* (hide 0) a))) (foo nil)))
failed. Now both fail.
The theory *s-prop-theory* is no longer used by the proof-checker; it
has been replaced by (theory '[minimal-theory]. We have left the
constant *s-prop-theory* defined in the source code in support of
existing books, however. This change eliminates annoying theory
warnings printed upon invocation of [proof-checker] commands
s-prop, sl, and split.
Terms are now kept in an internal form that avoids calls of primitive
functions (built-ins without explicit definitions; see code for
cons-term for details), in favor of the constants that result from
evlaluating those calls. So for example, the internal form for
(cons 1 2) is (quote (1 . 2)). This change was made at around the
same time as changes in support of [bind-free]; see above. One
consequence is that the splitting of goals into cases (technically,
source function clausify and even more technically, source function
call-stack) has been modified, which can cause subgoal numbers to
change.
GUARD-RELATED CHANGES.
Guard-checking can now be caused to happen on recursive calls, where
this was formerly not the case for :[program] mode functions and,
perhaps more important, for :[logic] mode functions whose [guard]s
have not been verified. Moreover, a warning is printed when ACL2
does not rule out the exclusion of guard-checking on recursive
calls. See [set-guard-checking]. Thanks to David Rager for bringing
this issue to our attention, and to Rob Sumners and the Univ. of
Texas ACL2 seminar in general for their feedback.
Guard violations are reported with less of the offending term hidden.
Thanks to Jared Davis for suggesting that we look at this issue.
PROOF-CHECKER CHANGES.
We fixed the [proof-checker] so that diving works as you might expect
for a macro call (op a b c) representing (binary-op a (binary-op b
c)). In the past, if the current term was of the form (append t1 t2
t3), then (DV 3) (and 3) would dive to t3 even though the
corresponding function call is (binary-append t1 (binary-append t2
t3)). This is still the case, but now this behavior holds for any
macro associated with a function in binop-table (see [add-binop]).
Moreover, users can now write customized diving functions; see
[dive-into-macros-table], and also see
books/misc/rtl-untranslate.lisp for example calls to
[add-dive-into-macro]. Of course, the old behavior can still be
obtained using the [proof-checker]'s DIVE command; see
[proof-checker-commands].
The runes command in the [proof-checker] now shows only the [rune]s
used by the most recent primitive or macro command (as shown by
:comm), unless it is given a non-nil argument. Also,
[proof-checker] command lemmas-used has been added as, in essence,
an alias for runes.
(The following two items are also mentioned above under ``BUG
FIXES.'')
Fixed a [proof-checker] bug that was preventing the use of the DV
command (or a numerical command) on [let] expressions. Thanks to
Bill Young for pointing out this problem.
The theory *s-prop-theory* is no longer used by the proof-checker; it
has been replaced by (theory '[minimal-theory]. We have left the
constant *s-prop-theory* defined in the source code in support of
existing books, however. This change eliminates annoying theory
warnings printed upon invocation of [proof-checker] commands
s-prop, sl, and split.
SYSTEM-LEVEL CHANGES.
Fixed a problem with building ACL2 on CMUCL in some systems (source
function save-acl2-in-cmulisp). Thanks to Bill Pase for bringing
this to our attention.
The installation instructions have been extended to include
instructions for building on GCL in Mac OS X. Thanks to Jun Sawada
and Camm Maguire.
Initial pre-allocation of space has been updated for GCL to reflect
more current GCL executables (we considered GCL 2.6.1-38). This can
help avoid running out of memory for large ACL2 sessions.
The main Makefile has been replaced by GNUmakefile, in order to
enforce the use of GNU `make'. If you use another `make' program,
you'll get an error message that may help you proceed.
(GCL only) SGC is no longer turned on for GCL 2.6 sub-versions
through 2.6.3 if si::*optimize-maximum-pages* is bound to T, due to
an apparent issue with their interaction in those sub-versions.
Also, we have eliminated preallocation for all versions after 2.6.1
because GCL doesn't need it (comments are in source function
save-acl2-in-akcl). Thanks to Camm Maguire for excellent GCL help
and guidance, and to Camm and Bob Boyer for useful discussions.
We have removed support for so-called ``small'' images. Thus, :[doc],
:[pe] and :[pc], [verify-termination], and other commands are fully
supported in ACL2 saved images. Because of this and other changes
in the generation of the so-called ``*1*'' logical functions,
related to guards (as described above in -GUARD-RELATED CHANGES'',
and related to the discussion of safe-mode in ``BUG FIXES'' above),
image sizes have increased substantially.
We no longer time or run ``nice'' the certification of individual
books. The file books/Makefile-generic had done these by default,
and some individual distributed and workshop book directories had
Makefiles that did so as well. Thanks to Mike Thomas, who pointed
out the lack of nice on some Windows systems (and we decided on
this simple solution). Overall targets in books/Makefile still time
their runs by default, and the partiular time program is now
controlled by a Makefile variable.
Failures during make certify-books or make regression now show up in
the log as ``**CERTIFICATION FAILED**'', regardless of the
operating system (as long as it supports `make'). Formerly, one
searched for ``**'' but this did not appear in openMCL runs.
We have eliminated ``Undefined function'' warnings that could occur
in OpenMCL.
BOOK CHANGES.
Reconciled the definitions of firstn in book/misc/csort.lisp,
books/bdd/bdd-primitives.lisp,
books/ordinals/ordinal-definitions.lisp, and
books/data-structures/list-defuns.lisp. Thanks to Ray Richards for
bringing this issue to our attention.
Distributed book books/misc/defpun now can handle [stobj]s where it
did not previously. Thanks to John Matthews for bringing this issue
to our attention.
The \"make\" variable COMPILE_FLG in file books/Makefile-generic
formerly only had an effect if there was a cert.acl2 file present.
That oversight has been remedied.
File \"books/arithmetic/certify.lsp\" was missing a [certify-book]
command for \"natp-posp\". Thanks to John Cowles for noticing this
deficiency and supplying a fix. (This file is of use to those who
want to certify the \"books/arithmetic/\" books without using
\"make\".)
A few small changes have been made to \"books/rtl/rel4\".
Small changes were made to books misc/symbol-btree and
misc/rtl-untranslate. In particular, the definition of
symbol-btreep was strengthened.
We made a minor fix to books/ordinals/e0-ordinal.lisp, adding
(verify-guards ob+) and hence (verify-guards ocmp) as well. This
was necessitated by the fix prohibiting functions with guards
verified from calling functions with guards not verified (see also
the related discussion under ``BUG FIXES'' above).
MISCELLANEOUS CHANGES.
Further sped up processing of large [mutual-recursion] nests
(extending what was done for Version_2.7), perhaps by a factor of
two in some cases.
As promised in Version_2.5 (see [note-2-5]), structured pathnames are
no longer supported. So for example, the argument to [include-book]
must now be a string constant.
Some documentation has been improved, for [stobj]s thanks to
suggestions by John Matthews and much of the rest thanks to
feedback from Eric Smith.
The function [current-package] is now available to users (it has been
taken off the list of so-called ``untouchables''). Thanks to Jared
Davis for bringing this issue to our attention.
The documentation for topic [using-computed-hints-7] has been
improved. Thanks to Doug Harper and Eric Smith for inspiring this
improvement.
We added several symbols to *acl2-exports*: [cw], [er], [intern$],
[set-case-split-limitations], and [set-difference-eq]. Thanks to
Jared Davis for suggesting most of these.
Now, a [table] event that sets the value for a key, (table tbl key
val :put), is redundant (see [redundant-events]) when it does not
change the value associated with an existing key of the table. In
particular, [define-pc-macro] is now fully redundant when it does
not change an existing [proof-checker] macro-command definition.
Thanks to Bill Young for bringing the latter issue to our
attention.
The definitions of unused system functions ev-w and ev-w-lst have
been deleted.
ACL2 now prints a warning if a [defpkg] event introduces a package
name with lower-case letters, since there is opportunity for later
confusion in that case. Thanks to Frederic Peschanski for bringing
this problem to our attention and Sandip Ray for encouragement.
ACL2 now works in Version 19 of CMU Common Lisp.
The function [sys-call] has been modified so that for ACL2 built on
Allegro Common Lisp in Unix or Linux, the existing environment is
used. Thanks to Erik Reeber for bringing this issue to our
attention.
The function [disabledp] can now be given a macro name that has a
corresponding function; see [macro-aliases-table]. Also,
[disabledp] now has a [guard] of t but causes a hard error on an
inappropriate argument.")
(NOTE-2-9-1
(RELEASE-NOTES)
"ACL2 Version 2.9.1 (December, 2004) Notes
(GCL only) A bug in [symbol-package-name] has been fixed that could
be exploited to prove nil, and hence is a soundness bug. Thanks to
Dave Greve for sending us an example of a problem with [defcong]
(see below) that led us to this discovery.
ACL2 now warns when [defcong] specifies [equal] as the first
equivalence relation, e.g., (defcong equal iff (member x y) 2). The
warning says that the rule has no effect because [equal] already
refines all other equivalence relations. Formerly, this caused an
error unless :event-name was supplied (see [defcong]), and in fact
the error was a nasty raw Lisp error on GCL platforms due to some
mishandling of packages by ACL2 that has been fixed (see the
paragraph about [symbol-package-name] above). Thanks to Dave Greve
for sending a helpful example in his report of this problem.
(GCL only) The build process was broken for GCL 2.6.0 (and perhaps
some earlier versions), and has been fixed. Thanks to Jose Luis
Ruiz-Reyna for bringing this problem to our attention.
(GCL only) We have increased the hole size to at least 20% of
max-pages, which may eliminate some garbage collection at the
expense of larger virtual memory (not larger resident memory or
larger image). Thanks to Camm Maguire for helpful explanations on
this topic.
We have clarified the [guard] warning message that is printed during
evaluation of recursively-defined functions whose [guard]s have not
been verified, for example:
ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking may be inhibited
on some recursive calls of executable counterparts (i.e., in the ACL2
logic), including perhaps EVENLP. To check guards on all recursive
calls:
(set-guard-checking :all)
To leave behavior unchanged except for inhibiting this message:
(set-guard-checking :nowarn)
And, ACL2 no longer prints that message when the [guard] was
unspecified for the function or was specified as T. Thanks to
Serita Nelesen for bringing the latter issue to our attention.
Finally, ACL2 now prints such a warning at most once during the
evaluation of any top-level form; thanks to Bill Young for pointing
out this issue.
The function [verbose-pstack] has been enhanced to allow specified
prover functions not to be traced. See [verbose-pstack].
Added [lp], wet, and [set-non-linearp] to *acl2-exports*, and hence
to the \"[ACL2-user]\" package.
The distributed book books/arithmetic-3/bind-free/integerp.lisp has
been modified in order to prevent potential looping; specifically,
the definition of function reduce-integerp-+-fn-1. Thanks to Robert
Krug for providing this change.
A small improvement was made in the wet failure message when the
error occurs during translation to internal form. Thanks to Jared
Davis for pointing out the obscurity of some wet error messages.
We have improved ACL2's evaluation mechanism for the function
bad-atom<=, which now is specified to return nil if neither
argument is a so-called ``bad atom'' (as recognized by function
bad-atom). The following events had caused a hard error, for
example. (We're sorry that bad-atom and bad-atom<= are not
documented, but we also consider it unlikely that anyone needs such
documentation; otherwise, please contact the implementors.)
(defun foo (x y) (declare (xargs :guard t)) (bad-atom<= x y))
(defun bar (x y) (declare (xargs :guard t)) (foo x y))
(thm (equal (bar 3 4) 7))
We have also changed the guard on [alphorder] to require both
arguments to be atoms.
For forms (local x) that are skipped during [include-book], or during
the second pass of [certify-book] or [encapsulate], ACL2 had
nevertheless checked that x is a legal event form. This is no
longer the case.
The [proof-checker] now does non-linear arithmetic when appropriate.
It had formerly ignored [set-non-linearp] executed in the ACL2
command loop.
Incremental releases are now supported. See [version] and {obsolete
after Version 4.3} set-tainted-okp. Thanks to Hanbing Liu for
discovering a flaw in our original design.
The pattern-matching algorithm for :[rewrite] rules has been made
slightly more restrictive, thanks to a suggestion and examples from
Robert Krug. For example, previously one could get an infinite loop
as follows.
(defstub foo (x) t)
(defaxiom foo-axiom
(equal (foo (+ 1 x))
(foo x)))
(thm (foo 0)) ; or replace 0 by any integer!
That is because the term (foo 0) was considered to match against the
pattern (foo (+ 1 x)), with x bound to -1. While such matching is
sound, it leads to an infinite loop since it allows foo-axiom to
rewrite (foo 0) to (foo -1), and then (foo -1) to (foo -2), and so
on. The fix is to insist that the new value, in this case -1, is no
larger in size according to [ACL2-count] than the old value, in
this case 0. Since that test fails, the match is considered to fail
and the loop no longer occurs. An analogous fix has been made for
multiplication, where now we only match when the new term is still
a non-zero integer. That change avoids a loop here.
(defstub foo (x) t)
(defaxiom foo-axiom
(equal (foo (* 2 x))
(foo x)))
(thm (foo 0)) ; or try (thm (foo 4))
Added macro find-lemmas in books/misc/find-lemmas.lisp (see brief
documentation there) for finding all lemmas that mention all
function symbols in a given list.
:Restrict [hints] now work for :[definition] rules, though they
continue to be ignored by the preprocessor and hence you may want
to use :do-not '(preprocess) with any restrict hints. Thanks to
John Matthews for pointing out the lack of support for :definition
rules in :restrict hints.
Some books have been updated. In particular, there is a new directory
books/workshops/2004/ in workshops distribution, for the 2004 ACL2
workshop. There is also a new version of Jared Davis's ordered sets
library, formerly in books/finite-set-theory/osets-0.81/ but now in
books/finite-set-theory/osets/.
Fixed a bug in the (under-the-hood) raw Lisp definition of
[defchoose], which had been causing a warning in CMU Common Lisp.
[Technical improvements related to the use of ``make dependencies''
for certifying distributed books:]
File books/Makefile-generic now does a better job with ``make
dependencies,'' specifically with respect to handling *.acl2 files
and handling [include-book] commands with :dir :system. Regarding
the latter, suppose for example that book basic.lisp contains the
line:
(include-book \"arithmetic/top-with-meta\" :dir :system)
Then make dependencies would generate the following line:
basic.cert: $(ACL2_SRC_BOOKS)/arithmetic/top-with-meta.cert
Thus, if :dir :system is used with [include-book], the corresponding
Makefile should define the variable ACL2_SRC_BOOKS. A standard
Makefile header for a books directory could thus be as follows.
# The following variable should represent the ACL2 source directory. It is the
# only variable in this Makefile that may need to be edited.
ACL2_SRC = ../../../../../..
ACL2_SRC_BOOKS = $(ACL2_SRC)/books
include $(ACL2_SRC_BOOKS)/Makefile-generic
ACL2 = $(ACL2_SRC)/saved_acl2h
Finally, the ``-s'' flag may now be omitted when running ``make
dependencies.''")
(NOTE-2-9-2
(RELEASE-NOTES)
"ACL2 Version 2.9.2 (April, 2005) Notes
Also see [note-2-9-1] for other changes since the last
non-incremental release (Version_2.9).
There was a bug in non-linear arithmetic (see
[non-linear-arithmetic]) that caused the following error:
ACL2 !>(include-book \"rtl/rel4/lib/top\" :dir :system)
....
ACL2 !>(set-non-linearp t)
T
ACL2 !>(thm
(implies (and (bvecp a 77)
(bvecp b 50))
(bvecp (fl (/ (* a b) (expt 2 23)))
104))
:hints ((\"Goal\" :in-theory (enable bvecp))))
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
By the simple :definition BVECP, the :executable-counterparts of EXPT
and UNARY-/ and the simple :rewrite rule ASSOCIATIVITY-OF-* we reduce
the conjecture to
Goal'
(IMPLIES (AND (INTEGERP A)
(<= 0 A)
(< A 151115727451828646838272)
(INTEGERP B)
(<= 0 B)
(< B 1125899906842624))
(BVECP (FL (* A B 1/8388608)) 104)).
HARD ACL2 ERROR in VARIFY: This should not have happened. The supposed
variable, '1/8388608, is instead a constant.
ACL2 !>
Thanks to Robert Krug for providing a fix for the above error.
Guard-checking was being inhibited (since v2-9) for calls of built-in
primitives on explicit values, e.g., (car 3). This has been fixed.
Guard-related warnings could be printed during proofs (this bug was
introduced in Version_2.9.1). These warnings have been eliminated.
Compound-recognizer rules natp-compound-recognizer and
posp-compound-recognizer are now built into ACL2 for predicates
[natp] and [posp], and hence have been deleted from book
natp-posp.lisp (where they were called natp-cr and posp-cr,
respectively).
The function file-clock-p, which recognizes a component of the ACL2
[state], is now defined using [natp] instead of [integerp]. Thanks
to Jared Davis for suggesting this change. (Technical explanation
about functions in ACL2 source file axioms.lisp: With a file-clock
of -1, the call of make-input-channel in open-input-channel will
create a channel that can't be closed; see the guard of
close-input-channel.)
(Allegro CL users only) Support is now provided for building an
Allegro CL application, provided you have an Allegro CL dynamic
runtime license. (Our belief is that with such a license, many
users can use the same application, rather than each user needing a
separate license.) See new GNUmakefile target allegro-app and file
build-allegro-exe.cl for more information.
The new home page now contains a link to a new page
other-releases.html, which contains information about other ACL2
releases. (This is in one's local home page, but may not show up on
the central ACL2 home page until the next non-incremental release.)
Thanks to Warren Hunt for suggesting this addition.
We thank Erik Reeber for suggesting a solution to output redirection
using [sys-call], which we have described at the end of its
documentation.
A new documentation topic fixes the flawed argument for
conservativity of the [defchoose] event that appears in Appendix B
of Kaufmann and Moore's paper, ``Structured Theory Development for
a Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2
(2001), pp. 161-203). See [conservativity-of-defchoose]. Thanks to
John Cowles and Ruben Gamboa for helpful feedback on drafts of this
note.
The solution to exercise 6.15 in books/textbook/chap6/solutions.txt
has been fixed. Thanks to Aaron Smith for pointing out the problem.
A new documentation topic [defun-sk-example] gives a little more help
in using [defun-sk] effectively. Thanks to Julien Schmaltz for
presenting this example as a challenge.
(GCL only) There is now a way to speed up GCL builds of ACL2, at the
cost of perhaps a percent or so in performance of the resulting
image. Using `make' one supplies the following.
LISP='gcl -eval \"(defparameter user::*fast-acl2-gcl-build* t)\"
Various makefiles have been improved in several ways.
(1) Parallel book certification, using GNU make's -j option, can be
used.
(2) Book certifications now stops at the first failure if
books/Makefile or books/Makefile-generic is used, and returns
non-zero exit status. However, the various make targets in the
ACL2 source directory (regression, certify-books, etc.) still
continue past failures unless you provide ACL2_IGNORE=' ' on
the `make' command line.
(3) The build process has been modified (file GNUmakefile) so that it
stops upon a failed compile or a failed initialization.
(4) The automatic dependency generation (from ``make dependencies''
has been improved so that commands of the form (ld
\"my-book.lisp\") in .acl2 files cause the appropriate
depedencies to be generated.
Thanks to comments from several users that led to the above Makefile
improvements: Ray Richards, Doug Harper, and the Rockwell ACL2
users for (1) and (2) (and inspiring (4)), and David Rager for (2)
and (3). In particular, Doug Harper sent a replacement for the
.date mechanism, which was interfering with make -n; so, these
files are no longer written.
A mechanism has been added for saving output. In particular, you can
now call [ld] on a file with output turned off, for efficiency, and
yet when a proof fails you can then display the proof attempt for
the failed (last) event. See [set-saved-output]. Another new
command --- see [set-print-clause-ids] --- causes subgoal numbers
to be printed during proof attempts when output is inhibited.
Documentation has been added for using ACL2's makefile support to
automate the certification of collections of books. See
[books-certification-classic].
Fixed a bug in [sys-call-status] that was causing hard Lisp errors.
Improved [cw-gstack] to allow a :frames argument to specify a range
of one or more frames to be printed. see [cw-gstack].
Fixed a bug in [proof-checker] command forwardchain. Thanks to
Ming-Hsiu Wang for bringing this bug to our attention.
We have provided a mechanism for saving an executable image. See
[saving-and-restoring] and see [save-exec]. We have eliminated
obsolete functions note-lib and make-lib.
Modified the [ground-zero] [theory] so that it contains all of the
built-in rules (in ACL2 source file axioms.lisp). It had formerly
failed to include rules from some definitions and theorems near the
end of axioms.lisp.
A new event, [set-enforce-redundancy], allows the enforcement of
[defthm], [defun], and most other events during book development.
See [set-enforce-redundancy].
A bug has been fixed that had allowed [deftheory] [events] to cause a
hard Lisp error when calling [union-theories] on ill-formed
theories after, for example:
:set-guard-checking nil
(in-theory (union-theories '((:rewrite no-such-rule))
(current-theory 'ground-zero)))
The handling of [guard] checking has been modified somewhat in a way
that should only very rarely affect users. (An ``Essay on Guard
Checking'' in the ACL2 source code explains this point to anyone
interested in implementation details.)
(GCL ONLY) Removed the -dir setting in the ACL2 wrapper script for
GCL. This should generally have no effect for most users, but it
eliminates a potential source of error down the road.
Several interesting new definitions and lemmas have been added to the
rtl library developed at AMD, and incorporated into
books/rtl/rel4/lib/. Other book changes include a change to lemma
truncate-rem-elim in books/ihs/quotient-remainder-lemmas.lisp, as
suggested by Jared Davis.
The macro [real/rationalp] may now be referred to in [in-theory]
[events] and [hints], thanks to a new [add-macro-alias] event.
Thanks to Jared Davis for this suggestion.
ACL2 terms of the form (if p 'nil 't) are now printed as (not p),
where in some setting they had been printed as (and (not p) t).
Thanks to Robert Krug for this improvement.
(GCL ONLY) Added profiling support, based heavily on code supplied by
Camm Maguire. See file save-gprof.lsp for instructions. Thanks to
Camm, and also to David Hardin for inspiring this addition.
Added support for preprocessing before printing (untranslating) a
term. See [user-defined-functions-table], in particular the
discussion of untranslate-preprocess. Thanks to Jared Davis for
inspiring this addition, and for providing a book that takes
advantage of it (books/misc/untranslate-patterns.lisp).
The documentation has been improved for explaining how [rune]s are
assigned; see [rune]. Thanks to Robert Krug for pointing out
inaccuracies in the existing documentation.")
(NOTE-2-9-3
(RELEASE-NOTES)
"ACL2 Version 2.9.3 (August, 2005) Notes
Also see [note-2-9-1] and see [note-2-9-2] for other changes since
the last non-incremental release (Version_2.9).
We fixed a soundness bug that exploited the ability to define
:[program] mode functions that are improperly guarded, and then to
use those functions in [defconst] forms. The fix is to evaluate
[defconst] forms using the same ``safe-mode'' that is used in
macroexpansion (see [guards-and-evaluation]). Here is a proof of
nil that succeeded in Allegro Common Lisp (but not, for example,
GCL). See also a long comment in source function defconst-fn for an
example that does not require the use of :set-guard-checking.
:set-guard-checking nil ; execute before certifying the book below
(in-package \"ACL2\")
(encapsulate
()
(local (defun f1 ()
(declare (xargs :mode :program))
(char-upcase (code-char 224))))
(local (defconst *b* (f1)))
(defun f1 ()
(char-upcase (code-char 224)))
(defconst *b* (f1))
(defthm bad
(not (equal *b* (code-char 224)))
:rule-classes nil))
(defthm ouch
nil
:hints ((\"Goal\" :use bad))
:rule-classes nil)
We fixed a soundness hole due to the fact that the \"LISP\" package
does not exist in OpenMCL. We now explicitly disallow this package
name as an argument to [defpkg]. Thanks to Bob Boyer and Warren
Hunt for bringing an issue to our attention that led to this fix.
ACL2 now requires all package names to consist of standard characters
(see [standard-char-p], none of which is lower case. The reason is
that we have seen at least one lisp implementation that does not
handle lower case package names correctly. Consider for example the
following raw lisp log (some newlines omitted).
>(make-package \"foo\")
#<\"foo\" package>
>(package-name (symbol-package 'FOO::A))
\"foo\"
>(package-name (symbol-package '|FOO|::A))
\"foo\"
>
Distributed book books/textbook/chap10/compiler, as well as workshop
books in directory books/workshops/2004/cowles-gamboa/support/,
were modified to accommodate the above change.
Added newline, [add-to-set-eql], the-fixnum, and the-fixnum! to
*acl2-exports*. Thanks to Jared Davis for bringing these to our
attention.
Added a line to acl2.lisp to support CMUCL running on Mac OSX, thanks
to a suggestion from Fabricio Chalub Barbosa do Rosario.
The executable scripts for saved ACL2 images now include $*, so that
command-line arguments will be passed along.
(For GCL profiling only) Fixed a colon (:) that should have been a
semicolon (;) in file save-gprof.lsp. Thanks to David Hardin for
pointing out this bug.
The documentation for :[elim] rules has been expanded and improved,
thanks to useful feedback from Hanbing Liu.
Fixed a bug in the guard for function include-book-dir.
For those who want to experiment with an alternate implementation of
[mv] and [mv-let], there is now support for under-the-hood
implementation of these in terms of raw Lisp functions values and
multiple-value-bind, respectively. The regression suite has seen
about a 10% speed-up in Allegro CL and about an 8% slowdown in GCL
for builds with this change. See the makefile (GNUmakefile) for
examples of how to build ACL2 by including the feature,
:acl2-mv-as-values. Source file init.lsp has been renamed to
init.lisp in support of this change (technical detail: otherwise
GCL loads the init file too soon, before its -eval argument is
evaluated). Thanks to David Rager for inspiring this change, by
pointing out the problematic use of globals by the existing [mv]
implementation from the standpoint of supporting parallel
evaluation. This capability is experimental: there is likely to be
some remaining work to be done on it.
A change related to the one just above is that we now limit the
maximum number of arguments to any call of [mv] to 32. Thanks to
Bob Boyer for raising a question that lead to this change.
Eliminated some compiler warnings in OpenMCL.
In the rtl library (books/rtl/rel4/), functions bits and setbits have
had their [guard]s improved (as they had been too restrictive,
especially for setbits).
A new function [time$] permits timing of forms, by using (under the
hood) the host Common Lisp's time utility.
We fixed an infinite loop that could occur during destructor
elimination (see [elim]). Thanks to Sol Swords to bringing this to
our attention and sending a nice example, and to Doug Harper for
sending a second example that we also found useful.
The method of speeding up GCL-based builds (see [note-2-9-2]) has
changed slightly from Version_2.9.2. Now, in the `make' command:
LISP='gcl -eval \"(defparameter user::*fast-acl2-gcl-build* t)\"
We improved the pretty-printer's handling of keywords. For example,
before this change one might see the following printed by ACL2.
(MODIFY TH S :KEY1 VAL1 :KEY2
(IF (IF X Y Z) AAAAAAAAAA BBBBBBB))
Now, the above might print as follows. Notice that we have avoided
breaking after a keyword (see [keywordp]) that is preceded by other
forms on the same line.
(MODIFY TH S
:KEY1 VAL1
:KEY2 (IF (IF X Y Z) AAAAAAAAAA BBBBBBB))
See [note-2-9-3-ppr-change] for a detailed discussion of this change.
(GCL ONLY) Evaluation in a break is no longer inhibited by ACL2 when
built on top of GCL, so GCL now matches other Common Lisps in this
respect.
For ACL2 built on most host Common Lisps, you will see the string
[RAW LISP] in the prompt, at least at a break, to emphasize that
one is inside a break and hence should probably quit from the
break. See [breaks].
Jared Davis suggested improvements to lemmas len-update-nth (in
source file axioms.lisp) and append-true-listp-type-prescription
(in books/meta/term-defuns.lisp), which have been incorporated. The
former required a change in books/workshops book
2004/ruiz-et-al/support/q-dag-unification.cert, which has been
made.
The [proof-checker] command rewrite allows further binding of free
variables in hypotheses, with new optional argument
instantiate-free. Proof-checker command show-rewrites (sr) gives
corresponding additional information. Documentation for these
commands has been improved; see [proof-checker-commands]. Thanks to
John Matthews and Bill Young for suggestions and feedback leading
to these improvements.
Fixed downcase printing so that the package name of a symbol is also
downcased. For example, after execution of (defpkg \"FOO\" nil) and
(set-acl2-print-case :downcase), 'foo::ab will print back as the
same, rather than as 'FOO::ab.
It is now possible to control the output so that numbers are printed
in binary, octal, or hex, though the default is still radix 10. See
[set-print-base]. Note that in support of this change, built-in
functions [explode-nonnegative-integer] and explode-atom now take
an extra print-base argument. Different support for radix
conversion may be found in a book newly contributed by Jun Sawada,
books/misc/radix.lisp.
Built-in axiom car-cdr-elim is now only an :[elim] rule. It was
formerly both an :elim rule and a :[rewrite] rule. A new rule,
cons-car-cdr, takes the place of the old :rewrite rule, but is
instead a hypothesis-free rule that can cause a case split (see
source file axioms.lisp). Thanks to Jared Davis for suggesting this
change.
Lemmas about [alphorder] (alphorder-reflexive, alphorder-transitive,
alphorder-anti-symmetric, and alphorder-total) are now available.
(They had been [local] in source file axioms.lisp.) Thanks to
Serita Nelesen for bringing this issue to our attention.
ACL2 has, for some time, printed a space in the event summary after
the open parenthesis for a [defthm] event, in order to ease
backward searching for the original form, for example (defthm bar
...):
Form: ( DEFTHM BAR ...)
The intention was that this extra space should be printed for every
event form; but it was missing in some cases, for example, for
[verify-guards]. This has been fixed.
In analogy to [include-book], now [ld] takes the (optional) keyword
argument :dir. Thanks to Jared Davis for providing an
implementation of this feature and to Eric Smith and Jeff Marshall
for requesting this feature.
We fixed a bug in [include-book] that could cause an error when
redefinition is on, for example:
(set-ld-redefinition-action '(:warn! . :overwrite) state)
(include-book \"/u/acl2/books/arithmetic/top\")
The behavior of [include-book] now matches the documentation:
handling of compiled files for uncertified [books] will follow the
same rules as for certified books. In particular, if you create an
object file in raw Lisp for some book, then including that book
will load that object file. Thanks to Jared Davis for bringing this
issue to our attention.
New documentation explains the interaction of redefinition and
redundancy. See [redundant-events] --- the ``Note About Unfortunate
Redundancies'' is new. Thanks to Grant Passmore for providing
examples that led us to write this additional documentation.
Solutions to exercises in { How To Prove Theorems Formally |
http://www.cs.utexas.edu/users/moore/publications/how-to-prove-thms}
are now available in distributed book
books/misc/how-to-prove-thms.lisp. Also in that directory may be
found a new book hanoi.lisp that contains a solution to the Towers
of Hanoi problem.
Subtopics
[Note-2-9-3-ppr-change]
Change in pretty-printing for ACL2 Version_2.9.3")
(NOTE-2-9-3-PPR-CHANGE
(NOTE-2-9-3)
"Change in pretty-printing for ACL2 Version_2.9.3
We have improved pretty-printing in ACL2 Version_2.9.3 to handle
keywords a little differently. To see a discussion of the basics of
this change, see [note-2-9-3]. In this note we describe it in
considerable detail.
Those who wish to understand the ACL2 pretty-printer's implementation
can now find considerably more comments on it in the source code.
In this note, we do not focus on the implementation. Rather, we
motivate the change and show how the improved prettyprinter
performs.
Why do we want better keyword handling? Imagine a macro that builds a
new state from an old state by changing the values in the affected
fields, leaving everything else unchanged. One could write
(modify th s :key1 val1 :key2 val2 :key3 val3)
where the three keys identify fields in the state.
To make it easier to read new concrete states, we may have a function
that prints them ``relative'' to a given base state, expressing the
new state as a modification of the given base state. So we may find
ourselves prettyprinting modify forms like that above.
The previous prettyprinter will sometimes print the form above as
follows.
(modify th s :key1
val1
:key2 val2 :key3 val3)
This can be unpleasant to read, because of the way :key1 and val1 are
separated. Here is an example of the old prettyprinter and the new
one, both printing an expression from the ACL2 source code in a
width of 40:
Old:
(ADD-TO-TAG-TREE
'ASSUMPTION
(MAKE
ASSUMPTION :TYPE-ALIST TYPE-ALIST
:TERM TERM :REWRITTENP REWRITTENP
:IMMEDIATEP IMMEDIATEP :ASSUMNOTES
(LIST
(MAKE
ASSUMNOTE :CL-ID
NIL :RUNE RUNE :TARGET TARGET)))
TTREE)
New:
(ADD-TO-TAG-TREE
'ASSUMPTION
(MAKE ASSUMPTION
:TYPE-ALIST TYPE-ALIST
:TERM TERM
:REWRITTENP REWRITTENP
:IMMEDIATEP IMMEDIATEP
:ASSUMNOTES
(LIST (MAKE ASSUMNOTE
:CL-ID NIL
:RUNE RUNE
:TARGET TARGET)))
TTREE)
Basically the change we made forces the prettyprinter to print each
:key on a new line unless they all fit on a single line. So we
would now get either
(modify th s :key1 val1 :key2 :val2 :key3 val3)
or
(modify th s
:key1 val1
:key2 val2
:key3 val3)
Furthermore, we fixed it so that if val1 (say) is a big s-expression
we may still print it on the same line as its key. The old
prettyprinter enforced the rule that if you wanted to print (foo a
b) and b gets broken up into several lines, then it has to start on
a new line. Thus, we'd never print
(foo a (bbb
(mum x)))
but would print instead
(foo a
(bbb
(mum x)))
Now, if a is a keyword, we can print the first way.
So here are some nice examples of prettyprinted keyword forms. All of
these are printed for a page of width 40.
<-- 40 chars ->
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(MODIFY TH S :KEY1 V1 :KEY2 V2)
(MODIFY TH S :KEY1 V1 :KEY2 V2 :KEY3 V3)
(MODIFY TH S1 ; Because of the extra char
:KEY1 V1 ; in S1 the flat size exceeds
:KEY2 V2 ; 40 and we break it.
:KEY3 V3)
The old ppr would have printed this as:
(MODIFY
TH S1 :KEY1 V1 :KEY2 V2 :KEY3 V3)
Returning to new examples:
<-- 40 chars ->
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(MODIFY TH S
:KEY1 (IF (IF X Y Z) AAAA BBBB)
:KEY2 VAL2
:KEY3 VAL3)
Now we extend AAAA and BBBB by one char each, so it would overflow
the right margin if printed as above, and we get:
<-- 40 chars ->
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(MODIFY
TH S
:KEY1 (IF (IF X Y Z) AAAAX BBBBX)
:KEY2 VAL2
:KEY3 VAL3)
If we make these names even longer we force the value off the line
containing :key1:
(MODIFY
TH S
:KEY1
(IF (IF X Y Z) AAAAXXXXX BBBBXXXXX)
:KEY2 VAL2
:KEY3 VAL3)
Here are some examples from the ACL2 source code, printed in 40
characters:
(DEFTHM
ALPHORDER-ANTI-SYMMETRIC
(IMPLIES (AND (NOT (CONSP X))
(NOT (CONSP Y))
(ALPHORDER X Y)
(ALPHORDER Y X))
(EQUAL X Y))
:HINTS
((\"Goal\"
:IN-THEORY
(UNION-THEORIES
'(STRING< SYMBOL-<)
(DISABLE
CODE-CHAR-CHAR-CODE-IS-IDENTITY))
:USE
((:INSTANCE SYMBOL-EQUALITY (S1 X)
(S2 Y))
(:INSTANCE BAD-ATOM<=-ANTISYMMETRIC)
(:INSTANCE
CODE-CHAR-CHAR-CODE-IS-IDENTITY
(C Y))
(:INSTANCE
CODE-CHAR-CHAR-CODE-IS-IDENTITY
(C X)))))
:RULE-CLASSES
((:FORWARD-CHAINING
:COROLLARY
(IMPLIES
(AND (ALPHORDER X Y)
(NOT (CONSP X))
(NOT (CONSP Y)))
(IFF (ALPHORDER Y X) (EQUAL X Y)))
:HINTS
((\"Goal\"
:IN-THEORY (DISABLE ALPHORDER))))))
Here is that same one, printed in a width of 60.
(DEFTHM
ALPHORDER-ANTI-SYMMETRIC
(IMPLIES (AND (NOT (CONSP X))
(NOT (CONSP Y))
(ALPHORDER X Y)
(ALPHORDER Y X))
(EQUAL X Y))
:HINTS
((\"Goal\"
:IN-THEORY
(UNION-THEORIES
'(STRING< SYMBOL-<)
(DISABLE CODE-CHAR-CHAR-CODE-IS-IDENTITY))
:USE ((:INSTANCE SYMBOL-EQUALITY (S1 X)
(S2 Y))
(:INSTANCE BAD-ATOM<=-ANTISYMMETRIC)
(:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C Y))
(:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY
(C X)))))
:RULE-CLASSES
((:FORWARD-CHAINING
:COROLLARY (IMPLIES (AND (ALPHORDER X Y)
(NOT (CONSP X))
(NOT (CONSP Y)))
(IFF (ALPHORDER Y X) (EQUAL X Y)))
:HINTS ((\"Goal\" :IN-THEORY (DISABLE ALPHORDER))))))
Just for comparison, here is the above printed in 60 columns by the
old prettyprinter.
(DEFTHM
ALPHORDER-ANTI-SYMMETRIC
(IMPLIES (AND (NOT (CONSP X))
(NOT (CONSP Y))
(ALPHORDER X Y)
(ALPHORDER Y X))
(EQUAL X Y))
:HINTS
((\"Goal\" :IN-THEORY
(UNION-THEORIES
'(STRING< SYMBOL-<)
(DISABLE CODE-CHAR-CHAR-CODE-IS-IDENTITY))
:USE
((:INSTANCE SYMBOL-EQUALITY (S1 X)
(S2 Y))
(:INSTANCE BAD-ATOM<=-ANTISYMMETRIC)
(:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C Y))
(:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY
(C X)))))
:RULE-CLASSES
((:FORWARD-CHAINING
:COROLLARY
(IMPLIES (AND (ALPHORDER X Y)
(NOT (CONSP X))
(NOT (CONSP Y)))
(IFF (ALPHORDER Y X) (EQUAL X Y)))
:HINTS
((\"Goal\" :IN-THEORY (DISABLE ALPHORDER))))))
Of course, given that you cannot tell for sure whether the keywords
you're seeing are part of a keyword/value parameter list or part of
some constant containing random keywords, the prettyprinter can't
solve the problem perfectly. We just tried to make it work nicely
on well-formed keyword/value parameter lists.
For example, here is a form printed by the each prettyprinter.
Old:
(MEMBER
X
'(:MONDAY
:MON :TUESDAY :TUES :WEDNESDAY
:WED :THURSDAY :THURS :FRIDAY
:FRI :SATURDAY :SAT :SUNDAY :SUN))
New:
(MEMBER X
'(:MONDAY :MON
:TUESDAY :TUES
:WEDNESDAY :WED
:THURSDAY :THURS
:FRIDAY :FRI
:SATURDAY :SAT
:SUNDAY :SUN))
The new way is not how one would print it by hand! But then, neither
is the old way.")
(NOTE-2-9-4
(RELEASE-NOTES)
"ACL2 Version 2.9.4 (February, 2006) Notes
Also see [note-2-9-1], see [note-2-9-2], and see [note-2-9-3] for
other changes since the last non-incremental release (Version_2.9).
A soundness bug has been fixed that was due to inadequate checking of
:[meta] rules in the presence of [local] [events]. Specifically, a
local [defevaluator] event is insufficient for supporting a :meta
rule (an example is shown in source function chk-acceptable-rules).
Thanks to Dave Greve and Jared Davis for bringing this bug to our
attention, by sending a proof of nil that exploited this bug. The
fix is to check legality of :meta rules even when skipping proofs
during an [include-book] event or the second pass of an
[encapsulate] event.
Fixed problem with parallel make for workshop books by adding a
dependency line to books/workshops/2003/Makefile.
Default hints (see [set-default-hints]) no longer prevent the use of
:INSTRUCTIONS (see [proof-checker]). Thanks to Jared Davis for
pointing out this problem.
New functions [remove-eq] and [remove-equal] have been defined, in
analogy to [remove]. These two symbols have also been added to
*acl2-exports*. Thanks to David Rager for pointing out that
remove-equal was missing. Moreover, the definitions of delete1-eq
and delete1-equal have been eliminated. Function remove1-eq, now in
:[logic] mode in source file axioms.lisp, serves in place of
delete1-eq, with corresponding new function definitions for
[remove1] and [remove1-equal].
The symbol [assert$] has been added to *acl2-exports*. Thanks to
Jared Davis for the suggestion.
Added SBCL support. Thanks to Juho Snellman for significant
assistance with the port. Thanks to Bob Boyer for suggesting the
use of feature :acl2-mv-as-values with SBCL, which can allow
thread-level parallelism in the underlying lisp; we have done so
when feature :sb-thread is present.
We have continued to incorporate suggestions for wording improvements
in documentation and error messages. Thanks to all who send these
suggestions, especially to Eric Smith, who has suggested the vast
majority of them.
Made a small improvement to errors and warnings caused on behalf of
[set-enforce-redundancy], to indicate when an event of the same
name already exists.
Fixed a bug in books/misc/rtl-untranslate.lisp that was causing a
guard violation when adding a new entry for an existing key.
Fixed a bug in translation to internal form that caused [defun-sk]
and [defchoose] to have difficulties handling ignored variables in
[let] forms. Thanks to Sandip Ray to bringing this issue to our
attention with a helpful example.
The form (push :acl2-mv-as-values *features*) has been added in
source file acl2-init.lisp for SBCL and OpenMCL only, in order to
support parallel execution (looking to the future...).
Default-hints (see [set-default-hints]) were being ignored inside the
[proof-checker], but no longer. Thanks to John Erickson for
bringing this problem to our attention and providing a simple
example of it.
Modified the TAGS \"make\" target (specifically, function make-tags) so
that it is gracefully skipped if the etags program is not found.
Thanks to David Rager for pointing out this issue.
Sandip Ray has re-worked the supporting materials for his ACL2
Workshop 2003 talk (originally with John Matthews and Mark Tuttle),
to run in a few minutes. The result is in
workshops/2003/ray-matthews-tuttle/support/ and is included in the
full ACL2 regression suite. Thanks, Sandip.
Debian releases of ACL2 had created superfluous .cert.final files
when certifying books. This has been fixed; thanks to Jared Davis
for noticing this problem.
Jared Davis has pointed out that ``If you add a :backchain-limit-lst
0 to a rewrite rule whose hypotheses are all forced, then ACL2
`really assumes them' without trying to relieve them right there
through rewriting.'' Relevant documentation has been added for
:backchain-limit-lst; see [rule-classes].
A new version of the rtl library has been included in
books/rtl/rel5/. Thanks to David Russinoff for contributing hand
proofs for the new lemmas, and to Matt Kaufmann for carrying out
their mechanization.
Fixed a bug in [save-exec] that was failing to set the initial cbd
according to the current directory when starting up ACL2. Thanks to
Camm Maguire for bringing our attention to this problem.
Variables introduced during let* abstraction are now in the current
package. Thanks to Jared Davis for suggesting such a change. See
[set-let*-abstractionp].
It is now allowed for two definitions to be considered the same from
the standpoint of redundancy (see [redundant-events]) when one
specifies a :[guard] of t and the other has no explicit :guard
(hence, the guard is implicitly t). Thanks to Jared Davis for
bringing this issue to our attention.
(For users of emacs/emacs-acl2.el) There have been a few enhancements
to distributed file emacs/emacs-acl2. el (skip this paragraph if
you don't use that file):
o Control-t q continues to compare windows ignoring whitespace, but
now, a prefix argument can be given to control case is also
ignored (ignore case if positive, else use case).
o Control-t Control-l has been defined to be similar to Control-t l,
except that proofs are skipped and output is suppressed.
o Control-t u has been defined to print, to the shell buffer, a
:[ubt!] form for the command containing the cursor.
o Control-t Control-f buries the current buffer.
o Meta-x new-shell now puts the new shell buffer in shell-mode
(thanks to David Rager for noticing this issue).
Linear arithmetic has been modified so that we do not generate the
equality (equal term1 term2) from the pair of inequalities (<=
term1 term2) and (<= term2 term1) in the case that we would have to
[force] both term1 and term2 to be [ACL2-numberp]s. Thanks to Dave
Greve for providing a motivating example and to Robert Krug for
providing a fix.
The event [delete-include-book-dir] had not been allowed inside
[books] and [encapsulate] forms. This was an oversight, and has
been fixed.
Sandip Ray has contributed a new library of books to support proofs
of partial and total correctness of sequential programs based on
assertional reasoning, in books/symbolic/. This work is based on
the paper J. Matthews, J S. Moore, S. Ray, and D. Vroon, ``A
Symbolic Simulation Approach to Assertional Program Verification,''
currently in draft form. In particular, the books include the macro
defsimulate, which automatically transforms inductive assertion
proofs of correctness of sequential programs to the corresponding
interpreter proofs. See the README in that directory.
We have changed the implementation of :dir :system for [ld] and
[include-book]. This change will not affect you if you build an
ACL2 executable in the normal manner, leaving in place the books/
subdirectory of the source directory; nor will it affect you if you
download a GCL Debian binary distribution. The change is that if
environment variable ACL2_SYSTEM_BOOKS is set, then it specifies
the distributed books directory, i.e., the directory determined by
:dir :system. You may find it convenient to set this variable in
your ACL2 script file (typically, saved_acl2). If it is set when
you build ACL2, the generated script for running ACL2 will begin by
setting ACL2_SYSTEM_BOOKS to that value. Thanks to various people
who have discussed this issue, in particular Jared Davis who sent
an email suggesting consideration of the use of an environment
variable, and to Eric Smith who helped construct this paragraph.
(Note that this use of ACL2_SYSTEM_BOOKS replaces the use of
ACL2_SRC_BOOKS described previously; see [note-2-9-1].)
ACL2 now automatically deletes files TMP*.lisp created during the
build process and created by :[comp]. If you want these to be
saved, evaluate (assign keep-tmp-files t) in the ACL2 loop or in
raw Lisp. The clean target for the standard `make' process for
certifying books (see [books-certification-classic]) will however
delete all files TMP*.*.
The TMP files discussed just above now generally include the current
process ID in their names, e.g., TMP@16388@1.lisp instead of
TMP1.lisp. Thanks to Bob Boyer for suggesting this measure, which
will reduce the possibility that two different processes will
attempt to access the same temporary file.
Now, :[pe] will print the information formerly printed by :pe!,
slightly enhanced to work for logical names that are strings, not
just symbols. Thanks to Warren Hunt for leading us to this change
by suggesting that :pe nth print the definition of [nth].
We eliminated spurious warnings that could occur in raw mode in
OpenMCL or CMUCL when [stobj]s are present. We thank Juho Snellman
for pointing out the relevant bug and appropriate fix.
Mfc-rw now takes a third argument that can specify an arbitrary known
equivalence relation; see [extended-metafunctions]. Thanks to Dave
Greve for discussions suggesting this improvement.
A small modification to a symbol-reading function allows
documentation string processing on Windows systems that use CR/LF
for line breaks. Thanks to William Cook for bringing this issue to
our attention.
The documentation has been improved on how to control the printing of
ACL2 terms. See [user-defined-functions-table]. Thanks to Sandip
Ray for asking a question that led to the example presented there.
We fixed an inefficiency that could cause an [ld] command to seem to
hang at its conclusion. Thanks to Sandip Ray for pointing out this
problem.
We checked that ACL2 runs under LispWorks 4.4.5, and have inhibited
redefinition warnings.
Two changes have been made on behalf of congruence-based reasoning.
Thanks to Dave Greve for examples and discussions that have led to
these changes, and to Eric Smith and Vernon Austel, who also sent
relevant examples.
o When a call of the new unary function [double-rewrite] is
encountered by the rewriter, its argument will be rewritten
twice. This solves certain problems encountered in
congruence-based rewriting. Warnings for :[rewrite] and
:[linear] rules will suggest when calls of [double-rewrite] on
variables in hypotheses are likely to be a good idea. See
[double-rewrite].
o Hypotheses of the form (equiv var (double-rewrite term)), where
equiv is a known [equivalence] relation and var is a free
variable (see [free-variables]), will bind var to the result of
rewriting term twice. Previously, hypotheses of the form (equal
var term) would bind a free variable var, but the call had to
be of equal rather than of an arbitrary known equivalence
relation.
The following improvements were made in support of ACL2 on top of
OpenMCL.
o New versions of OpenMCL that do not have :mcl in Lisp variable
*features* will now work with ACL2. Thanks to David Rager for
bringing this issue to our attention.
o Added support for OpenMCL 1.0 for 64-bit DarwinPPC/MacOS X, thanks
to Robert Krug.
o Fixed tracing in OpenMCL so that the level is reset to 1 even if
there has been an abort.
o Added support in OpenMCL for WET.
o Incorporated suggestions from Gary Byers for printing the ``Welcome
to OpenMCL'' prompt before initially entering the ACL2 loop
and, and for setting useful environment variable
CCL_DEFAULT_DIRECTORY in the ACL2 script.
Fixed a long-standing bug in forward-chaining, where variable-free
hypotheses were being evaluated even if the
[executable-counterpart]s of their function symbols had been
disabled. Thanks to Eric Smith for bringing this bug to our
attention by sending a simple example that exhibited the problem.
Improved reporting by the [break-rewrite] utility upon failure to
relieve hypotheses in the presence of free variables, so that
information is shown about the attempting bindings. See
[free-variables-examples-rewrite]. Thanks to Eric Smith for
requesting this improvement. Also improved the [break-rewrite] loop
so that terms, in particular from unifying substitutions, are
printed without hiding subterms by default. The user can control
such hiding (``evisceration''); see :DOC set-brr-term-evisc-tuple.
A new directory books/defexec/ contains books that illustrate the use
of [mbe] and [defexec]. Thanks to the contributors of those books
(see the README file in that directory).
The directories books/rtl/rel2 and books/rtl/rel3 are no longer
distributed. They are still available by email request.
(Subdirectory rel1/ supports some of the optional workshop/ books,
so it is still distributed.)
Added book books/misc/sticky-disable.lisp to manage [theories] that
might otherwise be modified adversely by [include-book]. Thanks to
Ray Richards for a query that led to our development of this tool.
The commands (exit) and (quit) may now be used to quit ACL2 and Lisp
completely; in fact they macroexpand to calls of the same function
as does [good-bye] (which is now a macro). Thanks to Jared Davis
for suggesting the new aliases. (OpenMCL-only comment:) These all
work for OpenMCL even inside the ACL2 loop.
The macro wet now hides structure by default on large expressions.
However, a new optional argument controls this behavior, for
example avoiding such hiding if that argument is nil. Thanks to
Hanbing Liu for pointing out that wet was not helpful for very
large terms.
We have fixed a bug in the forward-chaining mechanism that, very
rarely, could cause a proof to be aborted needlessly with an
obscure error message. Thanks to Jared Davis for sending us an
example that evoked this bug.
Fixed a bug that was causing proof output on behalf of
:functional-instance to be confusing, because it failed to mention
that the number of constraints may be different from the number of
subgoals generated. Thanks to Robert Krug for pointing out this
confusing output. The fix also causes the reporting of rules used
when silently simplifying the constraints to create the subgoals.
Fixed a bug in handling of leading ./ in pathnames, as in:
(include-book \"./foo\"). Thanks to Jared Davis for bringing this bug
to our attention.
Made a small fix for handling of free variables of
:[forward-chaining] rules, which had erroneously acted as though a
hypothesis (equal var term) can bind the variable var.
A small change has been made for :[type-prescription] rules for
hypotheses of the form (equal var term), where var is a free
variable and no variable of term is free (see [free-variables]). As
with :[rewrite] and :[linear] rules, we now bind var to term even
if (equal u term) happens to be known in the current context for
some term u. Also as with :rewrite and :linear rules, similar
handling is given to hypotheses (equiv var (double-rewrite term))
where equiv is a known [equivalence] relation.
We changed the handling of free variables in hypotheses of :[rewrite]
rules being handled by the [proof-checker]'s rewrite (r) command,
in complete analogy to the change described just above for
:[type-prescription] rules.
The installation instructions have been updated for obtaining GCL on
a Macintosh. Thanks to Robert Krug for supplying this information
and to Camm Maguire for simplifying the process by eliminating the
gettext dependency.
The macro [comp] is now an event, so it may be placed in [books].
Previously, a [save-exec] call could fail because of file permission
issues, yet ACL2 (and the underlying Lisp) would quit anyhow. This
has been fixed. Thanks to Peter Dillinger for bringing this problem
to our attention.
Jared Davis, with assistance from David Rager, has updated his
ordered sets library, books/finite-set-theory/osets/. See file
CHANGES.html in that directory.
A new function, [reset-kill-ring], has been provided for the rare
user who encounters memory limitations. See [reset-kill-ring].")
(NOTE-2-9-5
(RELEASE-NOTES)
"Changes in Version 3.0 since Version 2.9.4
Fixed a bug in [cw-gstack] that was causing a hard error when
attempting to report on a forced assumption. Thanks to Jared Davis
for pointing this out and sending an example that helped us to
determine a fix.
Added [set-backchain-limit] to the set of legal [events] that can be
placed in [encapsulate] forms and [books]. Thanks to John Cowles
for bringing this issue to our attention.
Fixed a bug that broke wet. Thanks to David Rager for bringing this
bug to our attention.
Guard verification now evaluates ground subexpressions (those with no
free variables) when computing the guard conjecture for the body of
a function. Thanks to Jared Davis for useful conversations leading
to this change. See [verify-guards], in particular its ``Note on
computation of guard conjectures and evaluation'' near the end of
that topic, for more details.
Added a warning when a [theory-invariant] is redefined. Thanks to
Jared Davis for suggesting a warning in this case and providing an
informative example. Also, [theory-invariant]s are now maintained
more completely, as they are checked at the end of every event
except for events executed on behalf of an [include-book] or the
second pass of an [encapsulate].
Fixed the handling of runic designators to match their specification
(see [theories]), so that disabling the name of a [defthm] event
[disable]s all rules generated for that event.
(For those who do numerous builds using feature :acl2-mv-as-values,
currently only OpenMCL and multi-threaded SBCL by default:) You can
speed up builds by adding the following parameter to `make', under
conditions described in GNUmakefile: USE_ACL2_PROCLAIMS=:REUSE.
Arranged that traced functions (see [trace$]) are automatically
untraced when events are undone (for example see [ubt]), at least
for most underlying Common Lisp implementations.
The macro [defun-sk] now creates non-executable functions, which
allows [stobj]s to be used where they had previously been
prohibited. More generally, the user now has control over [declare]
forms to be used by the underlying [defun]'d function; see
[defun-sk]. Thanks to Sandip Ray for pointing out the need for such
a modification.
:[Definition] rules are now treated, at least by default, as truly
first-class definitions. In particular, :expand [hints] use the
latest :[definition] rule by default. You may specify :install-body
nil to get the previous behavior of :definition rules; See
[definition], and you may choose a previously-installed :definition
rule to provide the current body; see [set-body]. Also see
[rule-classes] for details of the :install-body field, and see
[hints] to see a new :with directive for controlling expansion. The
:with directive for :expand hints can even direct the use of a
:[rewrite] rule for expansion! Thanks to various people, including
Sandip Ray and Rob Sumners, for discussions on the issue of the
applicability of :definition rules for :expand [hints].
[Constraint]s for functional instantiation now use the original
definition rather than a simplified (``normalized'') version of it.
Fixed a bug that caused the prompt to stay the same when
guard-checking is off (see [set-guard-checking]) and raw-mode is
changed (see [set-raw-mode]).
Lemma names in directory books/ordinals have been changed by
replacing /\\ with & and replacing \\/ with V. We made this change
because backslash is an escape character and hence disappears
unless it is itself escaped.
Fixed [proof-tree] output so that failed non-proof events do not
cause the proof-tree to be re-printed. Thus for example, if you
have already advanced the checkpoint marker, it will not be reset
by subequent failed non-proof events. Thanks to Pete Manolios and
Peter Dillinger for bringing this bug to our attention.
Fixed a bug that was preventing the printing of [stobj] fields as
constants instead of numbers in certain cases. (Note that this bug
only affected printing, not soundness.) Thanks to Eric Smith for
bringing this problem to our attention and providing the following
example (which now works fine).
(defstobj st fld1 fld2)
(in-theory (disable update-nth))
(defund run (st)
(declare (xargs :stobjs (st))) ;adding this didn't seem to help..
st)
;works great; *fld1* prints as *fld1*
(thm (equal (update-nth *fld1* 'abc st)
(car (cons x y))))
;*fld1* gets printed as 0, presumably because the call to run intervenes.
(thm (equal (update-nth *fld1* 'abc (run st))
(car (cons x y))))
The macro [progn] now allows the use of macros defined within its
bodies even when at the event level, as illustrated by the
following example.
(progn (defmacro my-defun (&rest args)
`(defun ,@args))
(my-defun g (x) x))
Thanks to Anna Slobodova for bringing this issue to our attention. A
related change is that all arguments of [progn] must now be
embedded event forms (see [embedded-event-form]), so use [er-progn]
instead if this is not the case.
The change to [progn] mentioned above also fixes a bug in handling
[local] events inside a [progn] that is inside an [encapsulate] or
in a book. For example, the following form formerly caused an
error.
(encapsulate
()
(defun foo (x) x)
(progn (local (defun bar (x) x))
(defun abc (x) x)))
We fixed two bugs in :[puff] and :[puff*]. The first, brought to our
attention by Eric Smith (who we thank), caused a cryptic error
message when puffing a command with no subsidiary stored events;
try, for example, (encapsulate () (value-triple 3)). The second was
due to a failure to restore the [ACL2-defaults-table]. Suppose for
example that we have certified the book foo.lisp, which contains
([program]) followed by some definitions and/or theorems. Now
suppose we start ACL2 and execute the following.
(include-book \"foo\")
(defthm test-thm
(equal x x)
:rule-classes nil)
If we now execute :[puff] 1, ACL2 will roll back the world to before
the [include-book]; then ``puff'' the include-book, which will
leave us in :[program] mode; and finally skip re-execution of the
[defthm] because such [events] are skipped in :[program] mode. The
fix is to re-install the [ACL2-defaults-table] immediately after
the [include-book] to its pre-[include-book] value.
A new event, [make-event], provides something like macros that take
state. For example, one can use it to put tests into certified
books, do proof search, and generate new function names. Many
examples appear in directory books/make-event/. See [make-event].
Thanks to Bob Boyer and Jared Davis for useful feedback and to
Warren Hunt, David Rager, and Sandip Ray for helpful discussions
leading to some of the examples in directory books/make-event/.
In support of [make-event], which is described in the preceding
paragraph, certify-book has a new keyword argument,
:save-expansion, that controls whether the result of expanding
[make-event] forms is written out to a file. See [certify-book];
and for a discussion of book expansion files, see [make-event].
We fixed a soundness bug that did not correctly detect [local]
events. For example, the following event was admitted.
(encapsulate
()
(local
(encapsulate
()
(local (progn (program))) ; or, (local (with-output :off summary (program)))
(set-irrelevant-formals-ok t)
(defun foo (x)
(declare (xargs :measure (acl2-count x)))
(1+ (foo x)))))
(defthm inconsistent
nil
:hints ((\"Goal\" :use foo))
:rule-classes nil))
A new value for [guard] checking, :none, is now allowed. If you
execute :[set-guard-checking] :none, then no guard checking will
take place (but raw Lisp code will not be executed in this case).
As a result, you should never see a guard violation, even for calls
of :program mode functions. We thank Pete Manolios, who has long
wanted this feature, and also Peter Dillinger, for asking for it.
New documentation explains the interaction between the [defun-mode]
and the value supplied to :[set-guard-checking]. See
[guard-evaluation-table], see [guard-evaluation-examples-script],
and see [guard-evaluation-examples-log].
In the course of adding the [guard]-checking value :none described in
the paragraph above, we eliminated an optimization that eliminated
guard checking for some recursive calls of :[logic] mode
mutually-recursive functions that have not had their guards
verified. But we doubt that this change will be noticed by any
users!)
The ACL2 hyper-card has been enhanced, thanks to David Rager, with a
listing of ``Useful EMACS Commands'' to match comments in
emacs/emacs-acl2.el.
Users contributed books following the Readme.lsp methodology:
data-structures/memories and unicode (Jared Davis), proofstyles
(Sandip Ray and J Moore).
Made some improvements to books/Makefile-generic (a file discussed
elsewhere; see [books-certification-classic]). In particular,
improved handling of .acl2 files for dependencies target.
(Only OpenMCL and, with feature :acl2-mv-as-values, GCL) Fixed a bug
that was causing proclaiming to fail when definitions are submitted
interactively.
The default stack size has been increased for several lisps.
(Very technical) A restriction has been weakened on the use of
[local] [stobj]s under a call of an ACL2 evaluator (trans-eval or
simple-translate-and-eval). Now, the error can only take place for
[stobj] names that occur in the term being evaluated. Thanks to
Erik Reeber for bringing this issue to our attention.
The notion of ``ancestor'' has been changed slightly. This notion is
used by extended metafunctions and [break-rewrite] (see
[extended-metafunctions] and see [brr@]), and also with backchain
limits (see [backchain-limit] and see [set-backchain-limit]).
Basically, each time a hypothesis is encountered during application
of a [rewrite] rule, that hypothesis is pushed (after instantiating
and negating) onto the current list of ancestors before it is
rewritten. However, hypotheses of the form (equal var term), where
var is free (see [free-variables]), had not been included in the
ancestors (similarly for (equiv var (double-rewrite term)) where
equiv is a known [equivalence] relation). Now such ``binding
hypotheses'' are included in a special way in ancestors data
structures. In particular, (null (mfc-ancestors mfc)) will now be
true if and only if the term being rewritten is part of the current
goal as opposed to a hypothesis from a rule encountered during
backchaining, even if that hypothesis is a binding hypothesis.
Thanks to Dave Greve for bringing this issue to our attention.
Termination and induction analysis now continue through both
arguments of [prog2$], not just the second. (Normally, the
gathering up of [if] tests stops at function calls; but it
continued through the second argument of [prog2$], and now it will
continue through both arguments.) Thanks to Sol Swords for
discussion leading to this change.
The ACL2 distribution is now kept on the http server rather than the
ftp server (but the home page has not been moved). Thanks to Robert
Krug for letting us know that some ACL2 users have found it
inconvenient to fetch ACL2 using ftp.
The file books/README.html has been renamed to books/Readme.html,
since some browsers don't show the former in the directory listing.")
(NOTE-2-9{R}
(RELEASE-NOTES)
"ACL2 Version 2.9(r) (October, 2004) Notes
No changes have been made for support of non-standard analysis, other
than a minor modification or two in books/nonstd/ books.
Please also see [note-2-9] for changes to Version_2.9 of ACL2.")
(NOTE-3-0
(RELEASE-NOTES)
"ACL2 Version 3.0 (June, 2006) Notes
Please see [note-2-9-5] for a description of changes since Version
2.9.4. These include the new [make-event] feature, a soundness bug
fix, an improvement for :expand [hints], evaluation in the logic by
way of :[set-guard-checking] :none, and many other improvements.
More generally, there have been several incremental releases since
Version 2.9: see [note-2-9-1], see [note-2-9-2], see [note-2-9-3],
see [note-2-9-4], and see [note-2-9-5].
A very few users have contributed books following the instructions on
the web. We expect that when more contributions come in, we will
give more attention to the question of how to organize the
distributed and workshop books. For now, we have simply added the
new contributions according to the old-style distribution
methodology.")
(NOTE-3-0-1
(RELEASE-NOTES)
"ACL2 Version 3.0.1 (August, 2006) Notes
NOTE! New users can ignore these release notes, because the
documentation has been updated to reflect all changes that are
recorded here.
Fixed a soundness bug, introduced in the previous release, due to a
failure to disallow [table] [events] that set the
[ACL2-defaults-table] in a [local] context. Here is a proof of nil
that exploits the bug.
(encapsulate ()
(local (program))
(defun foo ()
(declare (xargs :measure 17))
(+ 1 (foo))))
(thm
nil
:hints ((\"Goal\" :in-theory (disable foo (foo)) :use foo)))
Fixed a bug in the alternatives to [good-bye], which are the [exit]
and [quit] commands. Thanks to Jared Davis and Peter Dillinger for
pointing this out right away.
The definition of [len] has been highly optimized in raw Lisp. Thanks
to Bob Boyer and Warren Hunt for suggesting such an improvement and
providing a lot of help in coming up with the current
implementation.
The clause subsumption algorithms have been improved, both to improve
efficiency during warnings for :[rewrite] rules and to punt when
the subsumption computation for induction appears to be blowing up.
Thanks to Robert Krug for bringing this issue to our attention and
supplying a useful example.
A bug has been fixed that prevented [time$] from working properly in
OpenMCL and multi-threaded SBCL (actually, in any ACL2 image where
feature :acl2-mv-as-values is present). Thanks to Sol Swords for
bringing this problem to our attention.
A [type-spec] of the form (satisfies pred) carries the requirement
that pred be a unary function symbol in the current ACL2 [world];
otherwise, it is illegal. Thanks to Dave Greve for pointing out
that Common Lisp has this requirement.
Installed a fix provided by Gary Byers (for ACL2 source function
install-new-raw-prompt), for OpenMCL, that fixes an issue exposed
in some versions of OpenMCL when compiler optimization is off.
Fixed a bug in contributed book misc/untranslate-patterns.lisp that
was causing calls of add-untranslate-pattern to be rejected in
[books]. Thanks to Ray Richards for pointing out this bug and to
Jared Davis for assisting in the fix.
Fixed a bug in [defstobj] when keywords :initially and :resizable are
both supplied. In this case, the definition of the resizing
function mistakenly failed to quote the :initially value, even
though this value is not to be evaluated. One could even get an
error in this case, as in the following example supplied by Erik
Reeber, whom we thank for bringing this bug to our attention:
(defstobj $test
(test-x :type (array t (5)) :initially (0) :resizable t))
A new feature, [with-prover-time-limit], allows the setting of time
limits during proofs. This is not a general-purpose time-limit
utility, nor is it guaranteed to implement a strict bound; it only
attempts to limit time approximately during proofs. Thanks to Pete
Manolios and Daron Vroon, who made the most recent request for such
a feature, and to Robert Krug for a helpful discussion.
(GCL only) Fixed a bug in the procedure for building a profiling
image. Thanks to Sol Swords for bringing this bug to our attention
and to Eric Smith for bringing a subsequent problem to our
attention.
Handling of [theories] can now use significantly less time and space.
A regression suite run took about 25% longer before this change
than it did after making this change (and also the ones in the next
two paragraphs). Thanks to Vernon Austel for bringing this issue to
our attention and for supplying code, quite some time ago, that
provided detailed, useful implementation suggestions. Also thanks
to the folks at Rockwell Collins, Inc. for pushing the limits of
the existing implementation, thus encouraging this improvement.
Fixed a performance bug in obtaining executable counterpart symbols.
We now avoid certain computations made on behalf of warnings, when
such warnings are disabled.
We have relaxed the checks made when including an uncertified book,
to match the checks made when including a certified book. Thanks to
Eric Smith for suggesting this change.
Fixed a bug in :[pso] (see [set-saved-output]) that caused an error
when printing the time summary.
Made fixes to avoid potential hard Lisp errors caused by the use of
:[program] mode functions. The fix was to use a ``safe mode,''
already in use to prevent such errors during macroexpansion; see
[guards-and-evaluation]. However, such errors were possible during
evaluation of macro [guard]s, for example as follows:
(defun foo (x)
(declare (xargs :mode :program))
(car x))
(defmacro mac (x)
(declare (xargs :guard (foo 3)))
x)
(defun g (x)
(mac x))
A similar issue existed for calls of [defpkg], [in-theory], [table],
[make-event], and value-triple, but has been fixed for all but
in-theory and make-event, where technical issues have caused us to
defer this change.
Fixed a bug in wet that caused problems in OpenMCL, and perhaps other
Lisp implementations, when the argument to wet calls, or depends
on, certain built-ins including [prog2$], [time$], [mbe], and
[must-be-equal]. Thanks to David Rager for bringing this problem to
our attention.
The file books/Makefile-generic has been improved so that when book
certification fails with `make', the failure message contains the
book filename.
Documentation has been written to explain how to avoid an expensive
immediate rewrite of the result of applying a :[rewrite] or :[meta]
rule. See [meta]. Thanks to Robert Krug for supplying this trick,
and to Eric Smith and Dave Greve for useful discussions.
(OpenMCL only) OpenMCL-based ACL2 image names formerly had extension
\".dppccl\", which was correct only for some platforms (including
32-bit Darwin PPC). That has been fixed, thanks to a suggestion
from Gary Byers.
It is now legal to attach both a :use and a :cases hint at the same
goal. Thanks to Eric Smith for (most recently) requesting this
feature.
It is now permissible to include the same symbol more than once in
the imports list of a [defpkg] form (i.e., its second argument).
Also, the evaluation of [defpkg] forms with long import lists now
uses a reasonably efficient sorting routine to check for two
different symbols with the same name (see also
books/misc/sort-symbols.lisp). If you currently call a function
like remove-duplicates-eql for your imports list, as had been
suggested by a [defpkg] error message, then you may experience some
speed-up by removing that call. Thanks to Eric Smith for helping to
discover this issue through profiling.
Made miscellaneous efficiency improvements not listed above (for
example, following a suggestion of Eric Smith to avoid checking for
so-called ``bad Lisp objects'' during [include-book], which saved
almost 3% in time on one large example).
Modified the notion of ``untouchable'' to separate the notion of
untouchable functions and macros from the notion of untouchable
state global variables. See [push-untouchable]. Thanks to Bob Boyer
for sending an example, (put-global 'ld-evisc-tuple t state), that
suggested to us the need for more restrictive handling of
untouchables. In particular, many ld specials (see [ld]) are now
untouchable. You may be able to work around this restriction by
calling [ld]; see for example the change to
books/misc/expander.lisp. But please contact the ACL2 implementors
if this sort of workaround does not appear to be sufficient for
your purposes.
Fixed a bug in function set-standard-oi (see [standard-oi]).
Fixed a bug in the use of [ld-evisc-tuple]. The bad behavior was an
improper use of the print-level and print-length components of the
tuple (specifically, taking its [caddr] and [cadddr] instead of
taking its [cadr] and [caddr]). Thanks to Bob Boyer for bringing
this bug to our attention.
A new argument to the compile-flg argument of [certify-book], :all,
causes creation of a file to be compiled in place of the given
book, where that file contains not only a copy of the book (with
[make-event] forms expanded) but also contains definitions of the
so-called ``executable counterparts'' of the functions defined in
the book. Then, functions defined in the book will be run compiled
when including the book, even for functions whose [guard]s have not
been verified, or are in :program mode and running in so-called
``safe mode'' (for example, during expansion of macros). The
default behavior, value t of compile-flg, is unchanged. Moreover, a
new :comp! argument of [include-book] now compiles the executable
counterparts when creating the book's compiled file, and unlike
:comp, always deletes the old compiled file first so that one
always gets a fresh compile.
Now, [certify-book] gives a \"Guards\" warning only for :[logic] mode
functions that are defined in the given book but have not had their
guards verified. Previously, it also warned about such functions
that were defined in the certification world or in sub-books.
A new command, [redo-flat], facilitates the debugging of failed
[encapsulate] and [progn] forms by evaluating preliminary forms in
order to leave one at the point of failure. See [redo-flat]. Thanks
to Ray Richards and others for asking for such a utility, and to
Sandip Ray for useful discussions.
We have changed the automatic declaration of of function types (still
done in GCL and OpenMCL only, for now). Our motivation was to avoid
the assumption that Common Lisp functions return one value when
ACL2 says that they do; thanks to Bob Boyer for bringing this issue
to our attention with the example of defining (foo x y) to be
(floor x y). ACL2 was saying that foo returns a single value, but
because floor returns two values in raw Lisp, so does foo. Other
changes to automatic declaration include comprehending [defund],
not just [defun].
A new function, [mod-expt], computes (mod (expt base exp) m), and
does so efficiently in some implementations (currently only in GCL
2.7.0, which is not yet released). Thanks to Warren Hunt for
suggesting such an addition.
New functions [getenv$] and [setenv$] have been made available for
reading and writing environment variables. Thanks to Jun Sawada for
requesting these utilities.
The query utility :[pl] has been improved in several ways. As before,
:[meta] rules are only printed if the argument is a symbol; but the
information printed for them is now more appropriate. The following
are changes for the case that the argument is not a symbol, but
rather, a term. (1) Rules are displayed that have [equivalence]
relations other than [equal]. (2) All matching :[definition] rules
are displayed, where previously :definition rules were only shown
if they were ``simple'' rules (sometimes known as
``abbreviations''); see [simple]. (3) The ``Equiv'' field is
printed for terms, not just symbols. (4) The substitution is shown
that, when applied to the left-hand side of the rule, will yield
the specified term. Thanks to Eric Smith for suggesting these
changes.
The [proof-checker] command ;show-rewrites has been improved to match
the changes described above for :[pl]. In particular, :[definition]
rules that are not ``[simple]'' are now displayed by the
[proof-checker]'s show-rewrites (and sr) command, and the
[proof-checker]'s rewrite command has been correspondingly modified
to accept these :definition rules.
Fixed `make' targets copy-distribution, copy-workshops, and
copy-nonstd so that they should also work for non-developers.
Fixed a bug that was causing :[pr] to display [syntaxp] hypotheses
oddly in some cases, in particular (syntaxp (let ...)). (The
problem was in the ``untranslate'' display of the internal form of
syntaxp calls.) Thanks to Robert Krug for bringing this problem to
our attention. We also removed the restriction on [bind-free] that
its argument could not be a variable, a constant, or (more
interestingly) a [lambda] application (i.e., a [let] or [mv-let]
expression).")
(NOTE-3-0-1{R}
(RELEASE-NOTES)
"ACL2 Version 3.0.1(r) (August, 2006) Notes
No significant changes have been made since Version 3.0 for support
of non-standard analysis in particular.
Please also see [note-3-0-1] for changes to Version 3.0.1 of ACL2.")
(NOTE-3-0-2
(RELEASE-NOTES)
"ACL2 Version 3.0.2 (December, 2006) Notes
NOTE! New users can ignore these release notes, because the
documentation has been updated to reflect all changes that are
recorded here.
Fixed soundness bugs in the handling of primitive function
[pkg-witness], and improved its documentation. (The executable
counterpart returned an incorrect default value, and the axiom
symbol-package-name-pkg-witness-name needed pkg-name to be other
than \"\" in order to avoid the default value of \"ACL2\".) As fallout,
a new built-in :[forward-chaining] rule,
symbol-package-name-of-symbol-is-not-empty-string, now asserts that
the [symbol-package-name] of a symbol is never \"\". Thanks to Mike
Gordon for bringing these soundness bugs to our attention by
attempting to prove translations of ACL2 axioms in HOL4.
Fixed a soundness bug in linear arithmetic, due to incomplete
tracking of forced assumptions while deriving inequalities. Thanks
to Robert Krug for providing a fix and a proof of nil before the
fix.
Fixed a soundness bug in the redundancy criterion for [defun] events,
which has been modified; see [redundant-events]. This bug is
illustrated below. Thanks to Peter Dillinger and Jared Davis for
contributions to an email thread that led us to discover this bug.
The solution is that for a definition to be redundant with an
earlier definition, ACL2 no longer ignores :[measure] [xargs]
except when skipping proofs (e.g., during [include-book]). However,
a new ``measure'', (:? v1 ... vk), is supported, for specifying a
measured subset of the set of formals, i.e., a set of formals that
serves as the set of parameters for some valid measure.
(encapsulate
()
(local (defun foo (x y)
(declare (xargs :measure (acl2-count y)))
(if (and (consp x) (consp y))
(foo (cons x x) (cdr y))
y)))
; So the following is redundant -- but it guesses a measure
; of (acl2-count x), which isn't right!
(defun foo (x y)
(if (and (consp x) (consp y))
(foo (cons x x) (cdr y))
y)))
; end of encapsulate
; Now we prove a non-theorem by exploiting the bug above,
; erroneously replacing formal y by a constant in the induction
; scheme hinted below. (This should not be allowed, as y should be
; labeled as a measured formal.)
(defthm bad
(atom x)
:rule-classes nil
:hints ((\"Goal\" :induct (foo x '(3)))))
; It's easy to get a contradiction by instantiating the
; non-theorem just above.
(defthm contradiction
nil
:rule-classes nil
:hints ((\"Goal\" :use ((:instance bad (x '(7)))))))
Fixed a bug in :[pl] and the [proof-checker]'s show-rewrites (sr)
command that was causing a Lisp break. For :[pl], also improved the
display of unifying substitutions, modified output to take binding
hypotheses (equal var term) into account properly, and arranged for
inclusion of [meta] rules that modify the given term. Thanks to
Eric Smith for bringing these issues to our attention.
Introduced new utilities for undoing [command]s, :[ubu] and :[ubu!],
which are analogous to :[ubt] and :[ubt!] (respectively) except
that they only undo back up to, but not including, the indicated
command.
Fixed a performance bug, pointed out by Eric Smith, that was negating
efforts made for the preceding release to avoid computation for
disabled warnings.
Added [time$] and value-triple to *acl2-exports*. Thanks to Bob Boyer
and Erik Reeber (respectively) for bringing these issues to our
attention.
Improved the automatic proclaiming of function types for GCL and
OpenMCL, specifically to use an output format consistent with the
Common Lisp spec. Thanks to Bob Boyer for bringing this issue to
our attention.
Added books/misc/transfinite.lisp, which deals with transfinite
induction in ACL2. Thanks to Eric Smith for contributing this book.
Added books/misc/process-book-readme.lisp to the distribution. Thanks
to Sandip Ray for pointing out its omission.
Added contributions books/concurrent-programs/bakery/ and
books/concurrent-programs/german-protocol/. These contributions can
be used as tutorials, especially by new ACL2 users, for learning
how to model concurrent protocols in ACL2 and the steps involved in
reasoning about their correctness. Thanks to Sandip Ray for these
contributions. See the Readme.lsp files in these directories.
Theory invariants may now involve the variable ENS instead of the
variable THEORY. The practical effect of this change is that any
expression of the form (MEMBER-EQUAL rune THEORY) occurring in a
[theory-invariant] expression should be replaced by (ACTIVE-RUNEP
rune). See [theory-invariant]. Thanks to Eric Smith and Dave Greve
for pointing out an inefficiency in the handling of theory
invariants that led to this change, which can speed up their
handling by orders of magnitude on large examples, and to Eric for
testing this change and pointing out problems with an early
implementation of it.
Theory invariants (see [theory-invariant]) are no longer checked on
theories defined by [deftheory] [events]. After all, one can define
a theory with deftheory that is not intended to be used as the
current theory, but rather is intended to be combined with other
[theories] (see [theory-functions]). Thanks to Eric Smith for
bringing this issue to our attention.
[Theory-invariant] errors had been reported with very little detail
when warnings were inhibited. This problem has been fixed; thanks
to Eric Smith for bringing it to our attention and providing an
example. We have also improved the handling of redundancy for
[theory-invariant] [events].
The macro [defun-sk] now has a new optional keyword, rewrite, that
can be used to change the form of the :[rewrite] rule generated
when the quantifier is [forall]. Thanks to Eric Smith and Sandip
Ray for useful discussions on this topic. We have also slightly
modified the [hints] for the [defthm] event underneath a defun-sk
in order to make the proof more reliably efficient.
A new event, [reset-prehistory], allows setting of a barrier before
which undoing is illegal. An argument to this macro allows the
barrier to be made permanent; otherwise, it can be removed with
:[ubt-prehistory]. Thanks to Peter Dillinger for useful
conversations leading to the addition of [reset-prehistory].
A new query, ([wormhole-p] [state]), allows users to determine
whether or not they are in a [wormhole]. Thanks to Peter Dillinger
for providing this utility.
Value-triple no longer evaluates its form during [include-book], and
in raw Lisp its calls trivially macroexpand to nil, without any
consideration of its argument. This change avoids errors and
warnings when [stobj] names occur in the argument.
We fixed what could be considered a soundness hole that could occur
by exploiting redefinition in a particular way. Thanks to Peter
Dillinger for raising a question that led to discovery of this
hole.
A bug has been fixed in handling of illegal [theory] expressions.
Thanks to Eric Smith, who reported this problem and provided the
example (in-theory '((:definition natp) (:rewrite doesntexist))) to
show how a hard error could occur.
Improved error reporting by [certify-book] when the certification
[world] contains inadmissible forms.
Modified [defchoose] to add two new keyword arguments. There is now a
:doc keyword argument; previously, an optional documentation string
(see doc-string) was to be placed just before the body, without a
keyword. There is also a :strengthen argument that strengthens the
axiom added, which allows for the definition of ``fixing''
functions for equivalence relations that choose canonical
representatives of equivalence classes. See [defchoose]. Thanks for
Dave Greve for useful discussions that led us to this :strengthen
enhancement.
Added books/misc/bash.lisp, which provides utilities for simplifying
a goal into a list of subgoals (as documented at the top of that
file). Thanks to Dave Greve for requesting this utility and
suggesting refinements to its functionality, which have been
incorporated.
(For Emacs users only) The command meta-x new-shell provided by file
emacs/emacs-acl2.el now puts you in shell-mode, which for example
supports directory tracking. Thanks to Jared Davis for suggesting
this change.
Fixed some mishandling of [stobj]s by [make-event] expansion.
Introduced a new event, [defttag], that introduces a ``trust tag''
(``ttag'') allowing for extensions of ACL2 and for the use of
generally unsafe ACL2 constructs. Thanks to Peter Dillinger, Sandip
Ray, and Erik Reeber for useful discussions on defttag and the
following related items.
A new event, [remove-untouchable], can be used to give users access
to system functions and data structures. We also fixed a bug in
[push-untouchable]; and, it no longer is a no-op in :[program]
mode. Thanks to Peter Dillinger for proposing
[remove-untouchable] and suggesting that it and
[push-untouchable] be functional in :[program] mode.
Raw-mode (see [set-raw-mode]) no longer disables [certify-book].
However, [set-raw-mode] is now disallowed unless there is an
active ttag (see [defttag]). If you want to execute
([set-raw-mode] t) and there is no active ttag, consider
executing ([set-raw-mode-on!]) instead.
Redefinition of system functions is disallowed unless there is an
active ttag. However, [redef!] now introduces (defttag :redef!)
in order to allow redefinition of system functions.
A new event, [progn!], is a legal embedded event form that can go in
[books] and both [encapsulate] and [progn] forms (see
[embedded-event-form]), and is similar to [progn] except that
it allows arbitrary forms. Thus, a [progn!] form is potentially
dangerous and can only be evaluated if there is an active ttag.
See [ttags-seen] for information about how to find the ttags known in
the current ACL2 [world], and for related caveats.
A new book created with Peter Dillinger, books/misc/hacker.lisp
(added after Version_3.3: now books/hacking/hacker.lisp), uses
[progn!] to define utiliities with-raw-mode and
with-redef-allowed, which respectively allow raw Lisp
evaluation and redefinition to take place within a certifiable
book (!).
Macro [with-output] is no longer allowed in function bodies because
it does not have (and has never had) any effect in raw Lisp. See
[with-output] for a workaround.
Fixed a bug in redundancy of [defstobj] in raw Lisp, which caused an
error when certifying a book with a redundant [defstobj] event
whose [stobj] had already been modified. Here is an example:
(defstobj st fld)
(update-fld 3 st)
(certify-book \"foo\" 1) ; where foo.lisp contains (defstobj st fld)
New books illustrating [make-event] have been contributed in
directory books/make-event/: dotimes.lisp (David Rager),
stobj-test.lisp, and logical-tangent.lisp (Peter Dillinger).
Modified print-object$ (see [io]) so that it no longer prints an
extra space at the end.
Replaced the ``draconian restriction to avoid capture'' that had
prevented some :functional-instance [hints] from being legal. The
corresponding check now only requires that no variable free in the
functional substitution is captured by a [let] or [mv-let] (or
[lambda]) binding. See [lemma-instance].
Added new extended metafunction, mfc-rw+, which is equivalent to
mfc-rw except that it takes an alist argument, which may be useful
for efficiency. See [extended-metafunctions]. Thanks to Robert Krug
for suggesting this more efficient variant of mfc-rw.
Added support for the ignorable [declare] form.
We now cause an error on a call of open-input-channel (see [io]) with
an argument string whose first character is the | character. Thanks
to Bob Boyer for providing an example (several months ago) showing
the danger of such calls, namely that the following command would
log you out and kill all of your processes when running on top of
GCL in Linux:
(open-input-channel \"|kill -9 -1\" :object state)
Restricted the use of [make-event] to contexts in which it can be
tracked properly, under legal [events] (see [embedded-event-form]).
Thanks to Peter Dillinger for bringing an example to our attention
that led to this fix.
Fixed a bug that was avoiding [guard]-checking for the functions
[compress1] and [compress2]. Thanks to David Rager for bringing
this bug to our attention.
Added an error message when a [defun] or [mutual-recursion] event
fails, to clarify whether failure is for the [measure] conjecture
or for the [guard] conjecture. Thanks to David Rager for requesting
clarification for such failures.
Fixed a bug in reporting of [guard] violations (hard Lisp error) when
certain macros (for example, [cond]) are used in the [guard].
Thanks to Jared Davis for bringing this problem to our attention
and providing assistance with the solution, in particular by
providing a helpful example.
Grant Passmore has contributed a resolution/paramodulation prover
written in ACL2, in directory books/deduction/passmore/. Thanks,
Grant.
Improved the error message when illegal theories are encountered.
Improved the suppression of output for inhibit-output arguments of
routines in the book books/misc/expander.lisp. Thanks to Qiang
Zhang for pointing out the possibility for improvement here.
Added a new directory books/arithmetic-3/extra/ that extends
books/arithmetic-3 with additional rules, contributed by Alex
Spiridonov with guidance from Robert Krug. WARNING: This directory
is under development. It may undergo large changes in future
releases, so please consider it experimental and subject to change.
Feedback is welcomed.
As part of the work mentioned just above, Robert Krug and Alex
Spiridonov contributed improvements to books/arithmetic-3/:
o A new rule |(* (/ x) (/ (expt x n)))| in bind-free/collect.lisp,
which is important for reducing collect-* expressions though it
slowed down one proof (see comment above this rule in
bind-free/collect.lisp).
o Slight improvements of rules integerp-mod and rationalp-mod in
floor-mod/floor-mod.lisp.
o To avoid conflict with books/rtl/rel6/arithmetic/, renamed rule
mod-minus to mod-neg in floor-mod/floor-mod.lisp, and renamed
integerp-+-reduce-leading-constant to
integerp-+-reduce-leading-rational-constant in
bind-free/integerp.lisp.
(GCL on Windows only) Made a low-level change to avoid multiplying
stacks for GCL on Windows, since GCL 2.6.6 broke while doing this.
Fixed bugs in linear arithmetic (rarely evidenced, it seems)
involving using < to compare complex rational constants. Thanks to
Robert Krug for helping with the fixes.
Added a new event, [assert-event], for checking that forms evaluate
to non-nil values. Thanks to Peter Dillinger for suggesting and
collaborating on this addition.")
(NOTE-3-0{R}
(RELEASE-NOTES)
"ACL2 Version 3.0(r) (June, 2006) Notes
No significant changes have been made since Version 2.9 for support
of non-standard analysis in particular.
Please also see [note-3-0] for changes to Version 3.0 of ACL2.")
(NOTE-3-1
(RELEASE-NOTES)
"ACL2 Version 3.1 (December, 2006) Notes
NOTE! New users can ignore these release notes, because the
documentation has been updated to reflect all changes that are
recorded here.
Please see [note-3-0-2] for a description of changes since Version
3.0.1, and also see [note-3-0-1] for additional changes since
Version 3.0.")
(NOTE-3-1{R}
(RELEASE-NOTES)
"ACL2 Version 3.1(r) (December, 2006) Notes
No significant changes have been made since Version 3.0 for support
of non-standard analysis in particular.
Please also see [note-3-1] for changes to Version 3.1 of ACL2.")
(NOTE-3-2
(RELEASE-NOTES)
"ACL2 Version 3.2 (April, 2007) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Before this release, a raw Lisp error could put the ACL2 user into
the debugger of the host Common Lisp. Now, such cases will
generally put the user back at the top-level loop after an
informative message. For details, see [set-debugger-enable]; also
see [break$].
Fixed a soundness bug that was allowing unknown packages to sneak
into a book and wreak havoc. Thanks to Peter Dillinger for sending
an interesting example that led us to an exploration resulting in
finding this bug. (A comment in the source code for note-3-2 shows
such an example.) That example led us to fix a couple of other bugs
related to packages. See [hidden-death-package] if you are
generally interested in such issues, and for associated examples,
see comments in note-3-2 in the ACL2 source code.
Fixed subtle soundness bugs related to :[meta] rules by restricting
evaluators (see [defevaluator]), as discussed in a new
documentation topic: see [evaluator-restrictions].
Fixed a soundness bug that was allowing redefinition from :[logic] to
:[program] mode. This prohibition had been in ACL2 for awhile but
was accidentally removed in the preceding version.
Fixed a soundness bug related to [trace$]. Thanks to Peter Dillinger
for bringing it to our attention and for useful discussions, and
providing a proof of nil, the essence of which is illustrated as
follows:
(value-triple (trace$ (bar :entry (defun foo () 17))))
Thus, [trace$] could be used to cause destructive raw Lisp behavior.
Now, trace$ fails unless it is either given a list of symbols or
else there is an active trust tag (see [defttag]); otherwise,
consider using trace! instead.
Closed a loophole that could be viewed as compromising soundness. It
was possible to write files during book certification by exploiting
[make-event] expansion, but that is no longer the case by default.
A new function [open-output-channel!] is identical as a function to
open-output-channel, except that the new function may be called
even during [make-event] expansion and [clause-processor] [hints],
but requires that there is an active trust tag (see [defttag]).
Thanks to Peter Dillinger for producing a convincing example
(forging a [certificate] during book certification; see
[open-output-channel!]) and to him, Sandip Ray, and Jared Davis for
useful discussions on the topic.
Added book books/defexec/reflexive/reflexive.lisp to illustrate
reflexive functions.
ACL2 now generate scripts that invoke the saved image with exec.
(Previously this was only done for GCL and CLISP.) The benefit of
this change can be to avoid the lingering of ACL2 processes after
enclosing processes have exited. Thanks to Peter Dillinger for
pointing out this issue.
ACL2 has a better implementation of ([good-bye]) (hence of synonyms
([quit]) and ([exit])). As a result, you should now be able to exit
ACL2 and Lisp from within the ACL2 read-eval-print loop with any of
the above; formerly, this was not supported for some Lisp
implementations, and was slow in OpenMCL. Thanks to SBCL developer
Harald Hanche-Olsen for useful advice.
Fixed a bug in raw-mode (see [set-raw-mode]) that was causing hard
errors when evaluating calls of [er-progn], or of macros expanding
to such calls.
Fixed a few Makefile dependencies, necessary only for parallel
`make'.
A new book, misc/defpun-exec-domain-example.lisp, provides an example
showing how partial functions which return a unique value for
arguments in a specified domain can be efficiently executed with
ACL2. Execution is achieved using the [mbe] construct. Thanks to
Sandip Ray for providing this example.
Existing function [mod-expt] computes (mod (expt base exp) mod) with
great efficiency in GCL, but not in other Lisps. Now, the book
arithmetic-3/floor-mod/mod-expt-fast.lisp defines a function
mod-expt-fast that should provide significantly improved
performance for such expressions in other Lisps as well, though
still probably not as fast as when using mod-expt in GCL. Thanks to
Warren Hunt, with contributions from Robert Krug, for providing
this book,
Modified macro [break-on-error] to print of an error message before
entering a break, and to cause a hard error if the underlying Lisp
cannot handle it (formerly, a raw Lisp break would occur). Thanks
to Bob Boyer for bringing these issues to our attention.
The book books/misc/defpun.lisp, as well as other books related to
the defpun macro, has been modified to avoid namespace collisions
by prefixing function symbol names with \"DEFPUN-\"; for example base
has been replaced by defpun-base. Thanks to Dave Greve for
providing a first version of this update to defpun.lisp.
A theory, base, in books/arithmetic-3/bind-free/top.lisp, has been
renamed arithmetic-3-bind-free-base, to avoid potential name
conflicts.
Fixed books/arithmetic-3/bind-free/banner.lisp to print (as before) a
message about how to turn on non-linear arithmetic, by modifying
the call of value-triple to use :on-skip-proofs t. Thanks to Robert
Krug for bringing this issue to our attention.
Modified books/Makefile-subdirs and books/Makefile-psubdirs so that
they can be used with books/Makefile-generic. Thus, one can set
things up so that `make' can be used to certify books both in the
current directory and subdirectories, for example as follows.
ACL2 = ../../saved_acl2
arith-top: top all
all: top
DIRS = pass1 bind-free floor-mod
include ../Makefile-subdirs
include ../Makefile-generic
top.cert: top.lisp
top.cert: bind-free/top.cert
top.cert: floor-mod/floor-mod.cert
top.cert: floor-mod/mod-expt-fast.cert
An experimental extension of ACL2 is under development by Bob Boyer
and Warren Hunt to support function memoization, hash conses, and
an applicative version of hash tables. The default build of ACL2
does not include this extension, other than simple logic
definitions of functions in new source file hons.lisp. Future
versions of ACL2 may fully incorporate this experimental extension.
The [defevaluator] event macro has been modified primarily by adding
a new constraint as follows, where evl is the evaluator. The idea
is that for the evaluation of a function call, one may replace each
argument by the quotation of its evaluation and then also replace
the alist environment with nil.
(DEFTHMD UNHIDE-evl-CONSTRAINT-0
(IMPLIES (AND (CONSP X)
(SYNTAXP (NOT (EQUAL A ''NIL)))
(NOT (EQUAL (CAR X) 'QUOTE)))
(EQUAL (evl X A)
(evl (CONS (CAR X)
(KWOTE-LST (UNHIDE-evl-LIST (CDR X) A)))
NIL))))
In order to support this change, there is another change: an
evaluator maps nil to nil (note (AND X (CDR (ASSOC-EQ X A))) in
place of (CDR (ASSOC-EQ X A)) below).
(DEFTHM UNHIDE-evl-CONSTRAINT-1
(IMPLIES (SYMBOLP X)
(EQUAL (UNHIDE-evl X A)
(AND X (CDR (ASSOC-EQ X A))))))
With the new [defevaluator], Dave Greve has been able to do a proof
about beta reduction that seemed impossible before (see
books/misc/beta-reduce.lisp). Thanks to Dave for suggesting an
initial version of this change.
Explicit compilation is now avoided for OpenMCL, resulting in fewer
files to manage (no more files resulting from compilation) and,
according to some tests, slightly faster run times. See
[compilation]. Thanks to Bob Boyer and Warren Hunt for suggesting
this possibility.
Now, the term-evisc-tuple (see [ld-evisc-tuple]) is overridden by
state global user-term-evisc-tuple in all cases. Formerly, this was
only the case when term-evisc-tuple was called with non-nil first
argument.
Symbols with the dot (.) character are generally no longer printed
with vertical bars. For example, before this change:
ACL2 !>'ab.c
|AB.C|
ACL2 !>
After this change:
ACL2 !>'ab.c
AB.C
ACL2 !>
Thanks to Jared Davis for suggesting this improvement.
Fixed bugs in guard verification for theorems. The following examples
illustrate these bugs. If either theorem's body is executed in raw
Lisp there is likely to be a hard Lisp error, even though
[verify-guards] was supposed to ensure against that behavior.
; Example: Verify-guards failed to check that all functions in the theorem
; had already been guard-verified.
(defun my-car (x) (car x))
(defthm my-car-compute-example (equal (my-car 3) (my-car 3)))
(verify-guards my-car-compute-example)
; Example: Verify guards of a theorem whose body uses state improperly.
(defthm bad-state-handler
(if (state-p state)
(equal (car state) (car state))
t)
:rule-classes nil)
(verify-guards bad-state-handler)
See [gcl] for an example, developed with Warren Hunt and Serita
Nelesen, that shows how to get fast fixnum (small integer)
arithmetic operations in GCL.
Fixnum declarations are now realized as (signed-byte 30) and
(unsigned-byte 29) instead of what was generally (signed-byte 29)
and (unsigned-byte 28). MCL users may thus find better performance
if they switch to OpenMCL. Note that some definitions have changed
correspondingly; for example, [zpf] now [declare]s its argument to
be of type (unsigned-byte 29) instead of (unsigned-byte 28). A few
[books] may thus need to be adjusted; for example, changes were
made to books in books/data-structures/memories/.
ACL2's rewriter now avoids removing certain true hypotheses and false
conclusions. When a hypothesis rewrites to true or a conclusion
rewrites to false, ACL2 formerly removed that hypothesis or
conclusion. Now, it only does such removal when the hypothesis or
conclusion is either a call of [equal] or an equivalence relation
(see [equivalence]), or else is sufficiently trivial (roughly,
either redundant with another hypothesis or conclusion or else
trivially true without considering the rest of the goal). A
specific example may be found in source file simplify.lisp; search
for ``; But we need to do even more work''. Thanks to Robert Krug
for providing the idea for this improvement and its initial
implementation. As is common with heuristic changes, you may find
it necessary on occasion to rename some subgoals in your [hints].
And in this case, you might also find it necessary on rare
occasions to add :do-not '(generalize) [hints].
A new function, mfc-relieve-hyp, allows (for example) for more
powerful [bind-free] hypotheses, by providing an interface to the
rewriter's routine for relieving hypotheses. See
[extended-metafunctions]. Thanks to Robert Krug for providing the
idea for this feature and its initial implementation.
Two improvements have been made to non-linear arithmetic (see
[non-linear-arithmetic]). One allows for deducing strict inequality
(<) for the result of certain polynomial multiplications, where
previously only non-strict inequality (<=) was deduced. A second
allows the use of the product of two polynomials when at least one
of them is known to be rational. We had previously restricted the
use of the product to the case where both were known to be
rational. Thanks to Robert Krug for these improvements.
(OpenMCL and Allegro CL only) Fixed ACL2's redefinitions of raw Lisp
trace and untrace in OpenMCL and Allegro CL so that when given no
arguments, they return the list of traced functions. For trace,
this is an ANSI spec requirement. Note that [trace$] and [untrace$]
continue to return nil in the ACL2 loop.
Fixed a bug that was allowing the symbol &whole to appear in other
than the first argument position for a [defmacro] event, in
violation of the Common Lisp spec (and leading to potentially
surprising behavior). Thanks to Peter Dillinger for bringing this
bug to our attention.
It had been illegal to use [make-event] under some calls of [ld].
This has been fixed. Thanks to Jared Davis for bringing this issue
to our attention with a simple example, in essence:
(ld '((defmacro my-defun (&rest args) `(make-event '(defun ,@args)))
(my-defun f (x) x)))
ACL2 no longer prohibits certain [make-event] forms when including
uncertified [books]. Thanks to Peter Dillinger for first bringing
this issue to our attention.
Hard errors arose when using [break-rewrite] stack display commands,
in particular :path and :frame, from inside the [proof-checker].
This has been fixed.
Fixed a bug that could cause functions that call system built-ins
f-put-global, f-get-global, or f-boundp-global to cause a raw Lisp
error even when proving theorems. Thanks to Peter Dillinger, for
reporting such a failure for the form (thm (w '(1 2 3))).
Renamed the formal parameters of function set-equal in distributed
book books/arithmetic-3/bind-free/normalize.lisp so that more
distributed books can be included together in the same session. In
particular books books/data-structures/set-theory and
books/arithmetic-3/extra/top-ext can now be included together.
Thanks to Carl Eastlund for bringing this problem to our attention
and to Robert Krug for suggesting the formals renaming as a fix.
Metafunctions must now be executable. See [meta].
New utilities allow for user-defined simplifiers at the goal level,
both verified and unverified (``trusted''), where the latter can
even be defined by programs outside ACL2. See [clause-processor],
which points to a new directory books/clause-processors/ that
contains examples of these new utilities, including for example a
system (``SULFA'') contributed by Erik Reeber that implements a
decision procedure (thanks, Erik). Also see
[proof-checker-commands] for the new [proof-checker] command
clause-processor (or for short, cl-proc).
The rewriter has been tweaked to run faster in some cases involving
very large terms. Thanks to Eric Smith and Jared Davis for
providing a helpful example that helped us locate the source of
this inefficiency.
Added books/make-event/defspec.lisp. This book shows how one can
mimic certain limited forms of higher-order statements in ACL2 by
use of macros, [make-event], and [table] events. Thanks to Sandip
Ray for his contribution.
A new release of the RTL library, books/rtl/rel7/, replaces the
previous version, books/rtl/rel6/. Thanks to Hanbing Liu and David
Russinoff for providing this new version.
We thank David Russinoff for providing a proof of the law of
quadratic reciprocity. See books/quadratic-reciprocity/Readme.lsp.
Eliminated a slow array warning (see [slow-array-warning]) that could
occur when exiting a [wormhole] after executing an [in-theory]
event in that wormhole. Thanks to Dave Greve for bringing this
problem to our attention.
A new accessor, (mfc-rdepth mfc), provides a new field, the remaining
rewrite stack depth, which has been added to metafunction context
structures; see [extended-metafunctions]. Thanks to Eric Smith for
suggesting this addition.
The algorithms were modified for collecting up rule names and other
information used in proofs, into so-called ``tag-trees''. Tag-trees
are now free of duplicate objects, and this change can dramatically
speed up some proofs that involve many different rules. Thanks to
Eric Smith for doing some profiling that brought this issue to our
attention, and for reporting that this change reduced proof time on
an example by about 47% (from 3681.46 reported seconds down to
1954.69).
All legal xargs keywords may now be used in [verify-termination]
[events]. In particular, this is the case for :normalize.
(SBCL and CMUCL only) Fixed a problem with stobj array resizing
functions that was causing a hard error in ACL2 images built on
SBCL or CMUCL.
A new [table], [evisc-table], allows you to introduce print
abbreviations, for example for large constants. Moreover, a new
reader macro --- #, --- makes it convenient to reference constants
even inside a quote. See [evisc-table]. Thanks to Bob Boyer and
Warren Hunt for useful discussions leading to this feature.
The macros in books/misc/expander.lisp now have a new keyword
argument, :simplify-hyps-p. The default behavior is as before, but
now case splitting from hypothesis simplification can be avoided.
For details, evaluate (include-book \"misc/expander\" :dir :system)
and then :doc! defthm? and :doc! symsym. Thanks to Daron Vroon for
sending a question that prompted this additional functionality.
ACL2 failed to apply :[restrict] hints to rules of class
:[definition], except for the simplest sorts (see [simple]). This
has been fixed. Thanks to Jared Davis for pointing out this bug by
sending a small example.
Added a new :msg argument to assert-event; see [assert-event]. The
implementation of value-triple has been modified to support this
change.
Fixed a bug in macro io? that now allows the commentp argument to be
t. This provides a way other than cw to print without modifying
state, for example as follows. (Warning: Certain errors may leave
you in a [wormhole], in which case use :a! to abort.)
ACL2 !>(prog2$ (io? event t state
()
(fms \"Howdy~%\" nil *standard-co* state nil))
(+ 3 4))
Howdy
7
ACL2 !>:set-inhibit-output-lst (proof-tree event)
(PROOF-TREE EVENT)
ACL2 !>(prog2$ (io? event t state
()
(fms \"Howdy~%\" nil *standard-co* state nil))
(+ 3 4))
7
ACL2 !>
ACL2 now disallows calls of [progn!] inside function bodies, just as
it already disallowed such calls of [progn], since in both cases
the Common Lisp meaning differs from the ACL2 meaning.
Redefinition of system functions now always requires an active trust
tag (see [defttag]). This restriction was intended before, but
there was a hole that allowed a second redefinition without an
active trust tag. Thanks to Peter Dillinger for pointing out this
bug.
[Verify-termination] has been disabled for a few more built-in
functions that are in :[program] mode. (If you are curious about
which ones they are, evaluate (f-get-global
'built-in-program-mode-fns state).) [Note added for Version_3.4:
This state global has been changed to 'program-fns-with-raw-code.]
Moreover, such functions now will execute only their raw Lisp code,
so for example they cannot be called during macroexpansion. Thanks
to Peter Dillinger and Sandip Ray for useful discussions on details
of the implementation of this restriction.
New untouchable state global variables, temp-touchable-vars and
temp-touchable-fns, can control the enforcement of untouchability.
See [remove-untouchable]. Thanks to Peter Dillinger for suggesting
these features.
The ``TTAG NOTE'' string was being printed by [encapsulate] events
whenever an active trust tag was already in effect (see [defttag]),
even if the encapsulate event contained no [defttag] event. This
has been fixed. Thanks to Peter Dillinger for a query leading to
this fix.
Fixed a bug in [progn!] that could leave the user in raw-mode (see
[set-raw-mode]). This could occur when certifying a book with a
compile-flg value of t (see [certify-book]), when that book
contained a [progn!] event setting raw-mode to t without setting
raw-mode back to nil:
(progn! (set-raw-mode t) ...)")
(NOTE-3-2-1
(RELEASE-NOTES)
"ACL2 Version 3.2.1 (June, 2007) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
(OpenMCL and multi-threaded SBCL only) Fixed a soundness bug in the
evaluation of [mbe] forms in the presence of Lisp feature
:acl2-mv-as-values. Thanks to Sol Swords for reporting this problem
and sending a simple proof of nil (which can be found in a comment
in the ACL2 sources, in (deflabel note-3-2-1 ...)).
Added a new utility, [dmr] (Dynamicaly Monitor Rewrites), for
watching the activity of the rewriter and some other proof
processes. See [dmr]. We thank Robert Krug for useful
contributions.
Fixed a bug in evaluation of calls of [with-prover-time-limit].
Fixed the writing of executable scripts when building ACL2, so that
the build-time value of environment variable ACL2_SYSTEM_BOOKS is
no longer written there. Thanks to Dave Greve for discussing this
change.
Fixed bugs in :[pl] (which are similarly present in the
[proof-checker]'s sr (show-rewrites) command. The first bug was
evident from the following forms sent by Robert Krug, which caused
an error.
(include-book \"arithmetic-3/floor-mod/floor-mod\" :dir :system)
:pl (mod (+ 1 x) n)
The second bug was due to a failure to take note of which rules are
disabled, and could be seen by executing the following (very
slow!).
(defstub modulus () t)
(include-book \"arithmetic-3/floor-mod/floor-mod\" :dir :system)
:pl (mod (+ x y) (modulus))
Modified [certify-book] so that by default, all
executable-counterpart functions (sometimes called ``*1*
functions'') are compiled. This is the behavior that was already
supported with a compile-flg argument of :all; the change is that
argument t now has this behavior as well (and :all is supported
only for legacy purposes). A new value for compile-flg, :raw, gives
the behavior formerly produced by value t, namely where
executable-counterpart functions are not compiled. The above
changes are irrelevant if compilation is suppressed; see
[compilation]. Finally, if environment variable ACL2_COMPILE_FLG is
set, then after converting to upper-case this environment
variable's value of \"T\", \"NIL\", or \":RAW\" will determine the value
of the optional compile-flg argument to be t, nil, or :raw,
respectively, when this argument is not explicitly supplied.
Modified [include-book] so that :comp argument now acts like :comp!,
i.e., compiling a file that includes the file together with all
executable counterpart (so-called ``*1*'') functions. A new
argument, :comp-raw, has the behavior that :comp had formerly,
i.e., compiling the actual book only.
The function [nonnegative-integer-quotient] is now computed in raw
Lisp by calling [floor] on its arguments. This change was suggested
by Peter Dillinger, in order to avoid stack overflows such as
reported by Daron Vroon. A new book, books/misc/misc2/misc.lisp,
contains a proof of equivalence of [nonnegative-integer-quotient]
and [floor], and serves as a repository for other miscellaeous
proofs, including those justifying ACL2 modifications such as this
one.
Enhanced [accumulated-persistence] to break down results by useful
vs. useless rule applications. In particular, this provides
information about which rules were ever applied successfully, as
requested by Bill Young.
Added coverage of :[meta] rules to the [accumulated-persistence]
statistics.
Fixed a bug that was causing a :[clause-processor] hint to fire on a
subgoal of the goal to which it was attached, when the original
application didn't change the clause. Thanks to Dave Greve for
pointing out this bug and providing a useful example.
Fixed a bug in handling of computed [hints] related to the
stable-under-simplificationp parameter (see [computed-hints]).
There were actually two bugs. A minor but confusing bug was that
the same goal was printed twice upon application of such a hint.
The major bug was that :use [hints] (as well as other ``top''
hints: :by, :cases, and :clause-processor) were not being applied
properly. Thanks to Jared Davis for sending an example some time
ago that showed the duplicate printing, and to Dave Greve for
sending an example showing mis-application of :[clause-processor]
[hints]. Note that you may find that existing computed hints using
the stable-under-simplificationp parameter no longer have the same
behavior; see a comment about computed hints in note-3-2-1, ACL2
source file ld.lisp, for an example of how you might want to fix
such computed hints.
David Russinoff has contributed an updated version of
books/quadratic-reciprocity/ including minor modifications of the
treatment of prime numbers and a proof that there exist infinitely
many primes. Thanks to David for contributing this work, and to
Jose Luis Ruiz-Reina for posing the challenge.
Reduced the sizes of some [certificate] (.cert) files by relaxing the
test that allows original [defpkg] [events] to be placed there,
rather than evaluating the import list term into an explicit list
of symbols.
Improved execution efficiency slightly for function rcdp in file
books/misc/records.lisp, by using [mbe] to introduce a
tail-recursive body.
The executable script generated by [save-exec] (and by the normal
build process) now includes a time stamp as a comment. Thanks to
Jared Davis for suggesting this change in order to support his use
of omake. In the process, we also arranged that the startup banner
for an executable created by [save-exec] shows all of the build
(save) times, not just the one for the original image.
Sped up most redundant [defpkg] [events] by avoiding evaluation and
sorting of the imports list in the case of identical event forms.
And, for [defpkg] events that are not redundant, sped up their
processing in Allegro CL (and perhaps other Lisps, but apparently
not GCL) by using our own import function.
Modified [add-include-book-dir] so that it refuses to associate a
keyword with a different directory string than one it is already
bound to. See [delete-include-book-dir] for how to remove the
existing binding first. Thanks to Robert Krug for pointing out that
without this change, one can find it difficult to debug a failure
due to rebinding a keyword with [add-include-book-dir].
Added a new value for the :do-not-induct hint (see [hints]),
:otf-flg-override, which causes ACL2 to ignore the :[otf-flg] when
considering whether to abort the proof because of a :do-not-induct
hint. Thanks to Daron Vroon for suggesting such an addition.
Modified the printing of messages for entering and exiting raw mode
(see [set-raw-mode]), so that in particular they are inhibited
during [include-book] or whenever observations are inhibited (see
[set-inhibit-output-lst]). Thanks to Peter Dillinger for suggesting
such a change.
(For system hackers only.) The handling of [events] of the form
(progn! (state-global-let* ...)) had a bug that was causing
bindings to be evaluated twice. Moreover, the use of system
function [state-global-let*] is suspect in raw Lisp. We have
eliminated special treatment of state-global-let* by progn! in
favor of a new keyword argument, state-global-bindings, that
provides the intended functionality. See [progn!]. Moreover,
special handling that allowed [make-event] forms under
state-global-let* has been removed; the desired effect can be
obtained using (progn! :state-global-bindings ...). Thanks to Peter
Dillinger for pointing out the above bug and collaborating on these
changes.
Incorporated backward-compatible enhancements to
books/misc/expander.lisp from Daron Vroon (documented near the top
of that file).
The specification of :backchain-limit-lst had required that only a
single (:[rewrite], :[linear], or :[meta]) rule be generated. We
have weakened this restriction to allow more than one rule provided
that each rule has the same list of hypotheses. For example, the
rule class (:rewrite :backchain-limit-lst 1) is now legal for the
corollary formula (implies (f x) (and (g x) (h x))), where this was
not formerly the case. Thanks to Dave Greve for bringing this issue
to our attention.")
(NOTE-3-2-1{R}
(RELEASE-NOTES)
"ACL2 Version 3.2.1(r) (June, 2007) Notes
Please also see [note-3-2-1] for changes to Version 3.2.1 of ACL2.")
(NOTE-3-2{R}
(RELEASE-NOTES)
"ACL2 Version 3.2(r) (April, 2007) Notes
Changed the default distributed [books] directory for ACL2(r) from
books/ to books/nonstd/. See [include-book], in particular the
discussion of ``Distributed Books Directory''.
Added directory books/arithmetic-3/ and its subdirectories to
books/nonstd/. (But a chunk of theorems from
arithmetic-3/extra/ext.lisp are ``commented out'' using
#-:non-standard-analysis because they depend on books/rtl/rel7/,
which is not yet in books/nonstd/; feel free to volunteer to remedy
this!)
Incorporated changes from Ruben Gamboa to some (linear and
non-linear) arithmetic routines in the theorem prover, to
comprehend the reals rather than only the rationals.
Please also see [note-3-2] for changes to Version 3.2 of ACL2.")
(NOTE-3-3
(RELEASE-NOTES)
"ACL2 Version 3.3 (November, 2007) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 3.2.1 into new
features, bug fixes, prover algorithm enhancements, and
miscellaneous. Also see [note-3-2-1] for other changes since
Version 3.2.
NEW FEATURES
A new ``gag-mode'' provides less verbose, more helpful feedback from
the theorem prover, in support of The Method (see [the-method]).
See [set-gag-mode]. We recommend the use of gag-mode, which may
become the default in future ACL2 releases, and we welcome
suggestions for improvement. We thank Robert Krug and Sandip Ray
for helpful feedback in the design of [gag-mode]. Note that when
proofs fail, then even without gag-mode and even if proof output is
inhibited, the summary will contain a useful listing of so-called
``key checkpoints'' (see [set-gag-mode]).
Added support for a leading `~' in filenames. Thanks to Bob Boyer for
suggesting this enhancement. Note that since `~/' depends on the
user, it is disallowed in [books] to be certified (see
[certify-book]), since otherwise an [include-book] form in a book,
b, could have a different meaning at certification time than at the
time [include-book] is later executed on book b.
Made a change to allow (time$ FORM) and (with-prover-time-limit TIME
FORM) when FORM includes [make-event] calls that change the ACL2
[world]. Thanks to Jared Davis for requesting such support for
[time$].
Computed [hints] (see [computed-hints]) may now produce a so-called
``error triple'', i.e., a result of the form (mv erp val state),
where a non-nil erp causes an error, and otherwise val is the value
of the hint. It remains legal for a computed hint to return a
single ordinary value; indeed, the symbol form of a computed hint
must still be a function that returns an ordinary single value.
New hints provide additional control of the theorem prover, as
follows. See [hints] for more details, and see new distributed book
directory books/hints/ for examples, in particular file
basic-tests.lisp in that directory for simple examples.
o The hint :OR (hints-1 ... hints-k) causes an attempt to prove the
specified goal using each hints-i in turn, until the first of
these succeeds. If none succeeds, then the prover proceeds
after heuristically choosing the ``best'' result, taking into
account the goals pushed in each case for proof by induction.
o A custom hint is a keyword that the user associates with a
corresponding hint-generating function by invoking
[add-custom-keyword-hint]. Thus, a custom hint may be viewed as
a convenient sort of computed hint.
o A custom hint, :MERGE, is implemented in distributed book
books/hints/merge.lisp. It is useful for combining hints.
o A sophisticated yet useful custom hint is the :CONSIDER hint
implemented in distributed book books/hints/consider-hint.lisp.
With this hint, you can for example give the equivalent of a
:USE hint without the need to supply an instantiation. Include
that book in order to see documentation online with :doc
consideration, and see the book
books/hints/consider-hint-tests.lisp for examples.
A new hint, :[reorder], allows the specification of which subgoals
are to be considered first. Thanks to Sandip Ray for putting
forward this idea.
Enhanced [set-saved-output] by supporting a second argument of :same,
which avoids changing which output is inhibited.
Added macros thm? and not-thm? to distributed book
books/make-event/eval.lisp, so that it's easy to test within a
certified book that a proof attempt succeeds or that it fails.
Added printing function [cw!], which is analogous to [cw] just as
[fmt!] is to [fmt], i.e., printing so that the result can be read
back in. Thanks to Jared Davis for suggesting this enhancement
(after doing his own implementation).
The ACL2 customization file can now be specified using environment
variable ACL2-CUSTOMIZATION [note: starting with Version_4.0,
ACL2_CUSTOMIZATION]. See [ACL2-customization]. Thanks to Peter
Dillinger for requesting this feature.
Added new emacs capabilities for proof trees (all documented in
emacs):
o New function start-proof-tree-noninteractive, for example
(start-proof-tree-noninteractive \"*shell*\")
o C-z o Switch to another frame
o C-z b Switch to prooftree buffer
o C-z B Switch to prooftree buffer in \"prooftree-frame\" frame
Added Common Lisp function, search, as a macro in [logic] mode, with
limited support for keyword arguments. Thanks to Warren Hunt for
requesting this addition.
Sandip Ray has contributed a book, books/make-event/defrefine.lisp,
that provides a collection of macros to aid in reasoning about ACL2
functions via refinement.
Wrote and incorporated new utility for listing all the theorems in an
included book. See books/misc/book-thms.lisp. Thanks to Jared Davis
for requesting this functionality.
The new distributed book misc/defp.lisp generalizes the [defpun]
macro to allow more general forms of tail recursion.
(Low-level printing improvement) A new function,
set-ppr-flat-right-margin, allows the right margin for certain
kinds of ``flat'' printing to exceed column 40. Thanks to Jared
Davis for pointing out that state global variables
'fmt-hard-right-margin and 'fmt-soft-right-margin are not alone
sufficient to extend the right margin in all cases.
The event [add-include-book-dir] can now take a relative pathname as
an argument. Formerly, it required an absolute pathname.
A new book, books/misc/defopener.lisp, provides a utility creating a
theorem that equates a term with its simplification.
ACL2 now provides limited support for the Common Lisp primitive FLET,
which supports local function bindings. See [flet]. Thanks to
Warren Hunt for requesting this feature.
Added a definition of [boole$], a close analogue of Common Lisp
function boole. Thanks to Bob Boyer for providing an initial
implementation.
BUG FIXES
Fixed [defstobj] to inhibit a potentially useless theory warning.
Fixed a bug in the application of [certify-book] to relative
pathnames for files in other than the current directory. Thanks to
Amr Helmy for bringing this bug to our attention.
Fixed a bug in :[pl] and :[pr] for displaying rules of class :[meta].
Thanks to Jared Davis for finding this bug and providing a fix.
Formerly, [set-default-backchain-limit] was not a legal event form
for [encapsulate] forms and [books]. This has been fixed. Thanks to
Robert Krug and Sandip Ray for bringing this bug to our attention.
Fixed the handling of [hints] in [proof-checker] commands for the
prover, such as bash --- see [proof-checker-commands] --- so that
the user can override the default settings of hints, in particular
of :do-not and :do-not-induct hints attached to \"Goal\". This fix
also applies to the distributed book misc/bash.lisp, where Robert
Krug noticed that he got an error with :hints ((\"Goal\" :do-not
'(preprocess))); we thank Robert for pointing out this problem.
Fixed a bug in handling of [stobj]s occurring in guards of functions
whose [guard]s have been verified. In such cases, a raw Lisp error
was possible when proving theorems about non-''live'' [stobj]s. We
thank Daron Vroon for sending us an example that highlighted this
bug. The following (simpler) example causes such an error in
previous versions of ACL2.
(defstobj st fld)
(defun foo (st)
(declare (xargs :stobjs st :guard (fld st)))
st)
(thm (equal (foo '(3))
'(3)))
The [dmr] feature for dynamic monitoring of rewrites had a bug, where
the file used for communicating with emacs was the same for all
users, based on who built the ACL2 executable image. This has been
fixed. Thanks to Robert Krug for bringing this bug to our
attention.
Fixed a bug in some warnings, in particular the warning for including
an uncertified book, that was giving an incorrect warning summary
string.
Inclusion of uncertified books erroneously re-used [make-event]
expansions that were stored in stale [certificate]s. This is no
longer the case. Thanks to Jared Davis for bringing this bug to our
attention.
Fixed a bug that was disallowing calls of [with-output] in [events]
that were executing before calling [certify-book].
Modified the functionality of binop-table so other than binary
function symbols are properly supported (hence with no action based
on right-associated arguments). See [add-binop].
Fixed small [proof-checker] issues related to packages. Emacs
commands ctrl-t d and ctrl-t ctrl-d now work properly with colon
(`:') and certain other punctuation characters. The p-top command
now prints ``***'' regardless of the current package.
Fixed a bug that allowed [certify-book] to succeed without specifying
value t for keyword argument :skip-proofs-okp, even with
[include-book] [events] in the certification [world] depending on
events executed under [skip-proofs].
Improved [show-accumulated-persistence] in the following two ways.
Thanks to Robert Krug and Bill Young for requesting these
improvements and for providing useful feedback.
o It can provide more complete information when aborting a proof.
o The :frames reported for a rule are categorized as ``useful'' and
``useless'' according to whether they support ``useful'' or
``useless'' :tries of that rule, respectively. See
[accumulated-persistence] for further explanation.
Modified [make-event] so that the reported time and warnings include
those from the expansion phase. In analogy with [encapsulate] and
[progn], the rules reported still do not include those from
subsidiary events (including the expansion phase). A related change
to [ld] avoids resetting summary information (time, warnings) with
each top-level form evaluation; [events] already handle this
information themselves.
Fixed [set-inhibit-output-lst] so that all warnings are inhibited
when warning! but not warning is included in the list. Formerly,
only soundness-related warnings were inhibited in this case. Thanks
to Eric Smith for bringing this bug to our attention.
Distributed directory doc/HTML/ now again includes installation
instructions (which was missing in Version_3.2.1), in
doc/HTML/installation/installation.html.
Some fixes have been made for [proof-tree] support.
o [Proof-tree] output is no longer inhibited automatically during
[certify-book], though it continues to be inhibited by default
(i.e., ACL2 continues to start up as though
[set-inhibit-output-lst] has been called with argument
'(proof-tree)).
o Fixed a bug in Xemacs support for [proof-tree] help keys C-z h and
C-z ?.
o Fixed a bug in [proof-tree]s that was failing to deal with the case
that a goal pushed for proof by induction is subsumed by such a
goal to be proved later. Now, the proof-tree display regards
such subsumed goals as proved, as is reported in the theorem
prover's output.
Fixed a bug that was disallowing [value-triple] forms inside
[encapsulate] forms in a certification [world] (see [portcullis]).
If the :load-compiled-file argument of a call of [include-book] is
:comp, then an existing compiled file will be loaded, provided it
is more recent than the corresponding book (i.e., .lisp file). A
bug was causing the compiled file to be deleted and then
reconstructed in the case of :comp, where this behavior was
intended only for :comp!.
Fixed a bug that was avoiding compilation of some executable
counterparts (sometimes called ``*1* functions'') during
[certify-book], and also during [include-book] with
:load-compiled-file value of :comp or :comp!). Thanks to Eric Smith
for sending a small example to bring this bug to our attention.
Incorporated a fix from Eric Smith for a typo (source function
ancestors-check1) that could cause hard Lisp errors. Thanks, Eric!
Fixed the following issues with packages and book [certificate]s. See
[hidden-death-package] if you are generally interested in such
issues, and for associated examples, see comments on ``Fixed the
following issues with packages'' in note-3-3 in the ACL2 source
code.
o Reduced the size of .cert files by eliminating some unnecessary
[defpkg] events generated for the [portcullis].
o Fixed a bug that has caused errors when reading symbols from a
[portcullis] that are in undefined packages defined in locally
included books.
o Fixed a bug that could lead to failure of [include-book] caused by
a subtle interaction between [set-ignore-ok] and [defpkg]
events generated for the [portcullis] of a [certificate].
PROVER ALGORITHM ENHANCEMENTS
Non-linear arithmetic (see [non-linear-arithmetic]) has been improved
to be more efficient or more powerful in some cases. Thanks to
Robert Krug for contributing these improvements.
Improved certain (so-called ``[type-set]'') reasoning about whether
or not expressions denote integers. Thanks to Robert Krug for
contributing code to implement this change, along with examples
illustrating its power that are now distributed in the book
books/misc/integer-type-set-test.lisp.
Improved ACL2's heuristics for relieving hypotheses, primarily to use
linear reasoning on conjuncts and disjuncts of the test of an [if]
expression. For example, given a hypothesis of the form (if (or
term1 term2) ...), ACL2 will now use linear reasoning to attempt to
prove both term1 and term2, not merely for term2. Thanks to Robert
Krug for supplying examples illustrating the desirability of such
an improvement and for useful discussions about the fix.
Made a slight heuristic change, so that when a hypothesis with [let]
or [mv-let] subterms (i.e. [lambda] subterms) rewrites to t, then
that hypothesis is necessarily eliminated. Thanks to Jared Davis
for sending an example that led us to develop this change, and
thanks to Robert Krug for a helpful discussion.
MISCELLANEOUS
Added documentation on how to use [make-event] to avoid duplicating
expensive computations, thanks to Jared Davis. See
[using-tables-efficiently].
Modified the error message for calls of undefined functions to show
the arguments. Thanks to Bob Boyer for requesting this enhancement.
Modified utilies :[pr], :[pr!], :[pl], and :[show-bodies] to
incorporate code contributed by Jared Davis. That code defines
low-level source functions info-for-xxx that collect information
about rules, which is thus available to advanced users.
Dynamic monitoring of rewrites (see [dmr]) has been improved in the
following ways, as suggested by Robert Krug.
o Some stale entries from the rewrite stack are no longer printed, in
particular above ADD-POLYNOMIAL-INEQUALITIES.
o An additional rewrite stack entry is made when entering non-linear
arithmetic (see [non-linear-arithmetic]).
o An ADD-POLYNOMIAL-INEQUALITIES entry is printed with a counter, to
show how often this process is called.
Modified [save-exec] so that the newly-saved image will have the same
raw Lisp package as the existing saved image. This is a very
technical change that will likely not impact most users; for
example, the package in the ACL2 read-eval-print loop (see [lp])
had already persisted from the original to newly-saved image.
Thanks to Jared Davis for suggesting this change.
Changed [make-event] expansion so that changes to [set-saved-output],
[set-print-clause-ids], set-fmt-soft-right-margin, and
set-fmt-hard-right-margin will persist after being evaluated during
make-event expansion. (Specifically,
*protected-system-state-globals* has been modified; see
[make-event-details].) Thanks to Jared Davis for bringing this
issue to our attention.
Output from the [proof-checker] is now always enabled when invoking
[verify], even if it is globally inhibited (see
[set-inhibit-output-lst]).
Improved the message printed when an :induct hint fails, to give more
information in some cases. Thanks to Rex Page for suggesting where
an improvement could be made and providing useful feedback on an
initial improvement.
Added a warning for [congruence] rules (see [defcong]) that specify
[iff] as the second equivalence relation when [equal] can be used
instead. Those who heed these warnings can eliminate certain
subsequent [double-rewrite] warnings for [rewrite] rules with
conclusions of the form (iff term1 term2), and hence implicitly for
Boolean conclusions term1 that are interpreted as (iff term1 t).
Thanks to Sarah Weissman for sending us an example that highlighted
the need for such a warning.
Modified macro :[redef!] (which is for system implementors) so that
it eliminates untouchables.
Several improvements have been made to the experimental
hons/memoization version of ACL2. See [hons-and-memoization].
The distributed books directory, (@ distributed-books-dir), is now
printed in the start-up message.")
(NOTE-3-3{R}
(RELEASE-NOTES)
"ACL2 Version 3.3(r) (November, 2007) Notes
Please also see [note-3-3] for changes to Version 3.3 of ACL2.")
(NOTE-3-4
(RELEASE-NOTES)
"ACL2 Version 3.4 (August, 2008) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 3.3 into changes
to existing features, new features, bug fixes, new and updated
books, and Emacs support. Each change is described just once,
though of course many changes could be placed in more than one
category.
CHANGES TO EXISTING FEATURES
Fixed a long-standing potential infinite loop in the rewriter. Thanks
to Sol Swords for sending a concise example illustrating the
looping behavior. (Those interested in details are welcome to look
at the comment about loop behavior in source function
rewrite-equal.)
Incorporated a slight strengthening of non-linear arithmetic
contributed by Robert Krug (thanks, Robert). With non-linear
arithmetic enabled, the problem was essentially that ACL2 made the
following ``optimization'': given inequalities (< a u) and (< b v),
for positive rational constants a and b terms u and v of which at
least one is known to be rational, infer (< (* a b) (* u v)).
Without this optimization, however, ACL2 now infers the stronger
inequality obtained by direct multiplication of the two given
inequalities. To see the effect of this change, submit the event
(set-non-linearp t) followed by:
(thm (implies (and (rationalp x) (< 3 x)
(rationalp y) (< 4 y))
(< 0 (+ 12 (* -4 x) (* -3 y) (* x y)))))
The utility [set-checkpoint-summary-limit] has been modified in
several ways: it now takes a single argument (no longer takes
[state] as an argument); a natural number n abbreviates the pair (n
. n); the argument is no longer evaluated, but it still optionally
may be quoted; and a new value, t, suppresses all printing of the
checkpoint summary. Thanks to Jared Davis for suggesting most of
these improvements.
There was formerly a restriction on [mbe] that the :exec argument may
not contain a call of [mbe]. This restriction has been removed,
thanks to a request from Jared Davis and Sol Swords. Thanks also to
Sandip Ray, who pointed out that this restriction may have been in
place in order that [defexec] can guarantee termination using the
:exec code; its [documentation] has therefore been updated to
clarify this situation.
Rules of class :[rewrite] are now stored by performing certain
logical simplifications on the left side of the conclusion: (prog2$
X Y) is replaced by Y, (mbe :logic X :exec Y) is replaced by X
(more precisely, the analogous change is made to the generated call
of [must-be-equal]); and (the TYPE X) is replaced by X (again, the
change is actually made on the macroexpanded form). Thanks to Jared
Davis and Sol Swords for requesting this change. An analogous
change has also been made for rules of class :[forward-chaining].
The [trace$] utility has been reimplemented to work independently of
the underlying Lisp trace. It thus works the same for every host
Lisp, except as provided by an interface to the underlying host
Lisp trace (the :native option). Note that the host Lisp trace
continues to be modified for GCL, Allegro CL, and CCL (OpenMCL);
see [trace]. See [trace$] for updated detailed documentation on
tracing options, many of which are new, for example an :evisc-tuple
option that can be set to :no-print if you want the function traced
without the usual entry and exit printing. The previous [trace$]
had some issues, including the following, which have all been
fixed. Thanks to Peter Dillinger for assistance in determining
desired functionality of the new [trace$] and for helping to test
it.
Recursive calls were not always shown in the trace for two reasons.
(1) Compiler inlining could prevent recursive calls from being
shown in the trace, in particular in CCL (OpenMCL). Thanks to
Jared Davis and Warren Hunt for pointing out this issue and
requesting a fix, and to Bob Boyer and Gary Byers for relevant
helpful discussions. (2) ACL2's algorithm for producing
executable counterparts prevented tracing of recursive calls
even after (set-guard-checking :none). Thanks to Peter
Dillinger for requesting a fix.
It was possible to exploit a bug in the interaction of multiple
values and trace to prove a contradiction. An example is in a
comment in (deflabel note-3-4 ...) in the ACL2 source code.
Certain large structures could cause expensive computations for
printing even when a :cond condition was specified and
evaluated to nil.
[Trace!] now suppresses printing of the event summary, and returns
the value that would be returned (if there is an active trust
tag) by the corresponding call of [trace$].
Some bugs have been fixed in the underlying native trace installed by
ACL2 for GCL, Allegro CL, and CCL (OpenMCL), including the
following. In GCL it had been impossible to use the variable
ARGLIST in a :cond expression. In Allegro CL and CCL, a
[trace$] bug mishandled tracing non-ACL2 functions when
directives such as :entry and :exit were supplied. GCL trace
now hides the world even when tracing non-ACL2 functions.
Tracing in CCL no longer causes a Lisp error when untracing a
traced function defined outside the ACL2 loop; for example
(trace$ len1) followed by (untrace$ len1) no longer causes an
error.
The macro wet has been changed, for the better we think. see [wet].
The generation of goals for [forcing-round]s has been changed to
avoid dropping assumptions formerly deemed ``irrelevant''. (A
simple example may be found in a comment in source function
unencumber-assumption, source file prove.lisp.) Thanks to Jared
Davis for sending us an example that led us to make this change.
Modified the implementation of [make-event] so that in the
[certificate] of a book, [local] events arising from [make-event]
forms are elided. For example, if (make-event <form>) expands to
(local <expanded-form>), then where the latter had been stored in
the certificate, now instead (local (value-triple :ELIDED)) will be
stored. Thanks to Eric Smith for requesting this improvement. He
has reported that a preliminary version of this improvement shrunk
a couple of his .cert files from perhaps 40MB each to about 140K
each.
Now, a [table] event that sets the entire table, (table tbl nil alist
:clear), is redundant (see [redundant-events]) when the supplied
alist is equal to the current value of the table. Thanks to Peter
Dillinger for requesting this change.
The event constructor [progn!] now returns the value that is returned
by evaluation of its final form if no error occurs, except that it
still returns nil if the that final evaluation leaves ACL2 in
raw-mode.
:[Pso] and :[psog] have been improved so that they show the key
checkpoint summary at the end of a failed proof. (For a discussion
of key checkpoints, see [set-gag-mode].) As a result, a call of
[set-checkpoint-summary-limit] now affects subsequent evaluation of
:[pso] and :[psog]. In particular, you no longer need to
reconstruct a proof (by calling [thm] or [defthm]) in order to see
key checkpoints that were omitted due to the limit; just call
[set-checkpoint-summary-limit] and then run :pso or :psog.
The [proof-checker] behaves a little differently under [gag-mode].
Now, proof-checker commands that call the theorem prover to create
new proof-checker goals, such as bash and induct (see
[proof-checker-commands]), will show key checkpoints when in
[gag-mode]. As before, proof-checker commands pso and pso! (and
now, also psog) --- see [pso], see [psog], and see [pso!] --- can
then show the unedited proof log. However, unlike proof attempts
done in the ACL2 loop, such proof attempts will not show a summary
of key checkpoints at the end, because from a prover perspective,
all such goals were considered to be temporarily ``proved'' by
giving them ``byes'', to be dispatched by later proof-checker
commands.
A little-known feature had been that a [measure] of 0 was treated as
though no measure was given. This has been changed so that now, a
[measure] of nil is treated as though no measure was given.
Expanded *acl2-exports* to include every documented symbol whose name
starts with \"SET-\". Thanks to Jared Davis for remarking that
[set-debugger-enable] was omitted from *acl2-exports*, which led to
this change.
The [trace] mechanism has been improved so that the :native and
:multiplicity options can be used together for Lisps that support
the trace :exit keyword. These Lisps include GCL and Allegro CL,
whose native trace utilities have been modified for ACL2. For SBCL
and CCL (OpenMCL), which use the built-in Lisp mechanism for
returning multiple values in ACL2 (see [mv]), the use of
:multiplicity with :native remains unnecessary and will be ignored.
In support of this change, the modification of native Allegro CL
tracing for ACL2 was fixed to handle :exit forms correctly that
involve [mv].
NEW FEATURES
The command :[redef!] is just like :[redef], but prints a warning
rather than doing a query. The old version of :redef! was for
system hackers and has been renamed to :[redef+].
Introduced a new utility for evaluating a function call using the
so-called executable counterpart --- that is, executing the call in
the logic rather than in raw Lisp. See [ec-call]. Thanks to Sol
Swords for requesting this utility and participating in its
high-level design.
See [print-gv] for a new utility that assists with debugging guard
violations. Thanks to Jared Davis for requesting more tool
assistance for debugging guard violations.
Improved the guard violation error message to show the positions of
the formals, following to a suggestion of Peter Dillinger.
Added new [guard-debug] capability to assist in debugging failed
attempts at [guard] verification. See [guard-debug]. Thanks to
Jared Davis for requesting a tool to assist in such debugging and
to him, Robert Krug, and Sandip Ray for useful discussions.
New utilities provide the formula to be proved by [verify-guards].
See [verify-guards-formula] and see [guard-obligation], Thanks to
Mark Reitblatt for making a request leading to these utilities.
These utilities can be applied to a term, not just an event name;
thanks to Peter Dillinger for correspondence that led to this
extension.
A new utility causes runes to be printed as lists in proof output
from simplification, as is done already in proof summaries. See
[set-raw-proof-format]. Thanks to Jared Davis for requesting this
utility.
An experimental capability allows for parallel evaluation. See
[parallelism]. Thanks to David Rager for providing an initial
implementation of this capability.
Defined [xor] in analogy to [iff]. Thanks to Bob Boyer, Warren Hunt,
and Sol Swords for providing this definition.
Improved distributed file doc/write-acl2-html.lisp so that it can now
be used to build HTML documentation files for [documentation]
strings in user [books]. See the comment in the definition of macro
acl2::write-html-file at the end of that file. Thanks to Dave Greve
and John Powell for requesting this improvement.
It is now possible to specify :[hints] for non-recursive function
definitions (which can be useful when definitions are automatically
generated). See [set-bogus-defun-hints-ok]. Thanks to Sol Swords
for requesting such a capability.
Keyword argument :dir is now supported for [rebuild] just as it has
been for [ld].
We relaxed the criteria for functional substitutions, so that a
function symbol can be bound to a macro symbol that corresponds to
a function symbol in the sense of [macro-aliases-table]. So for
example, a functional substitution can now contain the doublet (f
+), where previously it would have been required instead to contain
(f binary-+).
We now allow arbitrary packages in raw mode (see [set-raw-mode]) ---
thanks to Jared Davis for requesting this enhancement --- and more
than that, we allow arbitrary Common Lisp in raw mode. Note however
that for arbitrary packages, you need to be in raw mode when the
input is read, not just when the input form is evaluated.
Two new keywords are supported by the [with-output] macro. A
:gag-mode keyword argument suppresses some prover output as is done
by [set-gag-mode]. Thanks to Jared Davis for asking for a
convenient way to set [gag-mode] inside a book, in particular
perhaps for a single theorem; this keyword provides that
capability. A :stack keyword allows sub-[events] of [progn] or
[encapsulate] to ``pop'' the effect of a superior [with-output]
call. Thanks to Peter Dillinger for requesting such a feature. See
[with-output].
The command [good-bye] and its aliases [exit] and [quit] now all take
an optional status argument, which provides the Unix exit status
for the underlying process. Thanks to Florian Haftmann for sending
a query to the ACL2 email list that led to this enhancement.
Keyword commands now work for macros whose argument lists have lambda
list keywords. For a macro with a lambda list keyword in its
argument list, the corresponding keyword command reads only the
minimum number of required arguments. See [keyword-commands].
It is now legal to [declare] variables ignorable in [let*] forms, as
in (let* ((x (+ a b)) ...) (declare (ignorable x)) ...). Thanks to
Jared Davis for requesting this enhancement.
Added a warning when more than one hint is supplied explicitly for
the same goal. It continues to be the case that only the first hint
applicable to a given goal will be applied, as specified in the
user-supplied list of :hints followed by the [default-hints-table].
Thanks to Mark Reitblatt for sending a question that led both to
adding this clarification to the [documentation] and to adding this
warning.
You may now use [set-non-linear], [set-let*-abstraction],
set-tainted-ok, and [set-ld-skip-proofs] in place of their versions
ending in ``p''. Thanks to Jared Davis for suggesting consideration
of such a change. All ``set-'' utilites now have a version without
the final ``p'' (and most do not have a version with the final
``p'').
Added a \"Loop-Stopper\" warning when a :[rewrite] rule is specified
with a :[loop-stopper] field that contains illegal entries that
will be ignored. Thanks to Jared Davis for recommending such a
warning.
Added a substantial documentation topic that provides a beginner's
guide to the use of quantification with [defun-sk] in ACL2. Thanks
to Sandip Ray for contributing this guide, to which we have made
only very small modifications. See [quantifier-tutorial].
[Defun-sk] now allows the keyword option :strengthen t, which will
generate the extra constraint that that is generated for the
corresponding defchoose event; see [defchoose]. Thanks to Dave
Greve for suggesting this feature.
BUG FIXES
Fixed a soundness bug related to the use of [mbe] inside
[encapsulate] events. An example proof of nil (before the fix) is
in a comment in (deflabel note-3-4 ...) in the ACL2 source code. We
therefore no longer allow calls of [mbe] inside [encapsulate]
events that have non-empty [signature]s.
Fixed a bug related to the definition of a function supporting the
macro [value-triple]. Although this bug was very unlikely to affect
any user, it could be carefully exploited to make ACL2 unsound:
(defthm fact
(equal (caadr (caddr (value-triple-fn '(foo 3) nil nil)))
'value) ; but it's state-global-let* in the logic
:rule-classes nil)
(defthm contradiction
nil
:hints ((\"Goal\" :use fact :in-theory (disable (value-triple-fn))))
:rule-classes nil)
Non-[local] definitions of functions or macros are no longer
considered redundant with built-ins when the built-ins have special
raw Lisp code, because ACL2 was unsound without this restriction! A
comment about redundant definitions in source function
chk-acceptable-defuns shows how one could prove nil without this
new restriction. Note that system utility :[redef+] removes this
restriction.
Although ACL2 already prohibited the use of certain built-in
:[program] mode functions for [verify-termination] and during
macroexpansion, we have computed a much more complete list of
functions that need such restrictions, the value of constant
*primitive-program-fns-with-raw-code*.
Modified what is printed when a proof fails, to indicate more clearly
which event failed.
Fixed a problem with [dmr] in CCL (OpenMCL) that was causing a raw
Lisp break after an interrupt in some cases. Thanks to Gary Byers
for a suggestion leading to this fix.
Fixed bugs in [proof-checker] code for dealing with free variables in
hypotheses.
Upon an abort, the printing of [pstack] and [gag-mode] summary
information for other than GCL was avoided when inside a call of
[ld]. This has been fixed.
(Windows only) Fixed bugs for ACL2 built on SBCL on Windows,
including one that prevented [include-book] parameters :dir :system
from working, and one that prevented certain compilation. Thanks to
Peter Dillinger for bringing these to our attention and supplying a
fix for the second. Thanks also to Andrew Gacek for bringing
[include-book] issues to our attention. Also, fixed writing of file
saved_acl2 at build time so that for Windows, Unix-style pathnames
are used.
Fixed a hard Lisp error that could occur with keywords as [table]
names, e.g., (table :a :a nil :put). Thanks to Dave Greve for
bringing this problem to our attention and providing this example.
Fixed handling of :OR [hints] so that proof attempts under an :OR
hint do not abort (reverting to induction on the original input
conjecture) prematurely. Thanks to Robert Krug for pointing out
this problem and pointing to a possible initial fix.
(SBCL and CLISP only) It is now possible to read symbols in the
\"COMMON-LISP\" package inside the ACL2 command loop (see [lp]). This
could cause a raw Lisp error in previous versions of ACL2 whose
host Common Lisp was SBCL or CLISP. Thanks to Peter Dillinger for
bringing this issue to our attention.
Fixed a bug that was preventing certain [hints], such as :do-not
hints, from being used after the application of an :or hint. Thanks
to Robert Krug for bringing this bug to our attention.
(Hons version only) Fixed a bug in the interaction of [memoize]
([hons] version only) with event processing, specifically in
interaction with failures inside a call of [progn] or
[encapsulate]. Thanks to Jared Davis for bringing this bug to our
attention and sending an example. A simplified example may be found
in a comment in source function table-cltl-cmd, source file
history-management.lisp; search for ``Version_3.3'' there.
Fixed [cw-gstack] so that its :evisc-tuple is applied to the top
clause, instead of using (4 5 nil nil) in all cases. If no
:evisc-tuple is supplied then (term-evisc-tuple t state) is used
for the top clause, as it is already used for the rest of the
stack.
Fixed a bug in the interaction of [proof-tree]s with :induct hint
value :otf-flg-override. Thanks to Peter Dillinger for reporting
this bug and sending an example that evokes it.
Fixed bugs in :[pr] and [find-rules-of-rune] for the case of rule
class :[elim]. Thanks to Robert Krug and Jared Davis for bringing
these related bugs to our attention.
Improved failure messages so that the key checkpoints are printed
only once when there is a proof failure. Formerly, a proof failure
would cause the key checkpoints to be printed for every
[encapsulate] or [certify-book] superior to the proof attempt.
Fixed a bug in generation of [guard]s for calls of [pkg-witness].
Thanks to Mark Reitblatt for sending an example showing this bug.
The bug can be in play when you see the message: ``HARD ACL2 ERROR
in MAKE-LAMBDA-APPLICATION: Unexpected unbound vars (\"\")''. A
distillation of Mark's example that causes this hard error is as
follows.
(defun foo (x)
(declare (xargs :guard t))
(let ((y x)) (pkg-witness y)))
The [cond] macro now accepts test/value pairs of the form (T val) in
other than the last position, such as the first such pair in (cond
(t 1) (nil 2) (t 3)). Thanks to Jared Davis for sending this
example and pointing out that ACL2 was sometimes printing goals
that have such a form, and hence cannot be submitted back to ACL2.
A few macros corresponding to [cond] in some books under books/rtl
and books/bdd were similarly modified. (A second change will
probably not be noticeable, because it doesn't affect the final
result: singleton [cond] clauses now generate a call of [or] in a
single step of macroexpansion, not of [if]. For example, (cond (a)
(b x) (t y)) now expands to (OR A (IF B X Y)) instead of (IF A A
(IF B X Y)). See the source code for cond-macro for a comment about
this change.)
Fixed a bug in the interaction of [proof-checker] command DV,
including numeric (``diving'') commands, with the [add-binop]
event. Specifically, if you executed (add-binop mac fn) with fn
having arity other than 2, a [proof-checker] command such as 3 or
(dv 3) at a call of mac could have the wrong effect. We also fixed
a bug in diving with DV into certain AND and OR calls. Thanks for
Mark Reitblatt for bringing these problems to our attention with
helpful examples.
Fixed a couple of bugs that were causing an error, ``HARD ACL2 ERROR
in RENEW-NAME/OVERWRITE''. Thanks to Sol Swords for bringing the
first of these bugs to our attention.
Fixed a bug that could cause [certify-book] to fail in certain cases
where there are [local] [make-event] forms.
Fixed a bug in [start-proof-tree] that could cause Lisp to hang or
produce an error. Thanks to Carl Eastlund for sending an example to
bring this bug to our attention.
Fixed a bug in the proof output, which was failing to report cases
where the current goal simplifies to itself or to a set including
itself (see [specious-simplification]).
Fixed a bug in [with-prover-time-limit] that was causing a raw Lisp
error for a bad first argument. Thanks to Peter Dillinger for
pointing out this bug.
The following was claimed in :doc [note-3-3], but was not fixed until
the present release:
Distributed directory doc/HTML/ now again includes installation
instructions, in doc/HTML/installation/installation.html.
In certain Common Lisp implementations --- CCL (OpenMCL) and
LispWorks, at least --- an interrupt could leave you in a break
such that quitting the break would not show the usual summary of
key checkpoints. This has been fixed.
NEW AND UPDATED BOOKS
Updated books/clause-processors/SULFA/ with a new version from Erik
Reeber; thanks, Erik.
Added new books directory tools/ from Sol Swords. See
books/tools/Readme.lsp for a summary of what these books provide.
The distributed book books/misc/file-io.lisp includes a new utility,
write-list!, which is like write-list except that it calls
[open-output-channel!] instead of [open-output-channel]. Thanks to
Sandip Ray for requesting this utility and assisting with its
implementation.
Added record-update macro supplied by Sandip Ray to distributed book
books/misc/records.lisp.
Sandip Ray has contributed books that prove soundness and
completeness of different proof strategies used in sequential
program verification. Distributed directory books/proofstyles/ has
three new directories comprising that contribution: soundness/,
completeness/, and counterexamples/. The existing
books/proofstyles/ directory has been moved to its subdirectory
invclock/.
Jared Davis has contributed a profiling utility for ACL2 built on CCL
(OpenMCL). See books/misc/oprof.lisp. Thanks, Jared.
ACL2 utilities [getprop] and [putprop] take advantage of
under-the-hood Lisp (hashed) property lists. The new book
books/misc/getprop.lisp contains an example showing how this works.
Added the following new book directories: books/paco/, which includes
a small ACL2-like prover; and books/models/jvm/m5, which contains
the definition of one of the more elaborate JVM models, M5, along
with other files including JVM program correctness proofs. See
files Readme.lsp in these directories, and file README in the
latter.
Added books about sorting in books/sorting. See Readme.lsp in that
directory for documentation.
Added book books/misc/computed-hint-rewrite.lisp to provide an
interface to the rewriter for use in computed hints. Thanks to
Jared Davis for requesting this feature.
Jared Davis has provided a pseudorandom number generator, in
books/misc/random.lisp.
Robert Krug has contributed a new library, books/arithmetic-4/, for
reasoning about arithmetic. He characterizes it as being more
powerful than its predecessor, books/arithmetic-3/, and without its
predecessor's rewriting loops, but significantly slower than its
predecessor on some theorems.
Incorporated changes from Peter Dillinger to verify guards for
functions in books/ordinals/lexicographic-ordering.lisp (and one in
ordinal-definitions.lisp in that directory).
A new directory, books/hacking/, contains a library for those who
wish to use trust tags to modify or extend core ACL2 behavior.
Thanks to Peter Dillinger for contributing this library. Obsolete
version books/misc/hacker.lisp has been deleted. Workshop
contribution books/workshops/2007/dillinger-et-al/code/ is still
included with the workshops/ tar file, but should be considered
deprecated.
In books/make-event/assert.lisp, changed assert! and assert!-stobj to
return (value-triple :success) upon success instead of
(value-triple nil), following a suggestion from Jared Davis.
EMACS SUPPORT
Changed emacs/emacs-acl2.el so that the fill column default (for the
right margin) is only set (still to 79) in lisp-mode.
Modified Emacs support in file emacs/emacs-acl2.el so that names of
events are highlighted just as [defun] has been highlighted when it
is called. Search in the above file for font-lock-add-keywords for
instructions on how to eliminate this change.
The name of the temporary file used by some Emacs utilities defined
in file emacs/emacs-acl2.el has been changed to have extension .lsp
instead of .lisp; thus it is now temp-emacs-file.lsp. Also, `make'
commands to `clean' books will delete such files (specifically,
books/Makefile-generic has been changed to delete
temp-emacs-file.lsp).")
(NOTE-3-4{R}
(RELEASE-NOTES)
"ACL2 Version 3.4(r) (August, 2008) Notes
Please also see [note-3-4] for changes to Version 3.4 of ACL2.
Fixed makefiles, books/nonstd/Makefile and GNUmakefile. The old
set-up seemed to work fine as long as all books certified, but it
was really broken, for example only certifying some of the books in
books/nonstd/nsa/, and then only when required by books in other
directories. Also fixed the ``clean'' target to clean links rather
than to make links.")
(NOTE-3-5
(RELEASE-NOTES)
"ACL2 Version 3.5 (May, 2009) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 3.4 into the
following categories: changes to existing features, new features,
heuristic improvements, bug fixes, new and updated books, Emacs
support, and experimental [hons] version. Each change is described
in just one category, though of course many changes could be placed
in more than one category.
CHANGES TO EXISTING FEATURES
Many improvements have been made to ACL2's ``evisceration'' mechanism
for hiding substructures of objects before they are printed, and to
related documentation:
o A new documentation topic explains evisc-tuples. See [evisc-tuple].
o A new interface, [set-evisc-tuple], has been provided for setting
the four global evisc-tuples. See [set-evisc-tuple].
o A new mode, ``iprinting'', allows eviscerated output to be read
back in. See [set-iprint].
o Function default-evisc-tuple has been deprecated and will probably
be eliminated in future releases; use abbrev-evisc-tuple
instead. Also eliminated is the brr-term-evisc-tuple (also the
user-brr-term-evisc-tuple). The term-evisc-tuple controls
printing formerly controlled by the brr-term-evisc-tuple or
user-brr-term-evisc-tuple.
o ACL2 output is done in a more consistent manner, respecting the
intention of those four global evisc-tuples. In particular,
more proof output is sensitive to the term-evisc-tuple. Again,
see [set-evisc-tuple].
o A special value, :DEFAULT, may be provided to [set-evisc-tuple] in
order to restore these [evisc-tuple]s to their original
settings.
o (Details for heavy users of the evisc-tuple mechanism) (1) There
are no longer [state] globals named user-term-evisc-tuple or
user-default-evisc-tuple. (2) Because of the above-mentioned
:DEFAULT, if you have referenced state globals directly, you
should use accessors instead, for example (abbrev-evisc-tuple
state) instead of (@ abbrev-evisc-tuple). (3) For uniformity,
[set-trace-evisc-tuple] now takes a second argument, state.
Improved [break-on-error] in several ways. First, it breaks earlier
in a more appropriate place. Thanks to Dave Greve for highlighting
this problem with the existing implementation. Also,
[break-on-error] now breaks on hard errors, not only soft errors
(see [er], options hard and hard?). Thanks to Warren Hunt and Anna
Slobodova for sending an example that showed a flaw in an initial
improvement. Finally, new options cause printing of the call stack
for some host Common Lisps. See [break-on-error]. Thanks to Bob
Boyer for requesting this feature.
[Trace!] may now be used in raw Lisp (though please note that all
soundness claims are off any time you evaluate forms in raw Lisp!).
Thanks to Bob Boyer for feedback that led to this enhancement.
ACL2 now searches for file acl2-customization.lsp in addition to (and
just before) its existing search for acl2-customization.lisp; See
[ACL2-customization]. Thanks to Jared Davis for suggesting this
change, which supports the methodology that files with a .lisp
extension are certifiable books (thus avoiding the need to set the
BOOKS variable in makefiles; see [books-certification-classic]).
Improved the error message for illegal [declare] forms of the form
(type (satisfies ...)). Thanks to Dave Greve for sending an example
highlighting the issue.
If trace output is going to a file (because [open-trace-file] has
been executed), then a note will be printed to that effect at the
time that a call of [trace$] or [trace!] is applied to one or more
[trace] specs.
The notion of redundancy (see [redundant-events]) has been made more
restrictive for [mutual-recursion] events. Now, if either the old
or new event is a [mutual-recursion] event, then redundancy
requires that both are [mutual-recursion] events that define the
same set of function symbols. Although we are not aware of any
soundness bugs fixed by this modification, nevertheless we believe
that it reduces the risk of soundness bugs in the future.
The definition of trace* has been moved to a book, misc/trace1.lisp.
A new version, used in ACL2s, is in book misc/trace-star.lisp.
[Trace] utilities [trace$] and [trace!] are still built into ACL2.
[Note: File misc/trace1.lisp was deleted after Version 4.2.]
Certain [certificate] files will now be much smaller, by printing in
a way that takes advantage of structure sharing. Certifying the
following example produces a .cert file of over 3M before this
change, but less than 1K after the change.
(defun nest (i)
;; Makes an exponentially-sized nest of conses i deep.
(if (zp i)
nil
(let ((next (nest (1- i))))
(cons next next))))
(make-event
`(defconst *big* ',(nest 20)))
Thanks to Sol Swords for providing the above example and to him as
well as to Bob Boyer, Jared Davis, and Warren Hunt for encouraging
development of this improvement. We have also applied this
improvement to the printing of function definitions to files on
behalf of [certify-book] and [comp].
Names of symbols are now printed with vertical bars according to the
Common Lisp spec. Formerly, if the first character of a symbol name
could be the first character of the print representation of a
number, then the symbol was printed using vertical bars (|..|)
around its name. Now, a much more restrictive test for ``potential
numbers'' is used, which can result in fewer such vertical bars.
Base 16 is now carefully considered as well; see [set-print-base].
Thanks to Bob Boyer for requesting this improvement. Note that
macros set-acl2-print-base and set-acl2-print-case have been
replaced by functions; see [set-print-base] and see
[set-print-case].
The ACL2 reader now supports `#.' syntax in place of the `#, syntax
formerly supported. Thanks to Bob Boyer for requesting this change.
See [sharp-dot-reader]. NOTE that because of this change, `#.' no
longer causes an abort; instead please use (a!) or optionally, if
in the ACL2 loop, :a!; see [a!].
Some small changes have been made related to [gag-mode]:
o [Gag-mode] now suppresses some messages that were being printed
upon encountering disjunctive splits from :OR [hints]. Thanks
to Sol Swords for suggesting this improvement.
o ACL2 had printed ``Q.E.D.'' with all output suppressed and
[gag-mode] enabled. Now, ``Q.E.D.'' will be suppressed when
PROVE and SUMMARY output are suppressed, even if gag-mode is
enabled.
o The use of [set-gag-mode] had drastic effects on the inhibited
output (see [set-inhibit-output-lst]), basically inhibiting
nearly all output (even most warnings) when turning on gag-mode
and enabling all output except proof-tree output when turning
off gag-mode. Now, [set-gag-mode] only inhibits or enables
proof (PROVE) output, according to whether gag-mode is being
turned on or off (respectively). The related utility
[set-saved-output] has also been modified, basically to
eliminate :all as a first argument and to allow t and :all as
second arguments, for inhibiting prover output or virtually all
output, respectively (see [set-saved-output]).
A [defstub] event [signature] specifying output of the form (mv ...)
now introduces a :[type-prescription] rule asserting that the new
function returns a [true-listp] result. Thanks to Bob Boyer for
sending the following example, which motivated this change.
(defstub census (*) => (mv * *))
(defn foo (x)
(mv-let (a1 a2)
(census x)
(list a1 a2)))
Improved the efficiency of [string-append] so that in raw Lisp, it
calls [concatenate]. Thanks to Jared Davis for suggesting this
change, including the use of [mbe]. A minor change was made to the
definition of [concatenate] to support this change, and the lemma
append-to-nil was added (see below).
The checksum algorithm used for [certificate] files of [books] has
been changed. Thanks to Jared Davis for contributing the new code.
This change will likely not be noticed unless one is using the
experimental [hons] version of ACL2, where it can greatly speed up
book certification and inclusion because of function memoization
(of source function fchecksum-obj).
Fewer calls are made to the checksum algorithm on behalf of
[certify-book] and a few other operations. Thanks to Jared Davis
for providing data that helped lead us to these changes.
Formatted printing directives ~p, ~q, ~P, and ~Q are deprecated,
though still supported. See [fmt]. Instead, please use ~x, ~y, ~X,
and ~Y (respectively). As a by-product, rule names in proof output
are no longer hyphenated.
A new keyword, :multiplicity, is available for tracing raw Lisp
functions using the ACL2 [trace] utility. See [trace$].
Users may now control whether or not a slow array access results in a
warning printed to the screen (which is the default, as before),
and if so, whether or not the warning is followed by a break. See
[slow-array-warning].
On linux-like systems (including Mac OS X and SunOS), :[comp] will
now write its temporary files into the \"/tmp\" directory, which is
the value of [state] global 'tmp-dir. You can change that directory
with (assign tmp-dir \"<your_temp_directory_path>\").
The messages printed for uncertified books have been enhanced. Thanks
to Jared Davis for requesting such an improvement.
A function definition that would be redundant if in :[logic] mode is
now considered redundant even if it (the new definition) is in
:[program] mode. That is, if a definition is ``downgraded'' from
:logic to :program mode, the latter (:program mode) definition is
considered redundant. Previously, such redundancy was disallowed,
but we have relaxed that restriction because of a scenario brought
to our attention by Jared Davis: include a book with the :logic
mode definition, and then include a book with the :program mode
definition followed by [verify-termination]. Thanks, Jared.
The ACL2 reader no longer accepts characters other than those
recognized by [standard-char-p] except for #\\Tab, #\\Page, and
#\\Rubout (though it still accepts strings containing such
characters). As a result, no [make-event] expansion is allowed to
contain any such unacceptable character or string. Thanks to Sol
Swords for sending an example that led us to make this restriction.
A simple example is the following book:
(in-package \"ACL2\")
(defconst *my-null* (code-char 0))
(make-event `(defconst *new-null* ,*my-null*))
For this book, a call of [certify-book] formerly broke during the
compilation phase, but if there was no compilation, then a call of
[include-book] broke. Now, the error occurs upon evaluation of the
[make-event] form.
ACL2 now collects up [guard]s from [declare] forms more as a user
might expect, without introducing an unexpected ordering of
conjuncts. We thank Jared Davis for sending us the following
illustrative example, explained below.
(defun f (x n)
(declare (xargs :guard (and (stringp x)
(natp n)
(= (length x) n)))
(type string x)
(ignore x n))
t)
Formerly, a guard was generated for this example by unioning the
conjuncts from the :guard onto a list containing the term (string
x) generated from the type declaration, resulting in an effective
guard of:
(and (natp n)
(= (length x) n)
(stringp x))
The guard of this guard failed to be verified because (stringp x))
now comes after the call (length x). With the fix, contributions to
the guards are collected up in the order in which they appear. So
in the above example, the effective guard is the specified :guard;
the contribution (stringp x) comes later, and is thus dropped since
it is redundant. NOTE by the way that if :guard and :stobjs are
specified in the same [xargs] form, then for purposes of collecting
up the effective guard as described above, :stobjs will be treated
as through it comes before the :guard.
Modified [close-output-channel] to try to do a better job flushing
buffers. Thanks to Bob Boyer for helpful correspondence.
The notion of ``subversive recursion'' has been modified so that some
functions are no longer marked as subversive. See
[subversive-recursions], in particular the discussion elaborating
on the notion of ``involved in the termination argument'' at the
end of that [documentation] topic.
Formerly, :[type-prescription] rules for new definitions inside
[encapsulate] forms were sometimes added as [constraint]s. This is
no longer the case. See also discussion of the ``soundness bug in
the forming of constraints'', which is related.
NEW FEATURES
It is now possible to affect ACL2's termination analysis (and
resulting induction analysis). Thanks to Peter Dillinger for
requesting this feature. The default behavior is essentially
unchanged. But for example, the following definition is accepted by
ACL2 because of the use of the new :ruler-extenders features; See
[ruler-extenders].
(defun f (x)
(declare (xargs :ruler-extenders :all))
(cons 3
(if (consp x)
(f (cdr x))
nil)))
The following lemma was added in support of the improvement to
[string-append] described above:
(defthm append-to-nil
(implies (true-listp x)
(equal (append x nil)
x)))
A mechanism has been provided for users to contribute documentation.
See [managing-ACL2-packages] for an example, which contains a link
to an external web page on effective use of ACL2 packages, kindly
provided by Jared Davis. ACL2 [documentation] strings may now link
to external web pages using the new symbol, ~url; see markup. Of
course, those links appear in the web version of the documentation,
but you made need to take a bit of action in order for these to
appear as links in the Emacs Info version; see [documentation].
Added [intersectp] (similar to [intersectp-eq] and
[intersectp-equal]).
The user now has more control over how ACL2 prints forms; See
[print-control]. Thanks to Bob Boyer for useful discussions leading
to this enhancement.
Some Common Lisp implementations only allow the syntax
pkg-name::expression when expression is a symbol. The ACL2 reader
has been modified to support a package prefix for arbitrary
expressions; see [sharp-bang-reader]. Thanks to Hanbing Liu for a
query that led to this feature and to Pascal J. Bourguignon for
suggesting an implmentation.
Ill-formed [documentation] strings need not cause an error. See
set-ignore-doc-string-error. Thanks to Bob Boyer for requesting
this feature.
Type declarations are now permitted in let* forms; see [let*], see
[declare], and see [type-spec].
(For Lisp programmers) Macro with-live-state has been provided for
programmers who refer to free variable STATE, for example with
macros that generate uses of STATE, and want to avoid compiler
warnings when evaluating in raw Lisp. For example, the following
form can be submitted either inside or outside the ACL2 loop to get
the desired effect (see doc-string): (with-live-state (f-put-global
'doc-prefix \" \" state)). For another example use of this macro, see
the definition of trace$ (ACL2 source file other-events.lisp).
(System hackers only) Added :[redef-] to undo the effect of
:[redef+]. See [redef-].
Function [random$] is a built-in random number generator. See
[random$]. Thanks to Sol Swords for requesting this feature and
providing an initial implementation.
HEURISTIC IMPROVEMENTS
Sped up [guard] generation for some functions with large if-then-else
structures in their bodies. Thanks to Sol Swords for sending an
illustrative example.
Sped up [guard] generation in some cases by evaluating ground
(variable-free) subexpressions. Thanks to Bob Boyer for sending a
motivating example: (defn foo (x) (case x ((1 2) 1) ((3 4) 3) ...
((999 1000) 999))).
Modified slightly a heuristic association of ``size'' with constants,
which can result in significant speed-ups in proofs involving
constants that are very large cons trees.
Added a restriction in the linear arithmetic procedure for deleting
polynomial inequalities from the linear database. Formerly, an
inequality could be deleted if it was implied by another
inequality. Now, such deletion requires that certain heuristic
``parent tree'' information is at least as restrictive for the
weaker inequality as for the stronger. Thanks to Dave Greve for
bringing a relevant example to our attention and working with us to
figure out some surprising behavior, and to Robert Krug for making
a key observation leading to the fix.
(GCL especially) Improved compiled code slightly by communicating to
raw Lisp the output type when a function body is of the form (the
character ...). This tiny improvement will probably only be
observed in GCL, if at all.
Applied a correction suggested by Robert Krug to the variant of
[term-order] used in parts of ACL2's arithmetic reasoning.
BUG FIXES
Fixed bugs in the handling of [flet] expressions, one of which had
the capability of rendering ACL2 unsound. Thanks to Sol Swords for
pointing out two issues and sending examples. One example
illustrated how ACL2 was in essence throwing away outer [flet]
bindings when processing an inner flet. We have exploited that
example to prove a contradiction, as follows: this book was
certifiable before this fix.
(in-package \"ACL2\")
(defun a (x)
(list 'c x))
; Example from Sol Swords, which failed to be admitted (claiming that
; function A is undefined) without the above definition of A.
(defun foo1 (x y)
(flet ((a (x) (list 'a x)))
(flet ((b (y) (list 'b y)))
(b (a (list x y))))))
(defthm not-true
(equal (foo1 3 4)
'(b (c (3 4))))
:hints ((\"Goal\"
:in-theory
(disable (:executable-counterpart foo1))))
:rule-classes nil)
(defthm contradiction
nil
:hints ((\"Goal\" :use not-true))
:rule-classes nil)
Sol's second example, below, pointed to a second bug related to
computing output signatures in the presence of nested flet
expressions, which we have also fixed: this form failed before the
fix.
:trans (flet ((foo (a) (list (flet ((bar (b) b)) a)))) x)
Fixed a subtle soundness bug in the forming of constraints from
deduced type prescriptions. As a result, when ACL2 prints a warning
message labeling encapsulated functions as ``subversive'', ACL2
will no longer deduce :[type-prescription] rules for those
functions. Examples that exploit the bug in ACL2 Version_3.4 may be
found in comments in ACL2 source function convert-type-set-to-term
(file other-processes.lisp) and especially in function
putprop-type-prescription-lst (file defuns.lisp). For more on the
general issue of ``subversive recursions,'' see
[subversive-recursions].)
Fixed a soundness bug in the handling of inequalities by the
[type-set] mechanism, which was using the inequality database
inside the body of a [lambda].
Fixed a long-standing soundness bug in [compress1] and [compress2],
whose raw Lisp code gave the logically incorrect result in the case
of a single entry other than the [header], where that entry mapped
an index to the [default] value. Also fixed soundness bugs in
[compress1], in the case of :order >, where the raw Lisp code could
drop the [header] from the result or, when the input alist had
entries in ascending order, fail to return an alist in descending
order. For example, the following book certified successfully.
(in-package \"ACL2\")
(defthm true-formula-1
(equal (compress1 'a '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5
:DEFAULT 1 :NAME A :ORDER <)
(1 . 1)))
'((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5
:DEFAULT 1 :NAME A :ORDER <)))
:hints ((\"Goal\" :in-theory (disable (compress1))))
:rule-classes nil)
(defthm ouch-1
nil
:hints ((\"Goal\" :use true-formula-1))
:rule-classes nil)
(defthm true-formula-2
(equal (compress1 'a '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5
:DEFAULT NIL :NAME A :ORDER >)
(1 . 1)
(2 . 2)))
'((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5
:DEFAULT NIL :NAME A :ORDER >)
(2 . 2)
(1 . 1)))
:hints ((\"Goal\" :in-theory (disable (compress1))))
:rule-classes nil)
(defthm ouch-2
nil
:hints ((\"Goal\" :use true-formula-2))
:rule-classes nil)
(defthm true-formula-3
(equal (compress1 'a '((:HEADER :DIMENSIONS (3) :MAXIMUM-LENGTH 4
:NAME A :ORDER >)
(1 . B)
(0 . A)))
'((:HEADER :DIMENSIONS (3) :MAXIMUM-LENGTH 4
:NAME A :ORDER >)
(1 . B)
(0 . A)))
:hints ((\"Goal\" :in-theory (disable (compress1))))
:rule-classes nil)
(defthm ouch-3
nil
:hints ((\"Goal\" :use true-formula-3))
:rule-classes nil)
Fixed a soundness bug involving measured subsets and
[verify-termination], by changing [verify-termination] so that it
uses [make-event]. See [verify-termination], in particular the
discussion about [make-event] near the end of that [documentation]
topic. Peter Dillinger first raised the idea to us of making such a
change; when we found this soundness bug, we were certainly happy
to do so!
Fixed a bug that could cause a hard Lisp error but not, apparently,
unsoundness. The bug was in the lack of attention to the order of
guard and type declarations when checking for redundancy. In the
following example, the second definition was redundant during the
first pass of the [encapsulate] form. The second definition,
however, was stored on the second pass with a guard of (and (consp
(car x)) (consp x)), which caused a hard Lisp error when evaluating
(foo 3) due to a misguided attempt to evaluate (car 3) in raw Lisp.
The fix is to restrict redundancy of definitions so that the guard
and type declarations must be in the same order for the two
definitions.
(encapsulate
()
(local (defun foo (x)
(declare (xargs :guard (consp x)))
(declare (xargs :guard (consp (car x))))
x))
(defun foo (x)
(declare (xargs :guard (consp (car x))))
(declare (xargs :guard (consp x)))
x))
; Now we get a hard Lisp error from evaluation of the guard of foo:
(foo 3)
Fixed a bug in the guard violation report for function
[intern-in-package-of-symbol]. Thanks to Dave Greve for bringing
this bug to our attention.
Made a change to allow certain [hints], in particular certain
:[clause-processor] hints, that had previously caused errors during
termination proofs by viewing the function being defined as not yet
existing. Thanks to Sol Swords for bringing this issue to our
attention with a nice example.
ACL2 now properly handles interrupts (via control-c) issued during
printing of the checkpoint summary. Previously it was possible on
some platforms to make ACL2 hang when interrupting both during a
proof and during the ensuing printing of the checkpoint summary.
Thanks to Jared Davis and Sol Swords for bringing this problem to
our attention.
Fixed a bug that was preventing, inside some book \"b\", the use of a
:dir argument to [include-book] that refers to a directory defined
using [add-include-book-dir] earlier in the book \"b\". (We found
this ourselves, but we thank John Cowles for observing it
independently and sending us a nice example.)
(GCL and CCL only) Fixed a bug in certain under-the-hood type
inferencing. Thanks to Sol Swords for sending an example using
[stobj]s defined with the :inline keyword, along with a helpful
backtrace in CCL, and to Gary Byers for his debugging help.
Fixed a bug in [print-gv], which was mishandling calls of functions
with more than one argument.
Fixed a bug in the handling of [and] and [or] terms by the
[proof-checker] command DV, including numeric (``diving'')
commands. Thanks for Mark Reitblatt for bringing this problems to
our attention with a helpful example.
Fixed printing of goal names resulting from the application of :OR
[hints] so that they aren't ugly when working in other than the
\"ACL2\" package. Thanks to Sol Swords for bringing this issue to our
attention.
Fixed [proof-tree] printing so that interrupts will not cause
problems with hiding ordinary output because of incomplete
proof-tree output. Thanks to Peter Dillinger for pointing out this
issue.
Fixed a hard error that could be caused by mishandling a [force]d
hypothesis during [forward-chaining]. Thanks to Peter Dillinger for
bringing this bug to our attention by sending a useful example.
Fixed a bug that could cause simplifications to fail because of
alleged ``specious simplification.'' This bug could appear when
deriving an equality from the linear arithmetic database, and then
attempting to add this equality to the current goal's hypotheses
when it was already present. Thanks to Eric Smith for sending a
helpful example (in July 2005!) that helped us debug this issue.
Fixed a bug in processing of :[type-set-inverter] rules.
Fixed a bug that was causing an error, at least for an underlying
Lisp of CCL (OpenMCL), when [ec-call] was applied to a term
returning multiple values. Thanks to Sol Swords for sending an
example that brought this bug to our attention.
Fixed handling of array orders to treat keyword value :order :none
correctly from an array's [header]. Previously, there were two
problems. One problem was that :order :none was treated like the
default for :order, <, while :order nil was treated in the manner
specified by :order :none (see [arrays]). Now, both :order :none
and :order nil are treated as :order nil had been treated, i.e., so
that there is no reordering of the alist by [compress1]. The other
problem with this case of :order was that the :maximum-length field
of the [header] was not being respected: the length could grow
without bound. Now, as previously explained (but not previously
implemented) --- see [arrays] --- a [compress1] call made on behalf
of aset1 causes a hard error if the header of the supplied array
specifies an :order of :none or nil.
An ignorable [declare] form had caused an error in some contexts when
it should have been allowed. In particular, this problem could
arise when using an ignorable declaration at the top level in a
[defabbrev] form. It could also arise upon calling
[verify-termination] when the corresponding [defun] form contained
an ignorable declaration at the top level. These bugs have been
fixed.
Contrary to existing documentation (see [make-event-details]), the
value of ``[ld] special variable'' [ld-skip-proofsp] was always set
to nil during [make-event] expansion, not merely when the
make-event form has a non-nil value for keyword parameter
:check-expansion. This has been fixed. Thanks to Sol Swords for
bringing this issue to our attention.
We have disallowed the certification of a book when not at the
top-level, either directly in the top-level loop or at the top
level of [ld]. Before this restriction, the following would certify
a book with a definition such as (defun foo (x) (h x)) that calls
function h before defining it, if the certification was by way of
the form such as:
(er-progn (defun h (x) x) (certify-book \"my-book\"))
But a subsequent [include-book] of \"my-book\" would then fail, because
h is not defined at the top level.
Printing with [fmt] directive ~c now works properly even when the
print-base is other than 10. Thanks to Sol Swords for reporting
this bug and providing a fix for it.
(SBCL, CMUCL, and CCL only) Fixed a bug in [sys-call-status] in the
case that the underlying Common Lisp is SBCL, CMUCL, or CCL
(OpenMCL). Thanks to Jun Sawada for bringing this bug to our
attention and providing a fix.
Fixed a bug that was preventing [local] [defstobj] events in
[encapsulate] events. Thanks to Jared Davis for bringing this bug
to our attention.
Fixed a bug evidenced by error message ``Unexpected form in
certification world'', which could result from attempting to
certify a book after evaluating an [encapsulate] form with a local
[defmacro]. Thanks to Jared Davis for pointing out this bug and
sending the example:
(encapsulate
()
(local (defmacro foo (x) `(table foo 'bar ,x)))
(local (foo 3)))
Formerly, evaluating a [trace$] form inside a [wormhole] such as the
[break-rewrite] loop could leave the user in a bad state after
returning to the top level, in which that function could not be
untraced. This has been fixed. Note however that when you proceed
from a break in the [break-rewrite] loop, the tracing state will be
the same as it was when you entered that break: all effects of
calling [trace$] and [untrace$] are erased when you proceed from
the break.
A :[guard] of (and) is no longer ignored. Thanks to Sol Swords for
bringing this bug to our attention.
A bug has been fixed that could result in needlessly weak induction
schemes in the case that a recursive call is made in the first
argument of [prog2$]. This has been fixed by including [prog2$] as
a default ruler-extender in the new ruler-extenders feature (see
above, and see [ruler-extenders]). For details on this bug see
Example 11 in distributed book
books/misc/misc2/ruler-extenders-tests.lisp.
(For CCL/OpenMCL on Windows) ACL2 should now build on CCL (OpenMCL)
on Windows. Thanks to David Rager for bringing this issue to our
attention and helping with a fix that worked for CCL 1.2, and to
the CCL team for improving handling of Windows-style filenames in
CCL 1.3.
NEW AND UPDATED BOOKS
See {ReleaseVersionNumbers |
https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers}
for a list of books in Version 3.5 of ACL2 but not Version 3.4.
Run the shell command
svn log -r 94:HEAD
to see all changes to books/ since the release of Version 3.4.
Here are just a few highlights.
Thanks largely to Jared Davis, many Makefiles have been improved to
do automatic dependency analysis. See [books-certification-classic]
for how to get your own Makefiles to do this by adding a line:
-include Makefile-deps.
Libraries books/arithmetic-4/ and books/rtl/rel7/ have been
eliminated from the default book certification (make regression),
in favor of new libraries books/arithmetic-5/ and books/rtl/rel8/
contributed by Robert Krug and Hanbing Liu, respectively. They and
Jun Sawada have arranged the compatibility of these libraries;
i.e., it is possible to evaluate both of the following in the same
session:
(include-book \"arithmetic-5/top\" :dir :system)
(include-book \"rtl/rel8/lib/top\" :dir :system)
Library books/rtl/rel1/ is no longer certified by default (though it
is still distributed in support of ACL2(r); see [real]).
EMACS SUPPORT
Slightly modified Control-t e (defined in emacs/emacs-acl2.el) to
comprehend the notion of an ``ACL2 scope'', and added Control-t o
to insert a superior [encapsulate] defining such a scope. See the
Emacs documentation for Control-t e (generally obtained after
typing Control-h k).
Modified distributed file emacs/emacs-acl2.el so that if you put the
following two forms in your ~/.emacs file above the form that loads
emacs/emacs-acl2.el, then Emacs will not start up a shell. Thanks
to Terry Parks for leading us to this modification.
(defvar acl2-skip-shell nil)
(setq acl2-skip-shell t)
EXPERIMENTAL HONS VERSION
Bob Boyer and others have contributed numerous changes for the
experimental ``hons'' version of ACL2 (see [hons-and-memoization]).
The ACL2 [state] can now be queried with (@ hons-enabled) so that a
result of t says that one is in the experimental hons version,
while nil says the opposite.")
(NOTE-3-5{R}
(RELEASE-NOTES)
"ACL2 Version 3.5(r) (May, 2009) Notes
Please also see [note-3-5] for changes in Version 3.5 of ACL2.
This release incorporates improvements from Ruben Gamboa in support
for non-standard analysis in ACL2(r), in the following ways:
ACL2(r) now supports non-classical objects that are not also numeric,
e.g., non-classical cons pairs. Consequently, the built-in
standard-numberp has been replaced with [standardp].
If f is a classical function, the value (f x1 ... xn) is guaranteed
to be standard when the xi are standard. ACL2(r) can now recognize
this fact automatically, using defun-std. For example, the
following can be used to assert that the square root of 2 is a
standard value.
(defthm-std sqrt-2-rational
(standardp (acl2-sqrt 2)))
More generally, the expression (f x1 ... xn) can contain free
variables, but the result is guaranteed to be standard when the
variables take on standard variables, as in the following:
(defthm-std sqrt-x-rational
(implies (standardp x)
(standardp (acl2-sqrt x))))
A potential soundness bug in [encapsulate] was fixed. Specifically,
when a classical, constrained function is instantiated with a
lambda expression containing free variables, it may produce
non-standard values depending on the values of the free variables.
This means that the functional instantiation cannot be used to
justify a non-classical theorem. For example, consider the
following sequence:
(encapsulate
((f (x) t))
(local (defun f (x) x)))
(defthm-std f-x-standard
(implies (standardp x)
(standardp (f x))))
(defthm plus-x-standard
(implies (standardp x)
(standardp (+ x y)))
:hints ((\"Goal\"
:use ((:functional-instance f-x-standard
(f (lambda (x) (+ x y))))))))
(defthm plus-x-eps-not-standard
(implies (standardp x)
(not (standardp (+ x (/ (i-large-integer)))))))
(defthm nil-iff-t
nil
:hints ((\"Goal\"
:use ((:instance plus-x-standard
(y (/ (i-large-integer))))
(:instance plus-x-eps-not-standard)))))
ACL2(r) also supports the introduction of non-classical functions
with [defchoose]. These behave just as normal functions introduced
with [defchoose], but they have a non-classical choice property.
Finally, ACL2(r) now comes with a revamped library supporting
non-standard analysis, still distributed separately as
books/nonstd/. The new library uses [defchoose] to state more
natural and useful versions of the IVT, MVT, etc. It also supports
the introduction of inverse functions, e.g., logarithms. Finally,
the library has much more extensive support for differentiation.")
(NOTE-3-6
(RELEASE-NOTES)
"ACL2 Version 3.6 (August, 2009) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 3.5 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, distributed books, Emacs
support, and experimental [hons-and-memoization] version. Each
change is described in just one category, though of course many
changes could be placed in more than one category.
Note that (starting with ACL2 Version 3.5) LispWorks is no longer
supported as a platform for ACL2, as the LispWorks compiler could
not handle the ACL2 sources; see comments in the ACL2 sources about
``function size'' being ``too large''.
CHANGES TO EXISTING FEATURES
In the [xargs] [declare] form, the function symbol (or symbols,
plural, in the case of [mutual-recursion]) being defined may now be
used in the specified :measure and :[guard] terms. Note that, the
definition(s) of the new symbol(s) are still not used in the
termination proof. Thanks to Daron Vroon for discussions leading to
this addition for the measure and to Dave Greve for requesting such
an enhancement for the guard.
Processing of the :guard-hints in an [xargs] [declare] form is now
delayed until the start of [guard] verification. As a result, the
function symbol(s) being defined may now be used as one might
expect in such hints, for example in an :in-theory form. Thanks to
Jared Davis for suggesting that we make such an improvement and
providing an example.
Made a low-level change to [make-event] in support of the ACL2s
utility ``dynamic-make-event''. Thanks to Peter Dillinger for
explaining the issue leading to this change.
Modified the failure message printed when a measure conjecture fails
to be proved, to indicate whether or not the hint :ruler-extenders
:all would create a different measure conjecture. Thanks to Peter
Dillinger for suggesting such a modification.
A call of [add-default-hints] had added hints to the end of the
current list of default hints. Now, it adds them to the beginning
of that list, so that they are tried first. However,
[add-default-hints] now takes a keyword argument, :at-end. If that
argument is supplied and evaluates to other than nil, then the
previous behavior occurs.
When [save-exec] is used to save ACL2 images, the build dates are now
printed on separate lines at startup and in the executable script.
Thanks To Bob Boyer for requesting some newlines.
[Forward-chaining] rules are now generated so that every [let] (also
[let*] and [lambda]) expression is expanded away, as is every call
of a so-called ``guard holder'' ([must-be-equal], [prog2$],
[ec-call], [the]). These were formerly only expanded away in the
conclusion. Thanks to Konrad Slind for a helpful email leading to
this change.
[Current-theory] now causes a hard error when applied to a name not
found in the current ACL2 logical [world], rather than simply
returning nil.
When the underlying Common Lisp is GCL, ACL2 no longer uses the #n=
reader macro when writing out certain files, including
[certificate] files. In all other Lisps, it now uses the #n=
``print-circle'' feature not only for [certificate] files and
``expansion.lsp'' files written for example in support of
[make-event], but also for files written in support of :[comp].
This is all managed with new [state] global variable
print-circle-files; see [print-control]. Thanks to Dave Greve for
pointing out that GCL is limited by default to 1024 indices for
#n=.
NEW FEATURES
A documentation topic explains in some detail how [hints] work with
the ACL2 proof ``waterfall'': see [hints-and-the-waterfall]. This
topic may be useful to those who write computed hints (see
[computed-hints]) or other advanced hints.
Added a new hint keyword, :no-thanks, that avoids printing the usual
``Thanks'' message for [hints]. Thanks to Peter Dillinger for
requesting this feature.
Added a new hint keyword, :backtrack, that checks the goals produced
by processing a goal, and can cause the goal to be re-processed
using a new hint. See [hints]. Thanks to Pete Manolios for a
conversation that led to the idea of this hint.
Added a new class of hints, [override-hints], that is similar to
[default-hints], except that override-hints are always applied,
even if the user has supplied a hint explicitly for the goal. See
[override-hints]. Thanks to Pete Manolios and Harsh Raju Chamarthi
for useful discussions on this topic, including its application to
testing.
When a goal ready to be pushed for proof by induction is given the
new hint ``:do-not-induct :otf'', it is indeed pushed for proof by
induction, rather than causing immediate failure as in the case of
the hint ``:do-not-induct t''. Instead, the proof fails when the
goal is later picked to be proved by induction. Thanks to Peter
Dillinger for discussions leading to this feature.
Related to computed hints only: Each history entry in the list stored
in variable HIST (see [computed-hints]) now has a :CLAUSE field,
which provide's access to a goal's parent, parent's parent, and so
on (within the same induction and forcing round only).
It is now possible to inhibit warnings produced by [in-theory]
[events] and [hints] that occur when certain built-in definitions
and executable-counterparts are disabled: just evaluate (assign
verbose-theory-warning nil). Thanks to Jared Davis (and probably
others in the past) for requesting such a mechanism.
HEURISTIC IMPROVEMENTS
A source function (linearize-lst) was replaced by tail-recursive
code, which can avoid a stack overflow. Thanks to Dave Greve for
sending a helpful example.
The heuristics for limiting [forward-chaining] have been slightly
relaxed, to allow derivations based on the occurrence of all
arguments of the forward-chaining rule's conclusion in the goal
(after stripping leading calls of NOT). Thanks to Dave Greve for
contributing this improvement and providing a motivating example.
We simplified induction schemes by eliminating each hypothesis of the
form (not (equal term (quote const))) for which some other
hypothesis in the same case equates term with some (presumably
other) quoted constant. Thanks to Dave Greve for requesting an
improvement of this sort.
BUG FIXES
Fixed a soundness bug related to redundancy of [encapsulate] events
(see [redundant-events]) and [ruler-extenders]. A proof of nil in
ACL2 Version 3.5 appears in a comment in (deflabel note-3-6 ...) in
the ACL2 source code. The fix is to insist that in order for one
[encapsulate] event to be redundant with another, they must be
evaluated with the same [default-ruler-extenders]. Analogous to
this issue of [default-ruler-extenders] for [encapsulate]s is an
issue of the [default-verify-guards-eagerness], which has similarly
been fixed.
Fixed soundness bugs related to the handling of
[subversive-recursions] for [constraint]s. Proofs of nil in ACL2
Version 3.5 appear in a comment in (deflabel note-3-6 ...) in the
ACL2 source code.
Fixed a bug that could cause the following error during calls of
[certify-book] in the presence of calls of [skip-proofs] in the
book:
ACL2 Warning [Skip-proofs] in
HARD ACL2 ERROR in FMT0: Illegal Fmt Syntax. The tilde-@ directive at
position 0 of the string below is illegal because its variable evaluated
to 0, which is neither a string nor a list.
\"~@0\"
Thanks to Dave Greve for reporting this bug and making available a
very helpful test case.
The :corollary of a rule (see [rule-classes]) failed to use the
[default-hints] of the logical [world]. This has been fixed.
(CCL only) We removed a call, for CCL 1.3 (and beyond) only, of
foreign function sync in the closing of output channels. Thanks to
Daron Vroon for reporting issues with such a call on a non-Intel
platform.
Fixed a bug in reporting failures when monitoring rewrite rules with
free variables in the hypotheses, that could cause a hard Lisp
error (from which ACL2 continues, however). Thanks to Eric Smith
for sending a very helpful example with his bug report.
Fixed the handling of :induct [hints], which had thrown away hint
information from parent goals. For example, the [thm] form below
failed to prove even though the second hint is in some sense
superfluous; induction occurs automatically at \"Goal'\" even without
the hint on that. The failure was due to discarding the hint
information on \"Goal\".
(in-theory (disable append))
(thm (equal (cdr (cons a (append (append x y) z))) (append x y z))
:hints
((\"Goal\" :in-theory (enable append))
(\"Goal'\" :induct t) ; failed unless this line is commented out
))
Fixed a bug in the [args] command that was failing to show the
formals of primitives (built-in functions like consp that do not
come with explicit definitions). Thanks to John Cowles for pointing
out this bug. (At a lower level, the bug was that primitives failed
to have 'stobjs-in or 'stobjs-out properties.)
Fixed bugs in the utility supporting moving directories of certified
books, sometimes used in Debian builds (as described in source
function make-certificate-file). Thanks to Alan Dunn for pointing
out such a bug, in paths associated with [defpkg] events in
[portcullis] commands in [certificate]s (which are used for error
reporting). There were also bugs, now fixed, that prevented
renaming some book paths. Please note that this mechanism is not
guaranteed to be sound; in particular, it can probably misbehave
when macros are used to generate portcullis events. However, it
seems likely that such issues will be very rare.
Eliminated warnings that could arise when tracing a function with
[trace$]. Now, when [trace$] is applied to a function without
option :native, that function's declarations and documentation are
discarded.
Fixed a bug that could cause a failure when building an executable
image using SBCL as the underlying Common Lisp. Thanks to Jun
Sawada for reporting this failure. We made a similar fix for CMUCL.
Fixed a bug in [save-exec] in the case that an absolute pathnanme is
supplied. Thanks to Jared Davis for bringing this bug to our
attention.
Fixed a bug in the use of [trace$] with the :native and :multiplicity
options that caused hard errors for some underlying Lisps.
Fixed a bug in the interaction of [trace$] and :[comp], which caused
error as [comp] tried to re-trace functions that it temporarily
untraced.
NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE
See {ReleaseVersionNumbers |
https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers}
for a list of books in Version 3.6 of ACL2 but not Version 3.5. For
changes to existing books rather than additions, see the {log
entries | http://code.google.com/p/acl2-books/source/list} starting
with revision r286 up through revision r329.
It is no longer required to specify a value for environment (or
`make') variable ACL2_SYSTEM_BOOKS when running `make' in the
distributed book directory, even when that directory is not under
the directory containing the ACL2 executable. Thanks to Peter
Dillinger for providing this improvement, by modifying
books/Makefile-generic and, as needed, distributed book Makefiles.
Thanks to Peter Dillinger, some books in support of the ACL2 Sedan
(ACL2s) are more easily available for ACL2 users who do not use
ACL2s. See [ACL2-sedan].
EMACS SUPPORT
If the following form is evaluated before the load of
emacs/emacs-acl2.el, then variables are now set to reflect the
directory containing that file.
(if (boundp '*acl2-sources-dir*)
(makunbound '*acl2-sources-dir*))
Fixed info-dir-entry line in generated info file (by patching
doc/write-acl2-texinfo.lisp). Thanks to Alan Dunn for providing
this patch.
EXPERIMENTAL HONS VERSION
Bob Boyer and others have contributed numerous changes for the
experimental ``hons'' version of ACL2 (see [hons-and-memoization]).
A number of these have been crafted to work specifically with CCL
(Clozure Common Lisp, formerly OpenMCL), which is now required as
the underlying Lisp for the ``hons'' version of ACL2.
A heuristic (source function too-many-ifs has been made more scalable
(for the non-HONS version as well, in fact), but with no functional
change. Thanks to Jared Davis for noticing performance issues and
suggesting fixes.
Other changes including the following, quoting Bob Boyer:
The CCL CASE macro now does better than a dumb linear search in some
CASEes.
SH and CSH are functions to talk to the underlying Gnu-Linux from
CCL. Good for repeated calling when you simply cannot afford
the copying cost of a FORK because you are using, say, a dozen
gigabytes.
Added CCL compiler-macros for IF and OR, to support some 'coverage'
analysis, cf. IF-REPORT, extending the profiling.
Introduced the type 'mfixnum' so that things like counting honses and
counting calls to memoized or profiled functions can run fast
in CCL 64 bits and yet still run at all under 32 bits.
Moved all HONSes to CCL's newish static space, which permits the
address of a cons to be used as a hash key, as in most Lisps.
(CCL moves most conses and most everything when it does a
compacting-gc.)
Quite a few changes in the memoize-fn reporting.
Added a timer facility, cf. call-with-timeout. Good for running under
throttle some gross thoughts like 'Is it true that you can't
fit 12 pigeons into 11 holes' on some propositional calculus
systems/functions.
Added rwx-size, pid-owner-cmdlines, rss, and proc-stat to help see
what is really going on virtually in Gnu-Linux.
Fixed at least one bug in compact-print-file and helped make its
integration into ACL2's read-object$ a little more sound. Still
worried some about *print-readably* vs. readtable-case. Does
anyone else stay awake late at night worrying about
readtable-case?
Revised how the *watch-dog-process* interrupts the main process for
the thousandth time, cf. watch. Haven't changed it in weeks,
which means that (a) it is getting tolerable or (b) I've run
out of gas.")
(NOTE-3-6-1
(RELEASE-NOTES)
"ACL2 Version 3.6.1 (September, 2009) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
The essential changes to ACL2 since Version 3.6 are the two bug fixes
described below. There was also some functionality-neutral code
refactoring, as requested by Daron Vroon in support of the ACL2
Sedan (see [ACL2-sedan]). Also see {ReleaseVersionNumbers |
https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers}
for a list of books in Version 3.6.1 of ACL2 but not Version 3.6.
For changes to existing books rather than additions, see the {log
entries | http://code.google.com/p/acl2-books/source/list} starting
with revision r329 up through revision 350.
Fixed a soundness bug in the handling of [ruler-extenders],
specifically in the handling of [let]-expressions. Thanks to Pete
Manolios, who sent us a proof of nil, essentially as follows. In
the termination proof for foo below, the binding of x to (cons t x)
was not substituted into the recursive call of foo for purposes of
the termination proof.
(defun foo (x)
(declare (xargs :ruler-extenders :all))
(let ((x (cons t x)))
(if (endp (cdr x))
x
(cons t (foo (cdr x))))))
(defthm foo-bad
nil
:hints ((\"Goal\"
:use ((:instance foo (x '(3))))
:in-theory (disable foo (foo))))
:rule-classes nil)
Fixed a typo in code supporting [ruler-extenders] (specifically,
swapped arguments in a recursive call of ACL2 source function
get-ruler-extenders2, which could cause problems for functions
defined using [mutual-recursion]). Thanks to Daron Vroon for
bringing this bug to our attention, pointing out the swapped
arguments.")
(NOTE-3-6{R}
(RELEASE-NOTES)
"ACL2 Version 3.6(r) (August, 2009) Notes
Please also see [note-3-6] for changes in Version 3.6 of ACL2.")
(NOTE-4-0
(RELEASE-NOTES)
"ACL2 Version 4.0 (July, 2010) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 3.6.1 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, distributed books, Emacs
support, and experimental versions. Each change is described in
just one category, though of course many changes could be placed in
more than one category. Also see [note-3-6-1] for other changes
since Version 3.6.
CHANGES TO EXISTING FEATURES
There have been extensive changes to the handling of compiled files
for books, which may generally be invisible to most users. The
basic idea is that when compiled files are loaded on behalf of
[include-book], they are now loaded before events in the book are
processed, not afterwards. This can speed up calls of include-book,
especially if the underlying Lisp compiles all definitions on the
fly (as is the case for CCL and SBCL). One functional change is
that for keyword argument :load-compiled-file of [include-book],
the values :comp-raw, :try, and :comp! are no longer legal. (Note
that the handling of :comp-raw was actually broken, so it seems
that this value wasn't actually used by anyone; also, the handling
of :comp! formerly could cause an error in some Lisp platforms,
including SBCL.) Another change is that if [include-book] is called
with :load-compiled-file t, then each sub-book must have a compiled
file or a so-called ``expansion file''; see [book-compiled-file].
In the unlikely event that this presents a problem, the makefile
provides a way to build with compilation disabled; see
[compilation]. Users of raw mode (see [set-raw-mode]) will be happy
to know that [include-book] now works if there an up-to-date
compiled file for the book, since [portcullis] commands are now
incorporated into that compiled file. The mechanism for saving
expansion files has changed, and the :save-expansion argument of
[certify-book] has been eliminated; see [certify-book]. More
discussion of ACL2's new handling of book compilation is described
in a new documentation topic; see [book-compiled-file].
It was possible to get a hard Lisp error when certifying a book with
a redundant [defconst] form whose term is not identical to the
existing [defconst] form for the same name. The following example
illustrates the problem, which has been fixed (as part of the
change in handling of compiled files for books, described above).
Imagine that after the initial (in-package \"ACL2\") form, file
foo.lisp has just the form (defconst *a* (append nil nil)). Then
before the fix, we could have:
ACL2 !>(defconst *a* nil)
[[output omitted]]
ACL2 !>(certify-book \"foo\" 1)
[[initial output omitted]
* Step 5: Compile the functions defined in \"/v/joe/foo.lisp\".
Compiling /v/joe/foo.lisp.
End of Pass 1.
End of Pass 2.
OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3
Finished compiling /vjoe/foo.lisp.
Loading /v/joe/foo.lisp
Error: Illegal attempt to redeclare the constant *A*.
The [wormhole] facility has been changed to repair a bug that allowed
guard violations to go undetected. The major change has to do with
the treatment of what used to be called the ``pseudo-flag''
argument which has been replaced by a quoted lambda expression. See
[note-4-0-wormhole-changes] for help in converting calls of
[wormhole]. Also see see [wormhole] and see [wormhole-eval].
The function assign-wormhole-output has been eliminated but its
functionality can be provided by [wormhole-eval].
The ACL2 tutorial has been greatly expanded, for example to include a
self-contained discussion of rewriting. See [ACL2-tutorial].
Formerly, the [mbe] macro and [must-be-equal] function were
disallowed in any definition within an encapsulate having a
non-empty signature. Now, these are allowed provided the definition
has been declared to be non-executable (see [defun-nx]). As a
result, [defevaluator] [events] may now include [must-be-equal]
among the function symbols known by the evaluator; this had not
previously been allowed. Thanks to Sol Swords for discussions
leading to this relaxation for [defevaluator].
[Princ$] now prints strings more efficiently. Thanks to Jared Davis
for suggesting the improvements to princ$.
The use of [xargs] declaration :non-executable t no longer requires
the absence of [state] or declared [stobj]s among the formal
parameters of a function definition. As before, the use of
:non-executable t turns off single-threadedness checking for the
body, and also as before, attempts to execute the function will
fail. Thanks to Sol Swords for requesting this relaxation (for
automatic generation of so-called ``flag functions'' for
definitions using [mutual-recursion]).
The [documentation] has been improved for explaining to advanced
users the details of the ACL2 hint mechanism; see
[hints-and-the-waterfall], and see the example about
nonlinearp-default-hint in distributed book
books/hints/basic-tests.lisp. Thanks to Robert Krug for useful
discussions, in particular suggesting the above example as one to
be explained with the documentation.
The time$ macro has been enhanced to allow user control of the timing
message that is printed, and of when it is printed. See [time$].
Thanks to Jared Davis for providing the essential design, helpful
documentation (largely incorporated), and an initial implementation
for raw Lisp.
The :ttags argument to [include-book] had been required when
including a certified book that uses trust tags. This is no longer
the case: essentially, :ttags defaults to :all except that warnings
will be printed. Thanks to Jared Davis for requesting such a
relaxation, and to him and Sandip Ray for useful discussions.
The definition of [mv-let] has been modified so that the single-step
macroexpansion (see [trans1]) of its calls can be evaluated. Thanks
to Pete Manolios for bringing this evaluation issue to our
attention and ensuing discussions.
All calls of so-called ``guard-holders'' --- [prog2$],
[must-be-equal] (from calls of see [mbe]), [ec-call], and [mv-list]
--- are now removed before storing hypotheses of rules of class
:[rewrite] or :[linear]. Thanks to Sol Swords for requesting this
enhancement and sending the following example in the case of
[rewrite] rules.
(defthm foo
(prog2$ (cw \"asdf\")
(and (equal (car (cons x y)) x)
(equal (cdr (cons x y)) y))))
The handling of [fmt] directive ~s has been modified so that if the
argument is a symbol that would normally be printed using vertical
bars (|), then that symbol is printed as with ~f. Thanks to Jared
Davis for providing the following example showing that treatment of
~s was a bit unexpected: (cw \"~s0.~%\" '|fo\\|o|).
Error messages have been improved for ill-formed terms (in ACL2's
so-called ``translation'' routines). Thanks to Jared Davis for
requesting such an enhancement.
Modified [defun-sk] so that it executes in :[logic] mode. Previously,
evaluation of a [defun-sk] event in :[program] mode caused a
somewhat inscrutable error, but now, :[program] mode is treated the
same as :[logic] mode for purposes of [defun-sk].
The ``system hacker'' commands ([redef+]) and ([redef-]) are now
embedded event forms (see [embedded-event-form]), hence may be used
in [books] as well as in [progn] and [encapsulate] [events]. Also,
these two commands are now no-ops in raw Lisp.
The function symbol worldp (in the \"ACL2\" package) has been renamed
to plist-worldp.
The function gc$-fn (resulting from macroexpansion of [gc$]) is now
in :[logic] mode. Thanks to Jared Davis for requesting this change.
The user now has control over whether compilation is used, for
example whether or not [certify-book] compiles by default, using
function set-compiler-enabled. See [compilation].
Modified the conversion of relative to absolute pathnames in
[portcullis] [command]s for book certification. Now, more pathnames
remain as relative pathnames.
The \"Ttags\" warning that can be printed by [include-book] is now
given even if [set-inhibit-output-lst] has specified `warning'. To
suppress it, specify warning! instead, for example,
(set-inhibit-output-lst '(acl2::warning! acl2::proof-tree)).
On occasion, ACL2 prints the message ``Flushing current installed
world'' as it cleans up when certain actions (installing a [world])
are interrupted. This operation has been sped up considerably. If
your session includes many [events], you can probably speed up any
such operation further by invoking [reset-prehistory]. Thanks to
Jared Davis for sending a query that led us to make this
improvement.
Calls of the form (ec-call (must-be-equal logic exec)) are no longer
allowed, since we do not have confidence that they would be handled
correctly.
The underlying function for [good-bye] (and hence for [exit] and
[quit]) is now in :[logic] mode. Thanks to Jared Davis for
requesting this enhancement.
We now require that every function symbol in the [signature] of an
[encapsulate] event have a :[logic] mode definition at the end of
the first pass, not merely a :[program] mode definition (which
formerly was sufficient). You can still define such a function in
:program mode, provided it is followed by a :logic mode definition
(where of course both definitions are [local], since we are
discussing functions is introduced in the [signature]). Thanks to
Carl Eastlund for bringing this issue to our attention. (Note: An
analogous modification has been made for :[bdd] [hints] as well.)
The following functions now have raw Lisp implementations that may
run faster than their ACL2 definitions: [assoc-eq], [assoc-equal],
[member-eq], [member-equal], subsetp-eq, [subsetp-equal],
[remove-eq], [remove-equal], [position-eq], and [position-equal].
Thanks to Jared Davis for suggesting that we consider such an
improvement.
We now avoid infinite loops caused when tracing functions that
implement [trace$]. Thanks to Rob Sumners and Eric Smith for useful
discussions.
The implementation of [trace!] has been modified slightly, to
accommodate the fix for ``some holes in the handling of trust
tags'' described later, below.
This item applies unless the host Lisp is GCL. An interrupt
(control-c) will now cause a proof to exit normally in most cases,
by simulating a timeout, as though [with-prover-time-limit] had
been called with a time-limit of 0. If the first interrupt doesn't
terminate the proof, a second one should do so (because a
different, more ``severe'' mechanism is used after the first
attempt). As a result, [redo-flat] should work as one might expect
even if a proof is interrupted. Thanks to Dave Greve for requesting
this enhancement to [redo-flat]. Technical note: for reasons
related to this change, time-limits are no longer checked in
evaluator functions (ev-fncall, ev, ev-lst, ev-fncall-w, ev-w, and
ev-w-lst).
It is now legal for [proof-checker] [macro-command]s to appear in
:[instructions] that are used in place of :[hints]. Thanks to
Sandip Ray for (most recently) requesting this feature.
The value of :command-conventions for [ld] special variable
ld-post-eval-print is now treated as though it were t if the value
[ld] special variable ld-error-triples is nil. The following
example illustrates this change.
ACL2 !>(ld-post-eval-print state) ; default
:COMMAND-CONVENTIONS
ACL2 !>(ld-error-triples state) ; default
T
ACL2 !>(set-ld-error-triples nil state)
*** Then, before the change:
ACL2 !>(mv t 3 state)
3
*** Instead, after the change:
ACL2 !>(mv t 3 state)
(T 3 <state>)
The default behavior of [ld] has been changed. Formerly when an error
occurred that halted a subsidiary call of ld, then the parent ld
would continue. That is no longer the case. Consider the following
example.
(ld '((ld '((defun f (x) x)
(defun bad (x)) ; ERROR -- missing the body
))
(defun g (x) x)))
Formerly, g would be defined in the resulting logical [world]. Now,
the error halts not only the inner ld but also the outer ld. See
[ld], and for details of the new default value for
:ld-error-action, :RETURN!, see [ld-error-action]. Also see the
paragraph below about a new utility, :[p!]. Thanks to Robert Krug
and Sandip Ray for helpful discussions.
Environment variable ACL2-CUSTOMIZATION has been replaced by
ACL2_CUSTOMIZATION --- that is, the hyphen has been replaced by an
underscore --- so that it can be set conveniently in the bash
shell. See [ACL2-customization].
The ``Warnings:'' summary is now omitted when there are no warnings,
where formerly ``Warnings: None'' was printed. Thanks to Jared
Davis for suggesting this change.
We have modified the generation of constraints for [encapsulate]
[events] in two primary ways, neither of them likely to affect many
users. One change is that the virtual movement of definitions and
theorems to in front of an [encapsulate] event, or of definitions
to behind that event, is no longer inhibited in the case of nested
encapsulates with non-empty [signature]s. The following example
illustrates the other change, as discussed below.
(encapsulate
((f (x) t))
(local (defun f (x) x))
(defun g (x) (cons x (f x)))
(defun h (x) (g x))
(defthm h-is-f (equal (car (h x)) x)))
Previously, the [constraint] on f and h was essentially the
conjunction of the definition of h and the theorem h-is-f. Now, the
definition of g is conjoined as well; moreover, g receives the same
[constraint] as do f and h, where previously g was only constrained
by its definition. While we are not aware of a soundness bug caused
by the previous approach, the new approach follows more precisely
the intended notion of [constraint].
The use of [trace$] (or [trace!]) option :multiplicity had been
required when option :native was supplied. This is no longer the
case. Also, a bug has been fixed that had prevented :multiplicity
from working properly in GCL and Allegro CL.
Several errors have been eliminated that formerly occurred when the
constraints for a function symbol were unknown because it was
constrained using a dependent clause-processor (see
[define-trusted-clause-processor]. Now, it is assumed that the
supporters argument in a [define-trusted-clause-processor] event is
such that every ancestor of any function symbol constrained by the
``promised encapsulate'' of that event among, or ancestral in,
those supporters. Thanks to Sol Swords, Sandip Ray, and Jared Davis
for helpful discussions.
The notion of [constraint] for functions introduced by [defun] has
been modified slightly. No longer do we remove from the body of the
definition calls of so-called ``guard-holders'': [prog2$],
[must-be-equal], [ec-call], and [mv-list], and uses of the-error
generated by [the]. Also, we now expand calls of the-error with the
same aggressive heuristics applied to a number of other functions
(technically, adding it to the list
*expandable-boot-strap-non-rec-fns*).
NEW FEATURES
A new event, [defattach], allows evaluation of calls of constrained
([encapsulate]d) functions. In particular, users can now, in
principle, soundly modify ACL2 source code; please feel free to
contact the ACL2 implementors if you are interested in doing so.
See [defattach].
Eric Smith has noticed that if you exit the [break-rewrite] loop
using :[a!] during an [ld] of a file, then all changes to the
logical [world] are discarded that were made during that call of
[ld]. A new utility, :[p!], pops just one level instead, and avoids
discarding that work. (This change is related to an item above,
``The default behavior of [ld] has been changed.'') Thanks to Eric
for pointing out this issue.
New function [mv-list] is the identity function logically, but
converts multiple values to lists. The first argument is the number
of values, so an example form is as follows, where foo returns
three values: (mv-list 3 (foo x y)). Thanks to Sol Swords for
requesting this feature and for reporting a soundness bug in one of
our preliminary implementations.
A new [state] global variable, host-lisp, has as its value a keyword
whose value depends on the underlying Common Lisp implementation.
Use (@ host-lisp) to see its value.
It is now possible to write [documentation] for HTML without error
when there are links to nonexistent documentation topics. See the
comments in macro acl2::write-html-file at the end of file
doc/write-acl2-html.lisp. When there are such errors, they should
be easier to understand than previously. Thanks to Alan Dunn for
providing the initial modifications.
It is now possible to inhibit specified parts of the Summary printed
at the conclusion of an event. See [set-inhibited-summary-types].
Also see [with-output], in particular the discussion of the new
:summary keyword. Thanks to Sol Swords for requesting more control
over the Summary.
A new :[hints] keyword, :case-split-limitations, can override the
default case-split-limitations settings (see
[set-case-split-limitations]) in the simplifier. Thanks to Ian
Johnson for requesting this addition and providing an initial
implementation.
It is now possible to defer and avoid some ttag-related output; see
[set-deferred-ttag-notes]. Thanks to Jared Davis for requesting
less verbosity from ttag-related output.
A new [command], :[pl2], allows you to restrict the rewrite rules
printed that apply to a given term. See [pl2]. Thanks to Robert
Krug for requesting such a capability.
ACL2 now provides a utility for canonicalizing filenames, so that
soft links are resolved; see [canonical-pathname]. Moreover, ACL2
uses this utility in its own sources, which can eliminate some
issues. In particular, [include-book] with argument :ttags :all no
longer breaks when given a book name differing from the book name
that was used at certification time; thanks to Sol Swords for
reporting that problem. Also, certain errors have been eliminated
involving the combination of packages in the certification world
and trust tags; thanks to Jared Davis for sending an example of
that problem.
You can now suppress or enable guard-checking for an individual form;
see [with-guard-checking]. Thanks to Sol Swords for requesting this
feature.
The [walkabout] utility has been documented (thanks to Rob Sumners
for suggesting this documentation). This utility can make it easy
to explore a large cons tree. New interactive commands (pp n) and
(pp print-level print-length) have been added to restrict how much
of the current object is displayed. See [walkabout].
Rules of class :[type-prescription] may now be provided a
:backchain-limit-lst keyword. The default behavior is unchanged,
but now [type-set] is sensitive not only to the new
:backchain-limit-lst of a :[type-prescription] rule (if supplied)
but to the [default-backchain-limit] of the current logical
[world]. Setting of backchain-limits can now specify either the new
(type-set) limit or the old limit (for rewriting); see
[set-default-backchain-limit] and see [set-backchain-limit].
Moreover, the functions [default-backchain-limit] and
[backchain-limit] now take a second argument of :ts or :rewrite to
specify which backchain-limit is desired.
HEURISTIC IMPROVEMENTS
The so-called ``too-many-ifs'' heuristic has been modified. Such a
heuristic has been employed in ACL2 (and previous Boyer-Moore
provers) for many years, in order to limit the introduction of
calls of [if] by non-recursive functions. Most users need not be
concerned with this change, but two proofs in the regression suite
(out of thousands) needed trivial adjustment, so user proofs could
need tweaking. In one application, this modification sped up proofs
by 15%; but the change in runtime for the regression suite is
negligible, so such speedups may vary. Thanks to Sol Swords for
providing a test from ACL2 runs at Centaur Technology, which was
useful in re-tuning this heuristic.
Guard proof obligations could have size quadratic in the number of
clauses in a [case] statement. This inefficiency has been removed
with a change that eliminates a hypothesis of the form (not (eql
term constant)) when there is already a stronger hypothesis,
equating the same term with a different constant. Thanks to Sol
Swords for bringing this problem to our attention and suggesting an
alternate approach to solving it, which we may consider in the
future if related efficiency problems persist.
We adjusted the heuristics for determining induction schemes in the
presence of [ruler-extenders], when handling calls of a function
symbol that is a ruler-extender, in either of two cases: either the
function takes only one argument; or the function is [prog2$] or
[ec-call], and the first argument contains no recursive call. These
cases are treated more directly as though the ruler-extender call
is replaced by the unique (in the case of [prog2$] and [ec-call],
the second) argument.
A new :[type-prescription] rule, true-listp-append, has been added:
(implies (true-listp b)
(true-listp (append a b)))
If you are interested in the motivation for adding this rule, see
comments in true-listp-append in ACL2 source file axioms.lisp.
The use of :forward-chaining lemmas has been improved slightly. In
previous versions, a conclusion derived by forward chaining was
discarded if it was derivable by type-set reasoning, since it was
``already provable.'' But this heuristic prevented the conclusion
from triggering further forward chaining. This has been fixed.
Thanks to Dave Greve for pointing out this problem.
The fundamental utility that turns an IF expression into a set of
clauses has been optimized to better handle tests of the form
(equal x 'constant) and their negations. This eliminates an
exponential explosion in large case analyses. But it comes at the
inconveience of sometimes reordering the clauses produced. The
latter aspect of this change may require you to change some Subgoal
numbers in proof hints. We apologize for the inconvenience.
Certification can now run faster (specifically, the compilation
phase) for books with very large structures generated by
[make-event], when there is significant sharing of substructure,
because of a custom optimization of the Lisp reader. Thanks to Sol
Swords for bringing this efficiency issue to our attention.
Jared Davis reported inefficiency in certain [make-event] evaluation
due to a potentially expensive ``bad lisp object'' check on the
expansion produced by the make-event. This check has been
eliminated except in the case that the expansion introduces
packages (for example, by including a book during the expansion
phase that introduces packages). Thanks to Jared for providing a
helpful example.
The application of rules of class :[induction] had the potential to
loop (as commented in ACL2 source function apply-induction-rule).
This has been fixed. Thanks to Daron Vroon and Pete Manolios for
sending nice examples causing the loop.
Heuristics have been tweaked so that false goals may be simplified to
nil that had formerly been left unchanged by simplification,
perhaps resulting in useless and distracting proofs by induction.
Thanks to Pete Manolios for pointing out this issue by sending the
following example: (thm (<= (+ 1 (acl2-count x)) 0)). (Technical
explanation: When every literal in a clause simplifies to nil, even
though we might not normally delete one or more such literals, we
will replace the entire clause by the false clause.)
Improved the efficiency of the built-in function, [take]. Thanks to
Bob Boyer for suggesting this improvement.
ACL2 can now use evaluation to relieve hypotheses when applying
:[type-prescription] rules. Thanks to Peter Dillinger and Dave
Greve for requesting this enhancement, and to Robert Krug for a
relevant discussion long ago.
Evaluation has been sped up during theorems for calls of [mv-let], by
avoiding repeated evaluation of the expression to which its
variables are bound. Thanks to Sol Swords for requesting this
improvement and sending an illustrative example.
Modified a heuristic to avoid the opening up non-recursive function
calls on calls of [hide] involving [if]-expressions. For example,
the [thm] form below is now admitted
(defun bar (x)
(cons x x))
(thm (equal (bar (hide (if a b c)))
(cons (hide (if a b c)) (hide (if a b c)))))
BUG FIXES
Fixed a soundness bug in destructor elimination, which was preventing
some cases from being generated. Thanks to Eric Smith for reporting
this bug and sending a helpful example. (Technical detail: the
fixes were in ACL2 source functions apply-instantiated-elim-rule
and eliminate-destructors-clause1, and comments in the former
contain Eric's example.)
Fixed a bug that supported a proof of nil by exploiting the fact that
[portcullis] [command]s were not included in check-sum computations
in a book's [certificate]. For such a proof of nil, see the
relevant comment in the ACL2 source file ld.lisp under (deflabel
note-4-0 ...).
Changed the implementation of [add-include-book-dir]. The previous
implementation could allow relative pathnames to be stored in the
[portcullis] [command]s of [certificate]s of [books], which perhaps
could lead to unsoundness (though we did not try to exploit this to
prove nil). Thanks to Jared Davis for reporting a bug in our first
new implementation. An additional change to both
[add-include-book-dir] and [delete-include-book-dir] is that these
now work in raw-mode (see [set-raw-mode]). (Thanks to Dave Greve
for suggesting a reduction in the warnings we produced related to
raw-mode.) Note that it is no longer permitted to make a direct
call of the form (table acl2-defaults-table :include-book-dir-alist
...); use [add-include-book-dir] instead.
Fixed a soundness bug related to [xargs] keyword :non-executable. New
macros, defun-nx and defund-nx, have been provided for declaring
functions to be non-executable; see [defun-nx]. While we expect
this bug to occur only rarely if at all in practice, the following
example shows how it could be evoked.
;;;;;;;;;;;;;;;;;;;;
;;; Book sub.lisp
;;;;;;;;;;;;;;;;;;;;
(in-package \"ACL2\")
(defun f ()
(declare (xargs :guard t
:non-executable t))
(mv-let (a b c)
(mv 3 4)
(declare (ignore a b))
c))
(defun g ()
(declare (xargs :guard t))
(prog2$ (mv-let (x y z)
(mv 2 3 4)
(declare (ignore x y z))
nil)
(f)))
(defthm g-nil
(equal (g) nil)
:hints ((\"Goal\" :in-theory (disable (f))))
:rule-classes nil)
;;;;;;;;;;;;;;;;;;;;
;;; Book top.lisp
;;;;;;;;;;;;;;;;;;;;
(in-package \"ACL2\")
(include-book \"sub\")
(defthm contradiction
nil
:hints ((\"Goal\" :use g-nil))
:rule-classes nil)
The modification described above pertaining to [defun-nx] also
prevents execution of non-executable functions that have been
[trace]d. The following example illustrates the problem; now, the
following [defun] of g is illegal, and the problem disappears if
[defun-nx] is used instead.
(defun g (x) ; Use defun-nx to avoid an error after Version_3.6.1.
(declare (xargs :guard t :non-executable t))
x)
(g 3) ; causes error, as expected
(trace$ g)
(g 3) ; returned 3 before the bug fix; after fix, causes error as expected
A hard error was possible when attempting to include an uncertified
book containing [events] of the form (make-event '(local ...)).
This has been fixed. Thanks to Sol Swords for bringing this issue
to our attention.
Fixed a bug in the heuristic improvement described for Version_3.6
(see [note-3-6]) as ``We simplified induction schemes....'' The bug
had prevented, in unusual cases such as the following (notice the
impossible case), a proof by induction.
(defun foo (a x)
(and (consp x)
(case a
(0 (foo (car x) (cdr x)))
(1 (foo (cdr x) (car x)))
(0 (foo a (cons x x))))))
(in-theory (disable (:type-prescription foo)))
(thm (atom (foo a x)))
Macro [cw-gstack] did not work with an :evisc-tuple argument. This
has been fixed by changing cw-gstack so that it now evaluates its
arguments. Thanks to Sol Swords for bringing this bug to our
attention.
Fixed a bug in :[pso] during the printing of failure messages for
termination proofs.
Fixed a bug in the handling of #. (see [sharp-dot-reader]). Thanks to
Bob Boyer for bringing this bug to our attention.
Replaced a hard Lisp error with a clean error, in certain cases that
a :[hints] value is erroneously supplied as a non-nil atom.
Example: (thm (equal x x) :hints 3).
Fixed a bug in the interaction of function tracing with conversion of
a function from :[program] to :[logic] mode. The following example
illustrates what had been wrong.
(defun f (x)
(declare (xargs :mode :program))
(car x))
(f 3) ; raw Lisp hard error
(trace$ f)
(f 3) ; raw Lisp hard error (still)
(defun f (x) (car x)) ; upgrade f to :logic mode
(f 3) ; clean guard violation; f is no longer traced
(trace$) ; uh oh - f is shown as traced
(untrace$ f)
(f 3) ; OUCH: hard Lisp error because old :program mode definition of
; the executable counterpart (sometimes called *1*f) was restored!
Made a fix so that when building ACL2 with `make' option
ACL2_SAFETY=3, there will no longer be any safety-0 compiled code
generated. Thanks to Gary Byers for bringing this bug to our
attention.
Fixed a bug in the handling of [override-hints] that generate custom
keyword hints (see [custom-keyword-hints]) involving the variable
stable-under-simplificationp. Thanks to Ian Johnson for bringing
this bug to our attention with explanation that included a helpful
example, included as comment in the ACL2 source code for function
apply-override-hint.
The saved_acl2 script in CLISP could contain unexpected characters
where simple newlines were expected. Dave Greve found this in a
Cygwin environment on Windows. Thanks to Dave for reporting this
bug and experimenting with a fix, and thanks to the CLISP folks for
providing helpful information.
Fixed a bug that could make :[oops] cause an error. Also, the [oops]
command can no longer take you back before a [reset-prehistory]
event.
(GCL only) Fixed a bug that could occur when calling trace in raw
Lisp in GCL.
Proof summaries have been improved, so that they account for [rune]s
used in rewriting that takes place when generating goals to be
proved in a forcing round. Thanks to Jared Davis for sending us an
example illustrating this issue.
Fixed a bug that (at least in CCL) could put extra backslashes (`\\')
in a pathname that ACL2 writes out to the executable script created
by a build. Thanks to Gary Byers for explaining that the CCL
behavior is legal (for our previous use of Common Lisp function
merge-pathnames).
We closed some holes in the handling of trust tags (also known as
``ttags''; see [defttag]) by [include-book]. The following example
illustrates this rather subtle situation. Consider the following
book.
(in-package \"ACL2\")
(make-event
(er-progn
(encapsulate
()
(defttag :foo)
(value-triple \"Imagine something bad here!\"))
(value '(value-triple :some-value)))
:check-expansion t)
Formerly, the following commands succeeded.
(certify-book \"test3\" 0 t :ttags :all)
:u
(include-book \"test3\" :ttags nil)
But because of [make-event] keyword argument :check-expansion t, we
know that the event (defttag :foo) is evaluated by the above
[include-book] form, and hence the :ttags argument of include-book,
above, should have specified :foo. The problem was that [defttag]
forms evaluated during [make-event] expansion did not contribute to
the trust tag information stored in the book's [certificate]. Note:
Because of this change, one should avoid using [make-event] with
:check-expansion t when the expansion would introduce a [defttag]
event during [include-book] but not [certify-book] time. For an
example illustrating this issue, see [make-event-details],
specifically the new version of the section labeled ``A note on
ttags'' at the end of that [documentation] topic.
Closed a small loophole that had the potential, in rare
circumstances, to violate atomicity of under-the-hood updates for
ACL2 [arrays].
The following example was formerly allowed, but resulted in a
guard-verified function (here, g) whose guard proof obligation is
not a theorem outside the [encapsulate] event. We now disallow
[guard] verification for functions introduced non-[local]ly inside
an [encapsulate] event unless we determine that the proof
obligations hold outside the [encapsulate] event as well.
(encapsulate
((f (x) t))
(local (defun f (x) (declare (xargs :guard t)) (consp x)))
;; ERROR!
(defun g (x)
(declare (xargs :guard (f x)))
(car x)))
The use of :[comp] on [stobj] functions had potentially caused a hard
Lisp error; for example, this could occur when (defstobj foo fld)
was followed by :comp foop. This has been fixed.
Fixed a bug that could cause a raw Lisp error when the first argument
of [with-local-stobj] is not a symbol.
It had been possible to use the reserved keyword
:computed-hints-replacement as the name of a custom keyword hint
(see [custom-keyword-hints]). This has been fixed. Thanks to Dave
Greve, who pointed out a confusing hint error message (which has
also been fixed) that led us to this issue.
Fixed a bug that could cause a hard Lisp error, instead of a graceful
ACL2 error, if keyword :backchain-limit-lst in a rule class is
given a cons that is not a true list, such as (1 . 1).
Eliminated an error that could occur when redefining a function as a
macro and then compiling, as in the example below.
(defun foo (x) x)
:redef!
(defmacro foo (x) x)
:comp t
Thanks to Eric Smith for sending the above example in his bug report.
Fixed a bug that could result in an assertion when a
[clause-processor] causes an error.
NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE
See the {log entries |
http://code.google.com/p/acl2-books/source/list} for a record of
books changed or added since the preceding release, with log
entries.
We note in particular the new system/ directory, which begins to
specify ACL2 system code in anticipation of opening the
architecture of ACL2 (see [defattach] for a relevant tool). Some
system functions were changed slightly (but with the expectation of
not generally affecting ACL2 behavior) in support of the
development of this directory. Those interested in contributing to
further such efforts are invited to contact the ACL2 implementors.
New utilities have been provided for certifying most of the
distributed books with more `make'-level parallelism. For example,
we have obtained close to a 12x reduction in time by using `make -j
24 regression-fast' on a 24-processor machine. For more information
see books/make-targets, or to include the books/workshops in the
regression run, see books/regression-targets. Thanks to Sol Swords
for providing these nice utilities.
The top-level makefile, GNUmakefile, has been fixed so that the build
processes (which are inherently sequential) will ignore the -j
option of `make'. Note that regressions can still, however, be done
in parallel, as the -j option will be passed automatically to the
appropriate `make' command.
EMACS SUPPORT
EXPERIMENTAL VERSIONS
The HONS version, supported primarily by Bob Boyer and Warren Hunt
(see [hons-and-memoization]), has undergone numerous improvements.
For example, keyword argument :FORGET is now supported when calling
[memoize] from within the ACL2 loop, and system function worse-than
is [memoize]d with the :condition that both terms are function
applications (clearing the memo-table after each prover
invocation). Thanks to Jared Davis and Sol Swords for investigating
the memoization of worse-than, and with suitable condition. Thanks
also to Jared Davis for contributing structural modifications to
the implementation of [hons].
David Rager contributed modifications to the parallel version (see
[parallelism]), which include taking advantage of atomic increments
available at least since Version 1.0.21 of SBCL and Version 1.3 of
CCL.
Subtopics
[Note-4-0-wormhole-changes]
How to convert calls of wormhole for Version 4.0")
(NOTE-4-0-WORMHOLE-CHANGES
(NOTE-4-0)
"How to convert calls of wormhole for Version 4.0
Here we describe how to convert an ``old-style'' call of [wormhole]
--- that is, a call suitable for ACL2 versions preceding 4.0 --- in
which the pseudo-flag was t. In order to convert such a call
(wormhole t 'name input form ...)
to a new-style call, the following steps must be carried out. Note
that the wormhole name must always be quoted now.
First, eliminate the first argument, t, and add a new second argument
that is the quoted lambda expression
'(lambda (whs) (set-wormhole-entry-code whs :ENTER))
Setting the entry code to :ENTER is not necessary if you maintain the
invariant (after initialization) that it is always :ENTER. In that
case, the simpler quoted lambda will suffice:
'(lambda (whs) whs)
Second, change the form argument so that instead of talking about the
state-global variable wormhole-output it talks about the
state-global variable wormhole-status. Look for (@
wormhole-output), (assign wormhole-output ...), (f-get-global
'wormhole-output ...) and (f-put-global 'wormhole-output ...) in
form and replace them with expressions involving wormhole-status.
However, remember that the old data stored in wormhole-output is now
in the wormhole-data component of the wormhole-status. Thus, for
example, an old use of (@ wormhole-output) will typically be
replaced by (wormhole-data (@ wormhole-status)) and an old use of
(assign wormhole-output ...) will typically be replaced by
(assign wormhole-status (set-wormhole-data (@ wormhole-status) ...))
In summary, an old-style call like
(wormhole t 'name
input
'(...1 (@ wormhole-output) ...2
...3 (assign wormhole-output ...4) ...5)
...6)
can become
(wormhole 'name
'(lambda (whs) (set-wormhole-entry-code whs :ENTER))
input
'(...1 (wormhole-data (@ wormhole-status)) ...2
...3 (assign wormhole-status
(set-wormhole-data (@ wormhole-status)
...4) ...5)
...6)
In any case, and especially if your wormhole call had a pseudo-flag
other than t, we recommend that you see [wormhole].")
(NOTE-4-0{R}
(RELEASE-NOTES)
"ACL2 Version 4.0(r) (July, 2010) Notes
Please see [note-4-0] for changes in Version 4.0 of ACL2.")
(NOTE-4-1
(RELEASE-NOTES)
"ACL2 Version 4.1 (September, 2010) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 4.1 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, distributed books, Emacs
support, and experimental versions. Each change is described in
just one category, though of course many changes could be placed in
more than one category.
CHANGES TO EXISTING FEATURES
The [guard] associated with calls of the macro, [search], has been
weakened so that now, given strings are no longer restricted to
contain only standard characters unless the :test argument is
[char-equal].
Modified the writing of ``hidden [defpkg]'' forms into [certificate]
files (see [hidden-defpkg]), to support moving certificate files
for distributed books, as is done by ACL2s (see [ACL2-sedan]) and
Debian releases of ACL2. Thanks to Camm Maguire for reporting a
problem with Debian releases of ACL2 that led to this change.
Expanded the constant *acl2-exports* by adding intersection-equal to
the list. Thanks to Jared Davis for requesting this change.
The :[comp] utility now compiles functions that have code
conditionalized for raw Lisp only (presumably because a trust tag
was active when they were defined). Previously, this was not the
case when :comp was applied to more than a single function symbol.
NEW FEATURES
A new macro, [top-level], allows evaluation directly in the top level
loop for forms that normally need to be evaluated inside function
bodies, such as [with-local-stobj]. See [top-level]. Thanks to
Jared Davis for requesting such a utility.
Added [count], a Common Lisp function, to ACL2. In support of that
addition, also added rewrite rule eqlablep-nth.
HEURISTIC IMPROVEMENTS
[None this time.]
BUG FIXES
We fixed a soundness bug that could occur when a function that
returns multiple values that is called in its own guard. Thanks to
Sol Swords for reporting this bug and sending a small
self-contained example, which is included in a comment in the
function chk-acceptable-defuns1 in ACL2 source file defuns.lisp.
It was possible to cause an error when giving theory hints during
redefinition of functions. This has been fixed. Thanks to Ian
Johnson for sending an example that nicely illustrated this
problem.
Fixed system function io? for the case that formal parameter commentp
is t and vars is non-empty. Thanks to David Rager for bringing to
our attention the fact that io? was broken for such a combination
of parameters.
Not exactly a bug fix, but: [defun-sk] was breaking when a :[guard]
is specified, so we have improved the documentation (see
[defun-sk]) to explain how to provide verified guards for a
function introduced by [defun-sk]. Thanks to Jared Davis for
bringing this issue to our attention.
Made a fix to the handling of interrupts, which in rare cases might
have left one in a state where all subsequent proof attempts were
labeled as ``Aborting due to an interrupt''.
Fixed :[pso] and related utilities, so that when proof output is
redirected to a file, all summary output goes to that file rather
than to the terminal.
(GCL on Windows only) Removed an inappropriate check, resulting in an
error about ``pathname-device,'' that could prevent Windows GCL
builds of ACL2. Thanks to Camm Maguire for reporting this problem
and a helpful discussion.
(Windows only) Modified the computation of canonical pathnames to
avoid issues of case-insensitivity, in particular for the drive
(e.g., \"C:\" vs. \"c:\"). Thanks to Harsh Raju Chamarthi for reporting
this issue and helping with its debugging.
(Windows only) The value of (@ distributed-books-dir) no longer will
be missing the Windows drive prefix, for example, \"C:\". Thanks to
Harsh Raju Chamarthi for reporting this issue and helping with its
debugging.
NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE
See the {log entries |
http://code.google.com/p/acl2-books/source/list} for a record of
books changed or added since the preceding release, with log
entries.
Modified books/Makefile-generic by adding a new BOOKS_SKIP_COMP
variable, which is used in Makefiles in some subdirectories of
books/, in order to avoid errors when compiling certified books for
multiple Lisps.
EMACS SUPPORT
Distributed file emacs/emacs-acl2.el has been modified so that the
forms control-t e and control-t control-e now pick up package
markers (see [sharp-bang-reader]), in the following sense: if the
top-level form is preceded by a line starting with #!, then that
line is included in the inserted string. Thanks to Jared Davis for
suggesting this enhancement and providing a preliminary
implementation.
EXPERIMENTAL VERSIONS
For the HONS version there have been some changes to [memoize]:
[Memoize] accepts a new keyword, :recursive, that is a synonym for
the existing keyword :inline. Thanks to Sol Swords for
requesting this addition. Moreover, it is now enforced that
these keywords have Boolean values.
[Memoize] may now be called on :[program] mode functions. Thanks to
Sol Swords for requesting this enhancement.
A bug has been fixed. Now, if [memoize] is called with a
:condition-fn (with value other than nil or t), then the
[guard] of the memoized function and the :condition-fn must be
the same. Previously, one could exploit the lack of such a
check to get a hard Lisp error, for example as follows.
(defun f (x) (declare (xargs :guard t)) x)
(defun cf (x) (declare (xargs :guard (consp x))) (car x))
(memoize 'f :condition-fn 'cf)
(f 3)
Memoization is now illegal for built-in functions that use underlying
raw Lisp in their implementations. To see why, consider the
form (gc$), which is a macro call expanding to (gc$-fn nil).
Previously, after evaluation of (memoize 'gc$-fn), a call of
gc$ would no longer call the garbage collector, which had been
invoked by raw Lisp code. Now, evaluation of (memoize 'gc$-fn)
causes an error.")
(NOTE-4-1{R}
(RELEASE-NOTES)
"ACL2 Version 4.1(r) (September, 2010) Notes
Please see [note-4-1] for changes in Version 4.1 of ACL2.")
(NOTE-4-2
(RELEASE-NOTES)
"ACL2 Version 4.2 (January, 2011) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 4.2 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, distributed books, Emacs
support, and experimental versions. Each change is described in
just one category, though of course many changes could be placed in
more than one category.
CHANGES TO EXISTING FEATURES
The [accumulated-persistence] utility can now do finer-grained
tracking, providing data for individual hypotheses and the
conclusion of a rule. See [accumulated-persistence]. To try this
out, evaluate the form (accumulated-persistence :all); then see
[accumulated-persistence] for a discussion of display options using
show-accumulated-persistence. Thanks to Dave Greve for suggesting
this new capability and collaborating on its design and
implementation.
The [defattach] utility now permits the use of :[program] mode
functions, though this requires the use of a trust tag (see
[defttag]). See [defattach] and for discussion of the new
capability, see [defproxy], which explains how part of this change
involves allowing :[program] mode functions to be declared
[non-executable].
Redefinition (see [ld-redefinition-action]) is no longer permitted
for functions that have attachments (see [defattach]). In such
cases, the attachment must be removed first, e.g. with (defattach
foo nil).
Made small changes to [mv-nth] and [defun-sk] in order to permit
guard verification of functions introduced with more than one
quantified variable in a [defun-sk] form. The change to [mv-nth] is
to weaken the [guard] by eliminating the requirement that the
second argument satisfy [true-listp], and replacing the call of
[endp] in the definition body by a corresponding call of [atom].
The new definition of [mv-nth] is thus logically equivalent to the
old definition, but with a weaker guard. Thanks to Sol Swords for
sending the following example, for which the final [verify-guards]
form had failed but now succeeds.
(defstub foo (a b c) nil)
(defun-sk forall-a-b-foo (c)
(forall (a b) (foo a b c))
:witness-dcls ((declare (Xargs :guard t
:verify-guards nil))))
(verify-guards forall-a-b-foo)
The implementations of [prog2$], [time$], [with-prover-time-limit],
[with-guard-checking], [mbe] (and [must-be-equal]), and [ec-call]
have changed. See the discussion below of the new utility,
[return-last]. A consequence is that [trace$] is explicitly
disallowed for these and related symbols, which formerly could
cause hard Lisp errors, because they are now macros. Tracing of
return-last is also disallowed. Another consequence is that time$
now prints a more abbreviated message by default, but a version of
the old behavior can be obtained with :mintime nil.
The following utilities no longer print an observation about raw-mode
transitions: set-raw-mode-on, [set-raw-mode-on!], [set-raw-mode],
and set-raw-mode-off. Thanks to Jared Davis for suggestion this
change in the case of [include-book] (which proved awkward to
restrict to that case).
The system function translate-and-test now permits its LAMBDA form to
refer to the variable WORLD, which is bound to the current ACL2
logical [world].
Modified abort handling to avoid talking about an interrupt when the
error was caused by a Lisp error rather than an interrupt.
The value of the constant *acl2-exports*, which is still a list, has
been extended significantly, though only with the addition of
symbols that one might reasonably have expected all along to belong
to this list. A new distributed book,
books/misc/check-acl2-exports.lisp, checks (at certification time)
that no documented constant, macro, or function symbol in the
\"ACL2\" package has been accidentally omitted from *acl2-exports*.
Thanks to Dave Greve for helpful discussions related to this
change.
Improved the built-in `untranslate' functions to produce let*
expressions when appropriate (more to help with tools that call
untranslate and the like, than to help with proof output).
The utility [redo-flat] now works for [certify-book] failures, just
as it continues to work for failures of [encapsulate] and [progn].
The following only affects users who use trust tags to add to list
values of either of the [state] global variables
program-fns-with-raw-code or logic-fns-with-raw-code. For functions
that belong to either of the above two lists, trace$ will supply a
default value of :fncall to keyword :notinline, to avoid discarding
raw-Lisp code for the function.
The [guard] of the macro [intern] has been strengthened so that its
second argument may no longer be either the symbol
*main-lisp-package-name* or the string \"COMMON-LISP\". That change
supports another change, namely that the following symbols in the
\"COMMON-LISP\" package are no longer allowed into ACL2: symbols in
that package that are not members of the list constant
*common-lisp-symbols-from-main-lisp-package* yet are imported into
the \"COMMON-LISP\" package from another package. See [pkg-imports]
and see [symbol-package-name]. To see why we made that change,
consider for example the following theorem, which ACL2 was able to
prove when the host Lisp is GCL.
(let ((x \"ALLOCATE\") (y 'car))
(implies (and (stringp x)
(symbolp y)
(equal (symbol-package-name y)
\"COMMON-LISP\"))
(equal (symbol-package-name (intern-in-package-of-symbol x y))
\"SYSTEM\")))
Now suppose that one includes a book with this theorem (with
:[rule-classes] nil), using an ACL2 built on top of a different
host Lisp, say CCL, that does not import the symbol
SYSTEM::ALLOCATE into the \"COMMON-LISP\" package. Then then one can
prove nil by giving this theorem as a :use hint.
The axioms introduced by [defpkg] have changed. See the discussion of
[pkg-imports] under ``NEW FEATURES'' below.
The error message for free variables (e.g., in definition bodies and
guards) now supplies additional information when there are
governing IF conditions. Thanks to Jared Davis for requesting this
enhancement and collaborating in its design.
The command :[redef-] now turns off redefinition.
Improved proof output in the case of a :[clause-processor] hint that
proves the goal, so that the clause-processor function name is
printed.
The [proof-checker] command `then' now stops at the first failure (if
any).
It is no longer permitted to submit definitions in :logic mode for
merely part of an existing [mutual-recursion] event. Such an action
left the user in an odd state and seemed a potential soundness
hole.
The function [break$] is now in :[logic] mode. Thanks to Jared Davis
for requesting this enhancement.
The macro [verify-termination] now provides clearer output in the
case that it is redundant. More important perhaps, as a courtesy it
now causes an error when applied to a constrained function, since
presumably such an application was unintended (as the constrained
function could never have been in :[program] mode). Note that if
one desires different behavior, one can create one's own version of
[verify-termination] (but with a different name).
Improved the [guard]s for the following functions, often weakening
them, to reflect more precisely the requirements for calling [eq]:
alist-difference-eq, intersection-eq, intersection1-eq,
[intersectp-eq], not-in-domain-eq, set-difference-assoc-eq,
set-equalp-eq, and [union-eq]. Thanks to Jared Davis for pointing
out this issue for [intersectp-eq].
(CCL only) Made a change that can reduce the size of a compiled file
produced by [certify-book] when the host Lisp is CCL, by discarding
source information (for example, discarding [local] events).
NEW FEATURES
See the discussion above about new statistics that can be gathered by
the [accumulated-persistence] utility.
A new hint, :[instructions], allows use of the [proof-checker] at the
level of [hints] to the prover. Thanks to Pete Manolios for
requesting this feature (in 2001!). See [instructions].
(For system hackers) There are new versions of system functions
translate1 and translate, namely translate1-cmp and translate-cmp
respectively, that do not take or return [state]. See the Essay on
Context-message Pairs for relevant information. Thanks to David
Rager for collaborating on this enhancement.
A new utility, [return-last], is now the unique ACL2 function that
can pass back a multiple value result from one of its arguments.
Thus, now the following are macros whose calls ultimately expand to
calls of [return-last]: [prog2$], [time$],
[with-prover-time-limit], [with-guard-checking], [mbe] (and
[must-be-equal]), and [ec-call]. With an active trust tag, an
advanced user can now write code that has side effects in raw Lisp;
see [return-last]. Thanks to Jared Davis for requesting this
feature.
A new function, [pkg-imports], specifies the list of symbols imported
into a given package. The axioms for [defpkg] have been
strengthened, taking advantage of this function. Now one can prove
theorems using ACL2 that we believe could not previously be proved
using ACL2, for example the following.
(equal (symbol-package-name (intern-in-package-of-symbol str t))
(symbol-package-name (intern-in-package-of-symbol str nil)))
Thanks to Sol Swords for a helpful report, which included the example
above. See [pkg-imports] and see [defpkg].
Added function [no-duplicatesp-eq].
Added a new hint keyword, :[backchain-limit-rw], to control the level
of backchaining for [rewrite], [meta], and [linear] rules. This
overrides, for the current goal and (as with :[in-theory] hints)
descendent goals, the default [backchain-limit] (see
[set-backchain-limit]). Thanks to Jared Davis for requesting this
feature.
Support is now provided for creating and certifying books that do not
depend on trust tags, in the case that the only use of trust tags
is during [make-event] expansion. See [set-write-ACL2x]. Thanks to
Sol Swords for reporting a couple of bugs in a preliminary
implementation.
Function (file-write-date$ filename state) has been added, giving the
write date of the given file.
See [forward-chaining-reports] for how to get new reports on the
forward chaining activity occurring in your proof attempts. Thanks
to Dave Greve for inspiring the addition of this utility.
It is now possible to use ACL2's printing utilities to return
strings, by opening output channels to the keyword :STRING rather
than to filenames. See [io]. Thanks to Jared Davis for a helpful
conversation that led us to add this feature.
HEURISTIC IMPROVEMENTS
We have slightly improved the handling of :[forward-chaining] rules
that contain free variables. Formerly, such rules might fire only
once, when the first match for a free variable is discovered, and
would not fire again even if subsequent forward chaining made
available another match. This made it difficult to predict whether
a rule with free variables would fire or not, depending as it did
on the order in which newly derived conclusions were added. The new
handling is a little slower but more predictable. Thanks to Dave
Greve for sending a helpful example that led us to consider making
such an improvement.
We have slightly improved the so-called ``[type-set]'' heuristics to
work a bit harder on terms of the form (rec term), where rec is a
so-called ``compound-recognizer'' function, that is, a function
with a corresponding enabled :[compound-recognizer] rule. Thanks to
Jared Davis for sending a helpful example (found, in essence, in
the modified function type-set-rec, source file type-set-b.lisp).
We made three heuristic improvements in the way contexts (so-called
``type-alists'') are computed from goals (``clauses''). Although
these changes did not noticeably affect timing results for the ACL2
regression suite, they can be very helpful for goals with many
hypotheses. Thanks to Dave Greve for sending a useful example (one
where we found a goal with 233 hypotheses!).
The algorithm for substituting alists into terms was modified. This
change is unlikely to affect many users, but in one example it
resulted in a speed-up of about 21%. Thanks to Dave Greve for
supplying that example.
Sped up [include-book] a bit by memoizing checksums of symbols. (This
change pertains to ``normal'' ACL2 only, not the [hons] version
(see [hons-and-memoization], where such memoization already
occurred.) We found about a 23% speed-up on an example from Dave
Greve.
Made a small change to the algorithm used to prove hypotheses of
:[type-prescription] rules (ACL2 source function
type-set-relieve-hyps). One change avoids a linear walk through the
context (the ``type-alist'' structure), while the other could avoid
storing unnecessary [force]d assumptions (into the so-called
``tag-tree'').
BUG FIXES
Fixed a long-standing soundness bug caused by the interaction of
[force]d hypotheses with destructor [elim]ination. The fix was to
avoid using forcing when building the context (so-called
``type-alist'') when the goal is considered for destructor
elimination; those who are interested can see a discussion in
source function eliminate-destructors-clause1, which includes a
proof of nil that no longer succeeds. A similar fix was made for
generalization, though we have not exploited the previous code to
prove nil in that case.
Fixed a bug that allowed book certification to ignore skip-proofs
around [encapsulate] [events]. Thus, a book could contain an event
of the form (skip-proofs (encapsulate ...)), and a call of
[certify-book] on that book could succeed even without supplying
keyword :skip-proofs-okp t. This bug was introduced in Version 3.5
(May, 2009).
Fixed a bug that could occur when including a book that attempts to
redefine a function as a macro, or vice-versa. (For details of the
issue, see the comment in the definition of variable
*hcomp-fn-macro-restore-ht* in source file other-events.lisp.)
(Windows only) Fixed handling of the Windows drive so that an
executable image saved on one machine can be used on another, even
with a different drive. Thanks to Harsh Raju Chamarthi for
reporting this issue and doing a lot of testing and collaboration
to help us get this right.
Made a change to avoid possible low-level errors, such as bus errors,
when quitting ACL2 by calling [good-bye] or its synonyms. This was
occurring in CCL, and we are grateful to Gary Byers for helping us
find the source of those errors (which basically was that ACL2 was
attempting to quit while already in the process of quitting).
Fixed a bug in [with-guard-checking], which was being ignored in
function bodies.
Fixed a bug in [top-level], which was not reverting the logical
[world] when an error resulted from evaluation of the given form.
Thanks to Jared Davis for bringing this bug to our attention.
Fixed a long-standing bug (back through Version 2.7) that was
discarding changes to the connected book directory (see [cbd]) when
exiting and then re-entering the top-level ACL2 loop (with [lp]).
In some host Lisps, it has been possible to be in a situation where
it is impossible to interrupt checkpoint printing during the
summary. We had thought this solved when the host Lisp was CCL, but
Sol Swords sent us an example (for which we are grateful)
illustrating that this behavior could occur. This has been fixed.
Fixed a bug in a proof obligation generated for :[meta] and
:[clause-processor] rules, that the [guard] on the metafunction or
clause-processor function, fn, holds under suitable assumptions.
Those assumptions include not only that the first argument of fn
satisfies [pseudo-termp], but also that all [stobj] inputs satisfy
the corresponding stobj recognizer predicates. We had erroneously
considered stobj outputs of fn instead of stobj inputs. Thanks to
Sol Swords for bringing this bug to our attention with a simple
example, and correctly pointing us to the bug in our code.
Fixed the following bugs in [defattach]. We hadn't always been
applying the full functional substitution when generating guard
proof obligations. We had been able to hit an assertion when
reattaching to more than one function. Attachment was permitted in
the case of an untouchable function (see [remove-untouchable]).
Finally, the guard proof obligation could fail in the case that the
two functions have different formal parameter lists, as in the
following example.
(encapsulate
((foo (x) x :guard (symbolp x)))
(local (defun foo (x) x)))
(defun bar (x2)
(declare (xargs :guard (symbolp x2)))
x2)
(defattach foo bar)
Fixed a raw Lisp error that could be caused by including a book using
[make-event] to define a function symbol in a locally-introduced
package. An example appears in a comment in ACL2 source function
write-expansion-file.
Made a change that can prevent an error near the end of book
certification when the underlying Host Lisp is Allegro Common Lisp,
in the case that environment variable ACL2_SYSTEM_BOOKS has been
set to the name of a directory with a parent that is a soft link.
Thanks to Dave Greve for supplying an example to led us to this
fix, which involves avoiding Allegro CL's implementation of the
Common Lisp function, truename.
Fixed a bug that was failing to substitute fully using bindings of
free variables in [force]d hypotheses. A related change is that
instead of binding such a free variable to a new variable of the
form ???-Y, the new variable is now of the form UNBOUND-FREE-Y.
Fixed a bug that could inhibit the printing of certain theory
warnings (and probably, in the other direction, cause inappropriate
such printing).
We eliminated excessive \"Raw-mode\" warnings about
[add-include-book-dir] that could be generated by the use of
raw-mode during [include-book]. Thanks to Dave Greve for bringing
this issue to our attention.
Fixed the printing of results from forms within an [encapsulate], so
that they are abbreviated according to the [ld-evisc-tuple].
It is now possible to evaluate [stobj]-related forms after evaluating
:[set-guard-checking] :none or :[set-guard-checking] nil, even in
cases where such evaluation formerly caused a guard violation due
to a bug in ACL2. Here is an example of an error that no longer
occurs.
ACL2 !>(defstobj st fld)
Summary
Form: ( DEFSTOBJ ST ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
ST
ACL2 !>(set-guard-checking :none)
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(fld st)
ACL2 Error in TOP-LEVEL: The guard for the function call (FLD ST),
which is (STP ST), is violated by the arguments in the call (FLD ST).
[... etc. ...]
You can understand how things now work by imagining that when a
function introduced by [defstobj] is called, [guard]-checking
values of :none or nil are temporarily converted to t. Thanks to
Pete Manolios, Ian Johnson, and Harsh Raju Chamarthi for requesting
this improvement.
Fixed a bug in which the wrong attachment could be made when the same
function has an attachment in a book and another in the
certification world of that book (possibly even built into ACL2),
if the load of a compiled file is aborted because a sub-book's
compiled file is missing. The bug has been present since the time
that [defattach] was added (Version_4.0). An example may be found
in a comment in the [deflabel] for note-4-2 (ACL2 source file
ld.lisp).
The :[doc] and related utilities now cause a clean error when
provided other than a symbol. Thanks to Jared Davis for pointing
out the raw Lisp error that had occurred in such cases.
It had been the case that in raw-mode (see [set-raw-mode]), it was
possible to confuse [include-book] when including a book in a
directory different from the current directory. This has been
fixed. Thanks to Hanbing Liu for bringing this problem to our
attention with a small example.
NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE
Many changes have been made to the distributed books, thanks to an
active ACL2 community. You can contribute books and obtain updates
between ACL2 releases by visiting the {ACL2 Books |
http://acl2-books.googlecode.com/} web page.
There is new Makefile support for certifying just some of the
distributed books. See [books-certification-classic], in particular
discussion of the variable ACL2_BOOK_DIRS. Thanks to Sandip Ray for
requesting this enhancement.
The [documentation] for [make-event] now points to a new book,
books/make-event/defrule.lisp, that shows how make-event can be
used to do macroexpansion before generating [events]. Thanks to
Carl Eastlund for useful interaction on the acl2-help mailing list
that led us to add this example.
EMACS SUPPORT
Incorporated a version of changes from Jared Davis to the control-t f
emacs utility (distributed file emacs/emacs-acl2.el), so that one
can fill a format string from anywhere within the string.
EXPERIMENTAL VERSIONS
We refrain from listing changes here to experimental versions, other
than an enhancement to the [hons] version that can reduce sizes of
[certificate] files, by applying [hons-copy] to introduce structure
sharing (ACL2 source function make-certificate-file1).")
(NOTE-4-2{R}
(RELEASE-NOTES)
"ACL2 Version 4.2(r) (January, 2011) Notes
Please see [note-4-2] for changes in Version 4.2 of ACL2.")
(NOTE-4-3
(RELEASE-NOTES)
"ACL2 Version 4.3 (July, 2011) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 4.2 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, changes at the system level and
to distributed books, Emacs support, and experimental versions.
Each change is described in just one category, though of course
many changes could be placed in more than one category.
CHANGES TO EXISTING FEATURES
Significant changes have been made for list-processing primitives
such as [member] and [assoc]; see [equality-variants]. In summary:
instead of separate functions based on [eq], [eql], and [equal],
there is essentially just one function, which is based on [equal];
the [eq] and [eql] variants are logically just the [equal] variant.
For example, [member-eq] and [member] are macros that generate
corresponding calls of [member-equal] in the logic, although in raw
Lisp they will execute using tests [eq] and [eql], respectively.
References to any of these in logical contexts such as [theories]
are now references to the function based on [equal]; for example,
the hint :in-theory (disable member) is completely equivalent to
the hint :in-theory (disable member-equal). Distributed books have
been modified as necessary to accommodate this change. While the
need for such changes was relatively infrequent, changes were for
example needed in contexts where terms are manipulated directly;
for example, [defevaluator] needs to mention [member-equal] rather
than [member], just as it was already the case to mention, say,
[binary-append] rather than [append]. Again, see
[equality-variants] for more information about equality variants.
A few improvements were made in support of the modified treatment of
equality variants discussed above. The changes include the
following.
o We now allow the use of macro aliases (see [macro-aliases-table] in
:trigger-fns of rules (see [rule-classes]).
o We now remove so-called ``guard holders'' (including calls of
[return-last], hence of [mbe]) in :trigger-terms of rules.
o We also remove guard holders in formulas of :[congruence] and
[type-prescription] rules.
o Macros union-eq and intersection-eq can now take any positive
number of arguments, and [union-eq] can take zero arguments.
(Thanks to Jared Davis for requesting this enhancement.) The
same can be said for new macros [union$] and [intersection$],
respectively.
o A few changes were made to built-in theorems from source file
axioms.lisp, in particular disabling :[type-prescription] rule
consp-assoc-equal (formerly two enabled rules, consp-assoc-eq
and consp-assoc) but adding this theorem as a :forward-chaining
rule, and similarly for
true-list-listp-forward-to-true-listp-assoc-equal (and
eliminating rule
true-list-listp-forward-to-true-listp-assoc-eq; and disabling
rule true-listp-cadr-assoc-eq-for-open-channels-p. Also,
theorem all-boundp-preserves-assoc has been renamed to
all-boundp-preserves-assoc-equal and also strengthened.
o Some [guard]s were slightly improved (logically weaker or the
same).
Improved get-output-stream-string$ to allow for a context and to do
genuine error printing instead of using [cw]. See [io].
Added the symbols [flet] and [with-local-stobj] to *acl2-exports*.
A small change was made to the processing of more than one :[guard]
declaration for the same function. In particular, a guard of t is
essentially ignored.
Attachments are now allowed during evaluation of the first argument
of [prog2$] even in contexts (such as proofs) during which the use
of attachments is normally prohibited. More generally, the second
of the three arguments of [return-last] has this property, except
in the case of [mbe] (or related macros like [mbe1]), where the
exec argument may provide the value. Thanks to Sol Swords for
useful discussions leading us to implement this enhancement.
The restriction has been removed that prohibited the use of [mbe]
inside [encapsulate] [events] with a non-empty [signature]. This
restriction was introduced in Version 3.4, but has not been
necessary since Version 4.0, when we first started disallowing
[guard] verification for functions introduced non-[local]ly inside
such [encapsulate] events.
We weakened the checks involving common ancestors for evaluator and
[meta] (and [clause-processor]) functions (see
[evaluator-restrictions]) so that except in the [mbe] case, the
next-to-last argument of [return-last] is not considered. Thanks to
Sol Swords for bringing this issue to our attention.
The macro [append] no longer requires at least two arguments. Thanks
to Dave Greve for requesting this enhancement.
(Mostly for system hackers) Now, [break-on-error] breaks at a more
appropriate (earlier) time for certain system functions that do not
return state, such as translate11. Thanks to David Rager for
requesting this improvement.
[Show-accumulated-persistence] may take a new argument, :runes, which
simply causes an alphabetical list of [rune]s to be printed out.
Improved [trace$] so that :entry, :exit, and :cond forms may
reference state even if the function being traced does not include
state as a formal.
The system function acl2x-expansion-alist now takes a second
argument, namely [state]. This change allows for more flexibility
in the sorts of attachments that can be made to this function (see
[defattach]). Thanks to Jared Davis and Sol Swords for requesting
this enhancement and providing a preliminary implementation.
An obscure [proof-checker] change, unlikely to affect users, replaces
the state global variables erp, val, print-macroexpansion-flg, and
print-prompt-and-instr-flg by pc-erp, pc-val,
pc-print-macroexpansion-flg, and pc-print-prompt-and-instr-flg,
respectively.
[State] globals fmt-hard-right-margin and fmt-soft-right-margin are
now untouchable (see [set-fmt-hard-right-margin] and see
[push-untouchable]). If you bind these state globals with
[state-global-let*], then you will need to do so with appropriate
setters to restore their values, for example as follows.
(state-global-let*
((fmt-hard-right-margin 500 set-fmt-hard-right-margin)
(fmt-soft-right-margin 480 set-fmt-soft-right-margin))
...)
The error message has been improved for the case of evaluating an
undefined function that has an attachment (see [defattach]). Thanks
to Jared Davis for sending the following example, which illustrates
the additional part of the message.
ACL2 !>(defstub foo (x) t)
[[... output omitted ...]]
ACL2 !>(defattach foo identity)
[[... output omitted ...]]
ACL2 !>(defconst *x* (foo 3))
ACL2 Error in ( DEFCONST *X* ...): ACL2 cannot ev the call of undefined
function FOO on argument list:
(3)
Note that because of logical considerations, attachments (including
IDENTITY) must not be called in this context.
[[... additional output omitted ...]]
The directory string supplied to [add-include-book-dir] no longer
must terminate with the `/' character, as had been required in some
Lisp implementations. Thanks to Sol Swords for bringing this issue
to our attention.
We no longer print induction schemes with [gag-mode]; use :[pso] if
you want to see them. Thanks to Dave Greve for this suggestion.
It is now legal to supply a constant for a [stobj] array dimension.
See [defstobj]. Thanks to Warren Hunt for requesting this
enhancement.
We cleaned up a few issues with [defpkg].
o It is no longer illegal to submit a [defpkg] form in raw-mode (see
[set-raw-mode]). Thanks to Jun Sawada for reporting an example
in which an [include-book] form submitted in raw-mode caused an
error because of a `hidden' [defpkg] form (see
[hidden-defpkg]). There will no longer be an error in such
cases.
o It had been the case that [local]ly including a book could make it
possible to use a package defined by that book. Consider for
example the following book, foo.lisp.
(in-package \"ACL2\")
(local (include-book \"arithmetic/top\" :dir :system))
After certifying this book, it had been possible to admit the
following events in a new session.
(include-book \"foo\")
(defconst acl2-asg::*foo* 3)
(defconst *c* 'acl2-asg::xyz)
In Version_4.3, neither of these [defconst] events is admitted.
o A hard Lisp error is now avoided that had been possible in rare
cases when including books with hidden packages (see
[hidden-defpkg]). An example may be found in a comment in the
[deflabel] for note-4-3 (in ACL2 source file ld.lisp).
The undocumented (but sometimes useful) functions packn1 and packn
are now [guard]-verified :[logic] mode functions. Thanks to Sandip
Ray for requesting this enhancement.
It had been the case that when including a book, functions defined in
the book's certification [world] (that is, in its [portcullis]
[command]s) were typically not given compiled code. That has been
fixed.
The commands :[pl] and :[pl2] have been improved, primarily by
printing information for more rule classes. See [pl] and see [pl2].
See also the item below about the new [proof-checker] command,
show-type-prescriptions.
NEW FEATURES
New macros [mv?-let] and [mv?] extend the funtionality of [mv-let]
and [mv] (respectively) to the case of a single value.
Macro [with-local-state] is available for system programmers who wish
bind [state] locally, essentially using [with-local-stobj]. But
this should only be done with extreme care, and it requires an
active trust tag; see [with-local-state].
Formatted printing functions now have analogues that print to strings
and do not take an output channel or [state] as arguments. See
[printing-to-strings].
The system function ancestors-check is now available for verified
modification by users, i.e., attachment using (defattach
ancestors-check <your_function>). Thanks to Robert Krug for
providing the necessary proof support, which we modified only in
small ways.
New macros, observation-cw and warning$-cw, provide formatted
printing of [observation]s and warnings (respectively) without
[state]. Thanks to Harsh Raju Chamarthi and David Rager for
requests leading to these utilities. Observation-cw is now used in
some of the distributed books (thanks to Robert Krug for useful
interaction for that).
The [proof-checker] command type-alist (see [proof-checker-commands])
now takes an optional third argument that causes the production of
forward-chaining reports (see [forward-chaining-reports]). Thanks
to Dave Greve for requesting such an enhancement.
The reports generated by forward-chaining,
[forward-chaining-reports], have been changed to indicate when a
conclusion reached by forward chaining is REDUNDANT with respect to
the type information already known. Thanks to Dave Greve for
suggesting this enhancement.
The utility [with-prover-time-limit] is now legal for [events] (see
[embedded-event-form]). For example, the following is now legal.
(encapsulate
()
(with-prover-time-limit
2
(defthm append-assoc
(equal (append (append x y) z)
(append x (append y z))))))
The new utility [with-prover-step-limit] is analogous to the utility
[with-prover-time-limit], but counts ``prover steps'' rather than
checking for time elapsed. See [with-prover-step-limit]. Also see
[set-prover-step-limit] to provide a default step-limit. Note that
just as [with-prover-time-limit] may now be used to create
[events], as discussed just above, [with-prover-step-limit] may
also be used to create [events]. Thanks to Carl Eastlund for
requesting support for step-limits.
The macro [progn$] is analogous to [prog2$], but allows an arbitrary
number of arguments. For example:
ACL2 !>:trans1 (progn$ (f1 x) (f2 x) (f3 x))
(PROG2$ (F1 X) (PROG2$ (F2 X) (F3 X)))
ACL2 !>
Thanks to David Rager for contributing this macro.
The macro [defattach] may now be supplied the argument :skip-checks
:cycles. In this case, as with argument :skip-checks t, a trust tag
is reuired (see [defttag]), and no logical claims are made. The
effect is to avoid the usual check that the extended ancestor
relation has no cycles (see [defattach]). Thanks to Dave Greve for
requesting this feature.
You can now limit the printing of subgoal names when using
:[set-gag-mode] :goals. See [set-print-clause-ids]. Thanks to Karl
Hoech for a suggestion leading to this enhancement.
A new [proof-checker] command, show-type-prescriptions, or st for
short, provides information about :[type-prescription] rules that
match a given term. Thanks to Dave Greve for requesting this
enhancement. See also the item above about related improvements to
commands :[pl] and :[pl2].
HEURISTIC IMPROVEMENTS
ACL2 now avoids some repeated attempts to rewrite hypotheses of
rewrite rules. See [set-rw-cache-state] for a discussion of this
behavior and how to avoid it. The default behavior has been
observed to reduce by 11% the overall time required to complete a
regression. Here are the directories that had the top three time
decreases and top three time increases, shown in seconds.
-368 coi/gacc (1064 down to 696: decrease of 35%)
-220 workshops/1999/ste (664 down to 444: decrease of 33%)
-148 unicode (331 down to 183: decrease of 45%)
....
+7 workshops/2002/cowles-flat/support (229 up to 236: increase of 3%)
+8 workshops/1999/ivy/ivy-v2/ivy-sources (508 up to 516: increase of 2%)
+12 workshops/2009/hardin/deque-stobj (78 up to 91: increase of 17%)
The so-called ``ancestors check,'' which is used to limit
backchaining, has been strengthened so that two calls of [equal]
are considered the same even if their arguments appear in the
opposite order. Thanks to Robert Krug for providing an
implementation and a useful discussion.
The check for [irrelevant-formals] in processing of [defun]s has been
made more efficient. Thanks to Eric Smith for reporting this issue
in 2001 (!) and thanks to Warren Hunt for recently sending an
example. For that example, we have seen the time for the
[irrelevant-formals] check reduced from about 10 seconds to about
0.04 seconds.
(GCL only) The macro [mv] has been modified so that certain fixnum
boxing can be avoided.
(Allegro CL only) We have set to nil four Allegro CL variables that
otherwise enable storing of certain source information (for
details, see the discussion of ``cross-referencing'' in ACL2 source
file acl2-init.lisp). As a result of this change we have about a 6%
speedup on the regression suite, but a 27% time reduction on an
example that includes a lot of books.
Exhaustive matching for the case of [free-variables] has been
extended to [type-prescription] rules, in analogy to the default
setting :match-free :all already in place for [rewrite], [linear],
and [forward-chaining] rules. See
[free-variables-type-prescription]. Thanks to Dave Greve for
requesting this enhancement.
BUG FIXES
A soundness bug was fixed in some raw-Lisp code implementing the
function, [take]. Thanks to Sol Swords for pointing out this bug
with (essentially) the following proof of nil.
(defthmd take-1-nil-logic
(equal (take 1 nil) '(nil))
:hints((\"Goal\" :in-theory (disable (take)))))
(thm nil :hints ((\"Goal\" :use take-1-nil-logic)))
Calls of [mbe] in ``safe-mode'' situations --- i.e., during
evaluation of [defconst], [value-triple], and [defpkg] forms, and
during macroexpansion --- are now guard-checked. Thus, in these
situations both the :logic and :exec forms will be evaluated, with
an error if the results are not equal. Formerly, only the :logic
form was evaluated, which was a soundness bug that could be
exploited to prove nil. For a such a proof and a bit of further
explanation, see the example at the top of the comments for
(deflabel note-4-3 ..) in ACL2 source file ld.lisp.
It had been possible to prove nil by proving the following theorem
using ACL2 built on CCL and then proving its negation using ACL2
built on a different host Lisp.
(defthm host-lisp-is-ccl
(equal (cdr (assoc 'host-lisp *initial-global-table*))
:ccl)
:rule-classes nil)
This hole has been plugged by moving the setting of 'host-lisp out of
the constant *initial-global-table*.
Fixed [trace$] for arguments that are [stobj] accessors or updaters.
It also gives an informative error in this case when the accessor
or updater is a macro (because the introducing [defstobj] event
specified :inline t).
Avoided a potential error that could occur when no user home
directory is located. Our previous solution for Windows simply
avoided looking for ACL2 customization files (see
[ACL2-customization]) and acl2-init.lsp files in a user's home
directory. With this change, we handle such files the same for
Windows as for non-Windows systems: we always look for ACL2
customization files (see [ACL2-customization]) and acl2-init.lsp
files in a user's home directory, but only if such a directory
exists. Thanks to Hanbing Liu for reporting this issue.
(GCL only) Fixed a bug that prevented the use of
[get-output-stream-string$] when the host Lisp is GCL.
Fixed [with-live-state] to work properly for executable counterparts
(so-called ``*1*'' functions).
Fixed a bug in the error message caused by violating the [guard] of a
macro call.
Fixed a bug in an error message that one could get when calling
[defattach] with argument :skip-checks t to attach to a :[program]
mode function symbol that was introduced with [defun]. (This is
indeed an error, but the message was confusing.) Thanks to Robert
Krug for bringing this bug to our attention.
Fixed a bug in the loop-checking done on behalf of [defattach], which
could miss a loop. For an example, see the comment about
loop-checking in the comments for (deflabel note-4-3 ..) in ACL2
source file ld.lisp.
Terms of the form (hide <term>) without free variables could be
simplified, contrary to the purpose of [hide]. This is no longer
the case, Thanks to Dave Greve for reporting this issue.
An infinite loop could occur when an error was encountered in a call
of [wormhole-eval], for example with the following form, and this
has been fixed.
(wormhole-eval 'demo
'(lambda ()
(er hard 'my-top \"Got an error!\"))
nil)
Fixed a bug in detection of package redefinition. While we have no
example demonstrating this as a soundness bug, we cannot rule it
out.
Fixed a bug in the message produced by an erroneous call of [flet].
Thanks to Jared Davis for reporting this bug and sending a helpful
example.
For a failed [defaxiom] or [defthm] event, we now avoid printing
[rune]s that are used only in processing proposed rules to be
stored, but not in the proof itself. Thanks to Dave Greve for
sending us an example that led us to make this fix.
ACL2 did not reliably enforce the restriction against non-[local]
[include-book] [events] inside [encapsulate] events, as illustrated
by the following examples.
; not permitted (as expected)
(encapsulate () (include-book \"foo\"))
; permitted (as expected)
(encapsulate () (local (include-book \"foo\")))
; formerly permitted (surprisingly); now, not permitted
(local (encapsulate () (include-book \"foo\")))
Moreover, the corresponding error message has been fixed. Thanks to
Jared Davis and Sandip Ray for relevant discussions.
When [include-book] is given a first argument that is not a string, a
more graceful error now occurs, where previously an ugly raw Lisp
error had occurred. Thanks to Eric Smith for bringing this bug to
our attention.
Fixed a bug in an error message that was printed when an unexpected
expression has occurred where a [declare] form is expected.
(Since all functions are compiled when the host Lisp is CCL or SBCL,
the following bug fix did not occur for those host Lisps.) After
evaluation of ([set-compile-fns] t), all defined functions are
expected to run with compiled code; but this was not the case for
functions exported from an [encapsulate] event. This has been
fixed.
It had been the case that the :[puff] command was broken for
[include-book] form whose book had been certified in a world with
an [add-include-book-dir] event. This has been fixed.
Evaluation of [stobj] updaters (see [defstobj]) may no longer use
attachments (see [defattach]). This is a subtle point that will
likely not affect many users. Thanks to Jared Davis for bringing
this issue to our attention; a slight variant of his example
appears in a comment in ACL2 source function oneify-cltl-code.
It had been the case that even when a [stobj] creator function was
declared to be untouchable (see [push-untouchable]), a
[with-local-stobj] form based on that same stobj was permitted.
Now, such forms are not admitted. Thanks to Jared Davis for a query
leading to this fix.
Fixed a buggy message upon [guard] violations, which was suggesting
the use of (set-guard-checking :none) in some cases when
guard-checking was already set to :none.
It had been possible to get a hard Lisp error when computing with
[ec-call] in [books]. The following is an example of such a book,
whose certification no longer causes an error.
(in-package \"ACL2\")
(defun f (x) x)
(defconst *c* (ec-call (f 3)))
(defun g (x) (cons x x))
The command :[pl2], and also the [proof-checker] commands rewrite and
show-rewrites (and hence their respective aliases r and sr), now
take rule-id arguments that can be :[definition] [rune]s. These
commands dealt with definition rules already, e.g.
:pl2 (append x y) binary-append
but they did not allow explicit specification of :definition runes,
e.g.:
:pl2 (append x y) (:definition binary-append)
The following example illustrates a bug in the processing of
(admittedly obscure) [hints] of the form :do-not-induct name, where
name is not t, :otf-flg-override, :otf, or nil. In this example,
ACL2 had essentially ignored the hint and reverted to prove the
original goal by induction, rather than to skip the goal
temporarily as is expected for such hints. Thanks to David Rager
for a helpful discussion.
(thm (and (equal (append (append x y) z) (append x y z))
(equal (append (append x2 y2) z2) (append x2 y2 z2)))
:hints ((\"Subgoal 1\" :do-not-induct some-name)))
Fixed a slight bug in the definitions of built-in [theories]. For
example, in a fresh ACL2 session the value of the following form is
nil, but formerly included several :[definition] [rune]s.
(let ((world (w state)))
(set-difference-theories (function-theory :here)
(function-theory 'ground-zero)))
CHANGES AT THE SYSTEM LEVEL AND TO DISTRIBUTED BOOKS
Many changes have been made to the distributed books, as recorded in
svn logs under the `Source' and 'Updates' links at the {ACL2 Books
| http://acl2-books.googlecode.com/} web page. Here we list some of
the more significant changes.
o A large library has been graciously contributed by the formal
verification group at Centaur Technology. See books/centaur/
and, in particular, file books/centaur/README, which explains
how the library depends on the experimental HONS extension (see
[hons-and-memoization]).
o Among the new books is an illustration of [defattach],
books/misc/defattach-example.lisp, as well as a variant of
defattach that avoids the need for [guard] verification,
books/misc/defattach-bang.lisp.
o Distributed book books/misc/trace1.lisp has been deleted. It had
provided slightly more friendly [trace] output for new users,
but distributed book books/misc/trace-star.lisp may be better
suited for that purpose.
ACL2 can once again be built on LispWorks (i.e., as the host Lisp),
at least with LispWorks 6.0. Thanks to David Rager for useful
conversations. Several changes have been made from previous
LispWorks-based ACL2 executables:
o ACL2 now starts up in its read-eval-print loop.
o You can save an image with [save-exec].
o Multiprocessing is not enabled.
o The stack size is managed using a LispWorks variable that causes
the stack to grow as needed.
o When ACL2 is built a script file is written, as is done for other
host Lisps. Thus, (assuming that no PREFIX is specified),
saved_acl2 is just a small text file that invokes a binary
executable, which for Lispworks is saved_acl2.lw.
The HTML documentation no longer has extra newlines in <pre>
environments.
Statistics on ACL2 code size may be found in distributed file
doc/acl2-code-size.txt. This file and other information can be
found in a new [documentation] topic, [about-ACL2].
Fixed the build process to pay attention to environment variable
ACL2_SYSTEM_BOOKS (which may be supplied as a command-line argument
to `make'). An ACL2 executable can thus now be built even when
there is no books/ subdirectory if a suitable replacement directory
is supplied.
Some warnings from the host Lisp are now suppressed that could
formerly appear. For example, the warnings shown below occurs in
Version 4.2 using Allegro CL, but not in Version 4.3.
ACL2 !>(progn (set-ignore-ok t)
(set-irrelevant-formals-ok t)
(defun bar (x y)
x))
[[.. output omitted ..]]
BAR
ACL2 !>:comp bar
; While compiling BAR:
Warning: Variable Y is never used.
; While compiling (LABELS ACL2_*1*_ACL2::BAR ACL2_*1*_ACL2::BAR):
Warning: Variable Y is never used.
BAR
ACL2 !>
EMACS SUPPORT
The distributed Emacs file emacs/emacs-acl2.el now indents calls of
er@par and warning$@par the same way that calls of defun are
indented.
EXPERIMENTAL VERSIONS
The parallel version (see [parallelism]) now supports parallel
evaluation of the ``waterfall'' part of the ACL2 prover; see
[set-waterfall-parallelism]. Thanks to David Rager for doing the
primary design and implementation work.
A new macro, [spec-mv-let], supports speculative and parallel
execution in the parallel version, courtesy of David Rager.
Among the enhancements for the HONS version (see
[hons-and-memoization]) are the following.
[Memoize]d functions may now be traced (see [trace$]). Thanks to Sol
Swords for requesting this enhancement.
[Memoize-summary] and [clear-memoize-statistics] are now :[logic]
mode functions that return nil. Thanks to Sol Swords for this
enhancement.
[Memoize] is now explicitly illegal for constrained functions.
(Already such memoization was ineffective.)
A new keyword argument, :AOKP, controls whether or not to allow
memoization to take advantage of attachments; see [memoize] and
for relevant background, see [defattach].
[Memoize] is now illegal by default for :[logic] mode functions that
have not had their guards verified. See [memoize] (keyword
:ideal-okp) and see [ACL2-defaults-table] (key
:memoize-ideal-okp) for and explanation of this restriction and
how to avoid it.
[History] commands such as :[pe] and :[pbt] now display ``M'' or
``m'' to indicate memoized functions. See [pc].")
(NOTE-4-3{R}
(RELEASE-NOTES)
"ACL2 Version 4.3(r) (July, 2011) Notes
Please see [note-4-3] for changes in Version 4.3 of ACL2.")
(NOTE-5-0
(RELEASE-NOTES)
"ACL2 Version 5.0 (August, 2012) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 4.3 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, changes at the system level and
to distributed books, Emacs support, and experimental versions.
Each change is described in just one category, though of course
many changes could be placed in more than one category.
NOTE: ACL2 is now distributed under Version 2 of the GNU General
Public License. [Added later: The license has changed since
Version_5.0. See LICENSE.] Formerly, any later version had been
acceptable. Moreover, books are no longer distributed from a
University of Texas website, but rather, from Google Code at the
{ACL2 Books Downloads |
http://code.google.com/p/acl2-books/downloads/} page.
CHANGES TO EXISTING FEATURES
A fatal error now occurs if environment variable ACL2_CUSTOMIZATION
has a value other than NONE or the empty string, but is not the
name of an existing file. Thanks to Harsh Raju Chamarthi for
requesting such a change.
Functions read-acl2-oracle (and read-acl2-oracle@par), read-run-time,
and main-timer are no longer untouchable (see
[remove-untouchable]).
We now avoid certain duplicate conjuncts in the [constraint] stored
for [encapsulate] [events]. For example, the constraint stored for
the following event formerly included (EQUAL (FOOP (CONS X Y))
(FOOP Y)) and (BOOLEANP (FOOP X)) twice each, but no more.
(encapsulate
((foop (x) t))
(local (defun foop (x) (declare (ignore x)) t))
(defthm foop-constraints
(and (booleanp (foop x))
(equal (foop (cons x y)) (foop y)))
:rule-classes
((:type-prescription :corollary (booleanp (foop x)))
(:rewrite :corollary (equal (foop (cons x y)) (foop y))))))
The :[guard] for a constrained function (see [signature]) may now
mention function symbols introduced in the same [encapsulate] event
that introduces that function. Thanks to Nathan Wetzler for a
helpful discussion leading to this improvement.
The test for redundancy (see [redundant-events]) of [encapsulate]
[events] has been improved in cases involving redefinition (see
[ld-redefinition-action]). Thanks to Jared Davis for providing the
following example, which illustrates the problem.
(redef!)
(encapsulate ()
(defun g (x)
(+ 3 x)))
(g 0) ; 3, as expected
(encapsulate ()
(defun g (x)
(+ 4 x)))
(g 0) ; 4, as expected
; Unfortunately, the following was flagged as redundant because it agreed
; with the first encapsulate above. That has been fixed; now, it is
; recognized as not being redundant.
(encapsulate ()
(defun g (x)
(+ 3 x)))
The test for redundancy of [defun] and [defconst] events has been
improved in the case that redefinition is active. In that case,
redundancy now additionally requires that the ``translated'' body
is unchanged, i.e., even after expanding macro calls and replacing
constants (defined by [defconst]) with their values. Thanks to Sol
Swords for requesting this enhancement, and to Jared Davis for
pointing out a bug in a preliminary change. See [redundant-events],
in particular the ``Note About Unfortunate Redundancies''. Note
that this additional requirement was already in force for
redundancy of [defmacro] events.
The macro [defmacro-last] and the [table] [return-last-table] have
been modified so that when they give special treatment to a macro
mac and its raw Lisp counterpart mac-raw, a call (return-last
'mac-raw ...) can be made illegal when encountered directly in the
top level loop, as opposed to inside a function body. See
[return-last]. Thanks to Harsh Raju Chamarthi for showing us an
example that led us to make this improvement.
We removed a barrier to admitting function definitions, as we explain
using the following example.
(defun foo (m state)
(declare (xargs :stobjs state))
(if (consp m)
(let ((state (f-put-global 'last-m m state)))
(foo (cdr m) state))
state))
Previously, ACL2 complained that it could not determine the outputs
of the [let] form, as is necessary in order to ensure that [state]
is returned by it. ACL2 now works harder to solve this problem as
well as the analogous problem for [mv-let] and, more generally for
[mutual-recursion]. (The main idea is to reverse the order of
processing the [if] branches if necessary.) We thank Sol Swords for
contributing a version of the above example and requesting this
improvement.
It is no longer the case that [break-on-error] causes a Lisp break
when encountering an error during translation of user input into
internal (translated) form (see [term]). The reason is that an
improvement to the translation process, specifically the one
described in the preceding paragraph, allows certain backtracking
from ``errors'', which are intended to be silent rather than
causing breaks into raw Lisp. Thanks to Jared Davis for sending an
example leading to this change.
(CCL and SBCL only) When the host Lisp is CCL or SBCL, then since all
functions are compiled, a [certify-book] command will no longer
load the newly-compiled file (and similarly for [include-book] with
argument :load-compiled-file :comp).
[Set-write-acl2x] now returns an error triple and can take more
values, some of which automatically allow including uncertified
books when [certify-book] is called with argument :acl2x t.
The environment variable COMPILE_FLG has been renamed
ACL2_COMPILE_FLG; see [certify-book].
The macros [defthmd] and [defund] no longer return an error triple
with value :SKIPPED when proofs are being skipped. Rather, the
value returned is the same as would be returned on success when
proofs are not skipped.
For those who use [set-write-ACL2x]: now, when [certify-book] is
called without a :ttagsx argument supplied, then the value of
:ttagsx defaults to the (explicit or default) value of the :ttags
argument.
The :[pl] and :[pl2] [command]s can now accept [term]s that had
previously been rejected. For example, the command :pl (member a
(append x y)) had caused an error, but now it works as one might
reasonably expect, treating [member] as [member-equal] (see
[equality-variants] for relevant background). Thanks to Jared Davis
for reporting this problem by sending the above example.
We have eliminated some hypotheses in built-in [rewrite] rules
characterp-nth and ordered-symbol-alistp-delete-assoc-eq.
Added the symbols [f-get-global], [f-put-global], and
[state-global-let*] to *acl2-exports*.
Added to the [guard]s of [push-untouchable] and [remove-untouchable]
the requirement that the second argument must be a Boolean. Thanks
to Jared Davis for sending an example that led to this change.
The built-in function string-for-tilde-@-clause-id-phrase has been
put into :[logic] mode and had its guards verified, as have some
subsidiary functions. A few new rules have been added in support of
this work; search for string-for-tilde-@-clause-id-phrase in ACL2
source file boot-strap-pass-2.lisp if interested. Thanks to David
Rager for contributing an initial version of this improvement.
All trust tags are now in the [keyword] package. The [defttag] event
may still take a symbol in an arbitrary package, but the trust tag
created will be in the keyword package (with the same [symbol-name]
as the symbol provided). Similarly, non-nil symbols occurring in
the :ttags argument of an [include-book] or [certify-book] command
will be converted to corresponding keywords. See [defttag].
There have been several changes to [gag-mode]. It is now is initially
set to :goals, suppressing most proof commentary other than key
checkpoints; see [set-gag-mode]. (As before, see [pso] for how to
recover the proof output.) Also, top-level induction schemes are
once again printed when gag-mode is on, though these as well as
printing of guard conjectures can be abbreviated (``eviscerated'')
with a new [evisc-tuple]; see [set-evisc-tuple], in particular the
discussion there of :GAG-MODE. Finally, the commentary printed
within [gag-mode] that is related to [forcing-round]s is now less
verbose. Thanks to Dave Greve and David Rager for discussions
leading to the change in the printing of induction schemes under
gag-mode; thanks to Warren Hunt for an email that led us to similar
handling for printing of guard conjectures; and thanks to Robert
Krug for a suggestion that led us to restore, in abbreviated form,
important information about the sources of forcing round goals.
An error now occurs if [ld] is called while loading a compiled book.
See [calling-ld-in-bad-contexts]. Thanks to David Rager for
reporting a low-level assertion failure that led us to make this
change.
The [proof-checker] interactive loop is more robust: most errors will
leave you in that loop, rather than kicking you out of the
proof-checker and thus back to the main ACL2 read-eval-print loop.
Thanks to David Hardin for suggesting this improvement in the case
of errors arising from extra right parentheses.
The summary at the end of a proof now prints the following note when
appropriate:
[NOTE: A goal of NIL was generated. See :DOC nil-goal.]
See [nil-goal].
Improved [dmr] to show the function being called in the case of
explicit evaluation: ``(EV-FNCALL function-being-called)''.
It is now permitted to bind any number of [stobjs] to themselves in
the bindings of a [let] expression. But if any stobj is bound to
other than itself in [let] bindings, then there still must be only
one binding in that LET expression. The analogous relaxation holds
for [lambda] expressions. Thanks to Sol Swords for requesting such
a change, which was needed for some code generated by macro calls.
The macro [top-level] now returns without error; See [top-level].
Formerly, this macro always returned an error triple (mv t ..
state), which meant that normal calls of [ld] would stop after
encountering a call of top-level. Thanks to Jared Davis for
bringing this issue to our attention.
It is no longer the case that when you specify [xargs] keyword
:non-executable t in a [defun] form rather than using [defun-nx],
then the form of the body need match only the shape (prog2$
(throw-nonexec-error ... ...) ...). We now require that the body of
the definition of a function symbol, fn, with formals (x1 ... xk),
be of the form (prog2$ (throw-nonexec-error 'fn (list x1 ... xk))
...). This fixes the following odd behavior, which could be
considered a bug. Consider a book that contains the following two
events.
(defun foo (x)
(declare (xargs :guard t :non-executable t :mode :logic))
(prog2$ (throw-nonexec-error 'bar (list x))
(cons 3 x)))
(defn h (x)
(foo x))
After certifying this book and then including it in a new session,
the behavior occurred that is displayed below; notice the mention
of BAR. However, if the two forms were submitted directly in the
loop, then the error message had mentioned FOO instead of BAR. This
discrepancy has been eliminated, by rejecting the proposed
definition of foo because the name in the first argument of
throw-nonexec-error was 'bar where now it must be 'foo.
ACL2 !>(h 3)
ACL2 Error in TOP-LEVEL: ACL2 cannot ev the call of undefined function
BAR on argument list:
(3)
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
ACL2 !>
A tautology checker used in the ACL2 sources (function if-tautologyp)
has been limited somewhat in the effort it makes to recognize a
tautology. While we expect it to be rare for the effect of this
change to be noticeable, we thank Sol Swords for sending us an
example that motivated this change: a [guard] verification that
took about 5 seconds in Version_4.3 now takes, on the same machine,
about 0.07 seconds.
The behavior of backquote (`) has been changed slightly to be
compatible with its behavior in raw Lisp. The change is to allow
the use of comma-atsign (,@) at the end of a list, as in the
following example.
(let ((x 3) (y 2) (z 7)) `(,x ,y ,@z))
Formerly, evaluation of this form had caused a guard violation in the
ACL2 loop unless guard-checking was off (i.e., [set-guard-checking]
was invoked with nil or :none), in which case it returned (3 2).
But we observed evaluation of this form to return (3 2 . 7) in
every host Lisp on which ACL2 runs (Allegro CL, CCL, CLISP, CMUCL,
GCL, LispWorks, and SBCL). Now, ACL2 behaves like these Lisps.
A call of the [theory] macro had previously returned nil when applied
to other than the name of name of a previously executed [deftheory]
event. Now, a hard error occurs.
The [table] binop-table has been replaced by the table
[untrans-table]. However, [add-binop] and [remove-binop] continue
to have the same effect as before. See [add-macro-fn], which is a
new feature discussed below.
The function [booleanp] is now defined using [eq] instead of [equal],
which may increase its efficiency. Thanks to Jared Davis for this
change.
For pairs (key . val) in the [macro-aliases-table], there had been a
requirement that val is a known function symbol. Now, it only needs
to be a symbol. (This change was made to support the new feature,
[defun-inline], described elsewhere in these release notes.)
NEW FEATURES
A new ``tau system'' provides a kind of ``type checker.'' See
[tau-system]. Thanks to Dave Greve for supplying a motivating
example (on which this system can provide significant speedup), and
to Sol Swords for sending a very helpful bug report on a
preliminary implementation.
Users may now arrange for additional summary information to be
printed at the end of [events]. [Note added at Version_6.1:
Formerly we pointed here to print-summary-user, but now, see
[finalize-event-user]; also see [note-6-1]]. Thanks to Harsh Raju
Chamarthi for requesting this feature and participating in a design
discussion.
A new, advanced [proof-checker] command, geneqv, shows the generated
equivalence relation at the current subterm. Thanks to Dave Greve
for an inquiry leading to this enhancement.
A new reader macro, #u, permits the use of underscore characters in a
number. See [sharp-u-reader]. Thanks to Jared Davis for requesting
this capability.
New [proof-checker] commands pl and pr provide interfaces to the ACL2
commands :[pl] and :[pr], respectively. These can be useful if you
want to see trivially-proved hypotheses, as now clarified in the
[proof-checker] documentation for its show-rewrites command. See
[proof-checker-commands]. Thanks to Pete Manolios for suggesting
such clarification and capability.
It is now legal to call [non-executable] functions without the usual
[signature] restrictions imposed on executable code. For example,
the third event below was not admissible, but now it is.
(defstobj foo fld)
(defun-nx id (x)
x)
(defun f (foo)
(declare (xargs :stobjs foo :verify-guards nil))
(cons 3 (id foo)))
Thanks to Jared Davis for requesting this enhancement, in particular
for calling non-executable functions in the :logic part of an [mbe]
call. Here is Jared's example, which is admissible now but formerly
was not.
(defstobj foo (fld))
(defun-nx my-identity (x) x)
(defun my-fld (foo)
(declare (xargs :stobjs foo))
(mbe :logic (my-identity foo)
:exec (let ((val (fld foo)))
(update-fld val foo))))
A new macro, [non-exec], allows the use of non-executable code, for
example inside ordinary function definitions. Thanks to Sol Swords
for requesting this enhancement.
A new ``provisional certification'' process is supported that can
allow [books] to be certified before their included sub-books have
been certified, thus allowing for potentially much greater
`make'-level parallelism. See [provisional-certification]. Thanks
to Jared Davis for requesting this feature and for helpful
discussions, based in part on rudimentary provisional certification
schemes that he developed first at Rockwell Collins and later for
his `Milawa' project. Also, thanks to Jared and to Sol Swords for
testing this feature and for providing a fix for a bug in a
preliminary implementation, and thanks to Sol for providing
performance feedback and a crucial suggestion that led to an
improved implementation.
Event summaries now show the names of events that were mentioned in
[hints] of type :use, :by, or :clause-processor. See
[set-inhibited-summary-types]. Thanks to Francisco J. Martin Mateos
for requesting such an enhancement (actually thanks to the
community, as his request is the most recent but this has come up
from time to time before).
ACL2 now stores a data structure representing the relation ``Event A
is used in the proof of Event B.'' See [dead-events], which
explains this data structure and mentions one application: to
identify dead code and unused theorems. Thanks to Shilpi Goel for
requesting such a feature and for helpful feedback.
A new [documentation] topic provides a guide to programming with
state; see [programming-with-state]. Thanks to Sarah Weissman for
suggesting that such a guide might be useful, and to David Rager
for helpful feedback on a preliminary version. There also has been
some corresponding reorganization of the documentation as well as
creation of additional documentation (e.g., see
[state-global-let*]). Now, most built-in functions and macros
commonly used in programs (as opposed to [events] like [defun], for
example) are subtopics of a new topic --- see [ACL2-built-ins] ---
which is a subtopic of [programming], a topic that in turn has
considerably fewer direct subtopics than before.
It is now possible to bind extra variables in a :USE hint, thus
avoiding the error message: ``The formula you wish to instantiate,
..., mentions only the variable(s) ...''. See [lemma-instance], in
particular the discussion of keyword :extra-bindings-ok. Thanks to
Sol Swords for requesting such an enhancement.
The function read-object-suppress is like read-object except that it
avoids errors and discards the value read. See [io].
A [stobj] may now be passed as an argument where another stobj is
expected if the two are ``congruent''. See [defstobj], in
particular, its discussion of the new :congruent-to keyword of
defstobj. Thanks to Sol Swords for requesting this enhancement and
for useful discussions contributing to its design.
A new top-level utility has been provided that shows the assembly
language for a defined function symbol; see [disassemble$]. Thanks
to Jared Davis for requesting such a utility and to Shilpi Goel for
pointing out an inconvenience with the initial implementation. Note
that it uses the distributed book books/misc/disassemble.lisp,
which users are welcome to modify (see [community-books]).
The macro set-accumulated-persistence is an alias for
[accumulated-persistence]. Thanks to Robert Krug for suggesting
this addition.
A new [documentation] topic lists lesser-known and advanced ACL2
features, intended for those with prior ACL2 experience who wish to
extend their knowledge of ACL2 capabilities. See
[advanced-features]. Thanks to Warren Hunt and Anna Slobodova for
requesting such information.
A new macro, [deftheory-static], provides a variant of [deftheory]
such that the resulting theory is the same at [include-book] time
as it was at [certify-book] time. Thanks to Robert Krug for helpful
discussions on this new feature and for updating his
books/arithmetic-5/ distributed books to use this feature.
A new event, [defabsstobj], provides a new way to introduce
single-threaded objects (see [stobj] and see [defstobj]). These
so-called ``abstract [stobj]s'' permit user-provided logical
definitions for primitive operations on stobjs, for example using
an alist-based representation instead of a list-based
representation for array fields. Moreover, the proof obligations
guarantee that the recognizer is preserved; hence the
implementation avoids executing the recognizer, which may be an
arbitrarily complex invariant that otherwise would be an expensive
part of [guard] checks. Thanks to Warren Hunt for a request leading
us to design and implement this new feature, and thanks to Rob
Sumners for a request leading us to implement a related utility,
[defabsstobj-missing-events]. See [defabsstobj]. Also thanks to Sol
Swords for sending an example exhibiting a bug in the initial
implementation, which has been fixed.
A new command, :psof <filename>, is like :pso but directs proof
replay output to the specified file. For large proofs, :[psof] may
complete much more quickly than :[pso]. see [psof]. More generally,
a new utility, [wof] (an acronym for ``With Output File''), directs
standard output and proofs output to a file; see [wof].
The new macro [defnd] defines a function with :[guard] t and
[disable]s that function, in analogy to how [defund] defines with
[defun] and then [disable]s. Thanks to Shilpi Goel for requesting
this feature.
The :[pl2] command now shows :[linear] rules; and a new
[proof-checker] command, show-linears (equivalently, sls), is an
analogue of the [proof-checker] show-rewrites (sr) command, but for
[linear] rules. Thanks to Shilpi Goel for requesting this new
proof-checker command. Finally, a corresponding new proof-checker
command, apply-linear (al), is an analogue of the [proof-checker]
rewrite (r) command, but for [linear] rules.
The macros [add-macro-fn] and [remove-macro-fn] replace macros
[add-binop] and [remove-binop], respectively, though the latter
continue to work. The new macros allow you to decide whether or not
to display calls of binary macros as flat calls for
right-associated arguments, e.g., (append x y z) rather than
(append x (append y z)). See [add-macro-fn].
It is now possible to request that the host Lisp compiler inline
calls of specified functions, or to direct that the host Lisp
compiler not inline such calls. See [defun-inline] and see
[defun-notinline]. We thank Jared Davis for several extensive,
relevant conversations, and for finding a bug in a preliminary
implementation. We also thank others who have engaged in
discussions with us about inlining for ACL2; besides Jared Davis,
we recall such conversations with Rob Sumners, Dave Greve, and
Shilpi Goel.
HEURISTIC IMPROVEMENTS
Reading of ACL2 [arrays] (see [aref1], see [aref2]) has been made
more efficient (as tested with CCL as the host Lisp) in the case of
consecutive repeated reads of the same named array. Thanks to Jared
Davis and Sol Swords for contributing this improvement.
Slightly modified the induction schemes stored, so that calls of
so-called ``guard-holders'' (such as [mbe] and [prog2$] --- indeed,
any call of [return-last] --- and [the]) are expanded away. In
particular, calls of equality variants such as [member] are treated
as their corresponding function calls, e.g., [member-equal]; see
[equality-variants]. Guard-holders are also now expanded away
before storing [constraint]s for [encapsulate] [events], which can
sometimes result in simpler constraints.
Improved the performance of [dmr] (technical note: by modifying raw
Lisp code for function dmr-flush, replacing finish-output by
force-output).
We now avoid certain rewriting loops. A long comment about this
change, including an example of a loop that no longer occurs, may
be found in source function expand-permission-result.
Slightly strengthened [type-set] reasoning at the level of literals
(i.e., top-level hypotheses and conclusions). See the comment in
ACL2 source function rewrite-atm about the ``use of dwp = t'' for
an example of a theorem provable only after this change.
Strengthened the ability of [type-set] reasoning to make deductions
about terms being integers or non-integer rationals. The following
example illustrates the enhancement: before the change, no
simplification was performed, but after the change, the conclusion
simplifies to (foo t). Thanks to Robert Krug for conveying the
problem to us and outlining a solution.
(defstub foo (x) t)
(thm ; should reduce conclusion to (foo t)
(implies (and (rationalp x)
(rationalp y)
(integerp (+ x (* 1/3 y))))
(foo (integerp (+ y (* 3 x))))))
BUG FIXES
Fixed a class of soundness bugs involving each of the following
functions: [getenv$], [get-wormhole-status], [cpu-core-count],
[wormhole-p], [random$], file-write-date$, and serialize-read-fn,
and (for the HONS version of ACL2) [clear-memoize-table] and
[clear-memoize-tables] as well as (possible soundness bug)
serialize-write-fn. For example, we were able to admit the
following events, but that is no longer the case (neither for
getenv$ as shown, nor analogously for other functions listed
above).
(defthm not-true
(stringp (cadr (getenv$ \"PWD\" (build-state))))
:rule-classes nil)
(defthm contradiction
nil
:hints ((\"Goal\"
:in-theory (disable (getenv$))
:use not-true))
:rule-classes nil)
Fixed a soundness bug involving with-live-state, which could cause an
error in the use of [add-include-book-dir] or
[delete-include-book-dir] in a book or its [portcullis] commands.
See [with-live-state], as the documentation for this macro has been
updated; in particular it is now untouchable (see
[remove-untouchable]) and is intended only for system hackers.
Thanks to Jared Davis for reporting a bug in the use of
[add-include-book-dir] after our first attempt at a fix.
Fixed a soundness bug based on the use of [skip-proofs] together with
the little-used argument k=t for [certify-book]. An example proof
of nil appears in a comment in the ACL2 sources, in (deflabel
note-5-0 ...).
Fixed a soundness bug that allowed users to define new
[proof-checker] primitive commands. Before this fix, a book proving
nil could be certified, as shown in a comment now in the
introduction of the [table] pc-command-table in source file
proof-checker-a.lisp.
(Technical change, primarily related to [make-event]:) Plugged a
security hole that allowed [books]' [certificate]s to be
out-of-date with respect to [make-event] expansions, but not
recognized as such. The change is to include the so-called
expansion-alist in the certificate's checksum. An example appears
in a comment in the ACL2 sources, in (deflabel note-5-0 ...).
Fixed a bug in [guard] verification due to expanding calls of
primitives when translating user-level terms to internal form, so
called ``translated terms'' (see [term]). While we have not
observed a soundness hole due to this bug, we have not ruled it
out. Before the bug fix, the following event was admissible, as
guard verification succeeded (but clearly should not have).
(defun f ()
(declare (xargs :guard t))
(car (identity 3)))
For those who want details about this bug, we analyze how ACL2
generates [guard] proof obligations for this example. During that
process, it evaluates ground subexpressions. Thus, (identity '3) is
first simplified to '3; so a term must be built from the
application of car to '3. Guard-checking is always turned on when
generating guard proof obligations, so now, ACL2 refuses to
simplify (car '3) to 'nil. However, before this bug fix, when ACL2
was building a term by applying car to argument '3, it did so
directly without checking guards; source code function cons-term is
`smart' that way. After the fix, such term-building reduction is
only performed when the primitive's guard is met.
While calls of many event macros had been prohibited inside
executable code, others should have been but were not. For example,
the following was formerly allowed.
(defun foo (state)
(declare (xargs :mode :program :stobjs state))
(add-custom-keyword-hint :my-hint (identity nil)))
(foo state) ; Caused hard raw Lisp error!
Thus, several event macros (including for example
[add-custom-keyword-hint]) may no longer be called inside
executable code.
Fixed an assertion that could occur, for example, after reverting to
prove the original goal by induction and generating a goal of NIL.
Thanks to Jared Davis for sending us a helpful example to bring
this bug to our attention.
It was possible for [defstobj] to generate raw Lisp code with
excessively restrictive type declarations. This has been fixed.
Thanks to Warren Hunt for reporting this bug and sending an example
that illustrates it. See [stobj-example-2] for examples of such raw
Lisp code; now, one finds (and fixnum (integer 0 *)) where formerly
the type was restricted to (integer 0 268435455).
Fixed a bug in that was ignoring the use of
:computed-hint-replacement in certain cases involving a combination
of computed hints and custom keyword hints. Thanks to Robert Krug
for reporting this bug and sending a very helpful example.
Fixed a bug in the output from [defattach], which was failing to list
previous [events] in the message about ``bypassing constraints that
have been proved when processing the event(s)''.
(GCL only) Fixed a bug in [set-debugger-enable] (which was only a bug
in GCL, not an issue for other host Lisps).
Fixed ACL2 trace output to indent properly for levels above 99 (up to
9999). Thanks to Warren Hunt for bringing this bug to our
attention.
Fixed a bug in the reporting of times in event summaries --- probably
one that has been very long-standing! The times reported had often
been too small in the case of compound [events], notably
[include-book]. Thanks to everyone who reported this problem (we
have a record of emails from Eric Smith and Jared Davis on this
issue).
Fixed a bug in :expand [hints], where the use of :lambdas could
prevent other parts of such a hint. For example, the following
invocation of [thm] failed before this fix was made.
(defund foo (x) (cons x x))
(thm (equal (car (foo x)) x)
:hints ((\"Goal\" :expand (:lambdas (foo x)))))
Certain ``program-only'' function calls will now cause hard Lisp
errors. (The rather obscure reason for this fix is to support
logical modeling of the ACL2 evaluator. A relevant technical
discussion may be found in source function oneify-cltl-code, at the
binding of variable fail_program-only-safe.)
There was an unnecessary restriction that [flet]-bound functions must
return all [stobj]s among their inputs. For example, the following
definition was rejected because state was not among the outputs of
h. This restriction has been removed.
(defun foo (state)
(declare (xargs :stobjs state))
(flet ((h (state) (f-boundp-global 'x state)))
(h state)))
We fixed a bug, introduced in the preceding release (Version 4.3), in
the check for irrelevant formals (see [irrelevant-formals]). That
check had been too lenient in its handling of lambda ([let])
expressions, for example allowing the following definition to be
admitted in spite of its first formal parameter obviously being
irrelevant.
(defun foo (x clk)
(if (zp clk)
:diverge
(let ((clk (1- clk)))
(foo x clk))))
Fixed a bug in the mini-proveall target in GNUmakefile. The fix
includes a slight change to the :mini-proveall [command] (an extra
event at the end). Thanks to Camm Maguire for reporting this bug.
Fixed a bug that occurred when [certify-book] was called after using
[set-fmt-soft-right-margin] or [set-fmt-hard-right-margin] to set a
small right margin.
Fixed [set-inhibit-warnings] so that it takes effect for a subsequent
[include-book] event. Thanks to Jared Davis and David Rager for
queries that led to this fix.
Hard Lisp errors are now avoided for certain :[rewrite] rules: those
whose [equivalence] relation is other than equal when the rule is
originally processed, but is no longer a known equivalence relation
when the rule is to be stored. Thanks to Jared Davis for sending a
useful example, a minor variant of which is included in a comment
in source function interpret-term-as-rewrite-rule (file
defthm.lisp).
Fixed a bug in the ACL2 evaluator (source function raw-ev-fncall),
which was unlikely to be exhibited in practice.
Fixed a hard Lisp error that could occur for ill-formed :[meta]
[rule-classes], e.g., (:meta :trigger-fns '(foo)).
It is now an error to include a [stobj] name in the :renaming alist
(see [defstobj]).
Some bogus warnings about non-recursive function symbols have been
eliminated for rules of class :[type-prescription].
(Allegro CL host Lisp only) Fixed an obsolete setting of compiler
variable comp:declared-fixnums-remain-fixnums-switch, which may
have been responsible for intermittent (and infrequent) checksum
errors encountered while including books during certification of
the regression suite.
Fixed a [proof-checker] bug that could result in duplicate goal names
in the case of forced hypotheses. An example showing this bug,
before the fix, appears in a comment in the ACL2 sources, in
(deflabel note-5-0 ...).
We fixed a bug in a prover routine involved in [type-set]
computations involving linear arithmetic. This bug has been around
since at least as far back as Version_3.3 (released November,
2007). We are not aware of any resulting unsoundness, though it did
have the potential to weaken the prover. For example, the following
is proved now, but was not proved before the bug was fixed.
(thm
(implies (and (rationalp x)
(rationalp y)
(integerp (+ (* 1/3 y) x)))
(integerp (+ y (* 3 x))))
:hints ((\"Goal\" :in-theory (disable commutativity-of-+))))
Although all bets are off when using redefinition (see
[ld-redefinition-action]), we wish to minimize negative effects of
its use, especially raw Lisp errors. The examples below had caused
raw Lisp errors, but no longer.
(defstobj st fld :inline t)
(redef!)
(defstobj st new0 fld)
(u)
(fld st) ; previously an error, which is now fixed
; Fresh ACL2 session:
(redef!)
(defun foo (x) x)
(defmacro foo (x) `(quote ,x))
(u)
; Fresh ACL2 session:
(redef!)
(defmacro foo (x) (cons 'list x))
(defun foo (x) x)
Fixed a bug that could cause hard Lisp errors in an [encapsulate]
event. Thanks to Sol Swords for sending an example that exhibited
this bug. Here is a simpler such example; the bug was in how it was
checked whether the [guard] for a guard-verified function (here, g)
depends on some function introduced in the [signature] of the
[encapsulate] (here, the function f).
(encapsulate
((f (x) t))
(local (defun f (x) (declare (xargs :guard t)) x))
(defun g (x)
(declare (xargs :guard (if (integerp x) (f x) t)))
x))
Fixed a bug in mfc-relieve-hyp that we believe could prohibit its use
on the last hypothesis. Thanks to Sol Swords for reporting this bug
and providing a fix.
The syntax #! (see [sharp-bang-reader]) was broken after a skipped
readtime conditional. For example, the following input line caused
an error.
#+skip #!acl2(quote 3)
This bug has been fixed.
Fixed a bug in the [break-rewrite] utility, which was evidenced by
error messages that could occur when dealing with free variables.
An example of such an error message is the following; we thank
Robert Krug for sending us an example that produced this error and
enabled us to produce a fix.
HARD ACL2 ERROR in TILDE-@-FAILURE-REASON-PHRASE1: Unrecognized failure
reason, ((MEM-ARRAY . X86) (ADDR QUOTE 9)).
We fixed an obscure bug that we believe could interfere with
[defproxy] because of an incorrect (declaim (notinline <function>))
form.
CHANGES AT THE SYSTEM LEVEL AND TO DISTRIBUTED BOOKS
Improvements have been made related to the reading of characters. In
particular, checks are now done for ASCII encoding and for the
expected [char-code] values for Space, Tab, Newline, Page, and
Rubout. Also, an error no longer occurs with certain uses of
non-standard characters. For example, it had caused an error to
certify a book after a single [portcullis] [command] of (make-event
`(defconst *my-null* ,(code-char 0))); but this is no longer an
issue. Thanks to Jared Davis for helpful correspondence that led us
to make these improvements.
The character encoding for reading from files has been fixed at
iso-8859-1. See [character-encoding]. Thanks to Jared Davis for
bringing this portability issue to our attention (as this change
arose in order to deal with a change in the default character
encoding for the host Lisp, CCL), and pointing us in the right
direction for dealing with it. In many cases, the character
encoding for reading from the terminal is also iso-8859-1; but this
is not guaranteed. In particular, when the host Lisp is SBCL this
may not be the case.
Although the HTML documentation is distributed with ACL2, it had not
been possible for users to build that documentation without
omitting graphics, for example on the ACL2 home page. That has been
fixed, as files graphics/*.gif are now distributed.
Compiler warnings are suppressed more completely than they had been
before. For example, the following had produced a compiler warning
when the host Lisp is CCL, but no longer does so.
(defun f () (car 3))
(trace$ f)
Removed support for ``tainted'' [certificate]s. One reason is that
there are rarely incremental releases. A stronger reason is that
for the compatibility of a new release is with the previous
non-incremental release, it's not particularly relevant whether or
not the new release is incremental.
The `make' variable BOOKS can now be defined above the line that
includes Makefile-generic. (For relevant background, see
[books-certification-classic].)
(SBCL only) ACL2 images built on SBCL now have an option,
--dynamic-space-size 2000, that can avoid space problems that could
previously have caused the session to die.
The default value for variable LISP in file GNUmakefile is now ccl.
Thus, if you use `make' in the standard way to build an ACL2
executable, the default host Lisp is ccl rather than gcl.
EMACS SUPPORT
EXPERIMENTAL VERSIONS
For the version supporting the reals, ACL2(r) (see [real]), the
supporting function floor1 has been defined in raw Lisp. This
avoids an error such as in the following case.
(defun f () (declare (xargs :guard t)) (floor1 8/3))
(f) ; had caused raw Lisp error, before the fix
Among the enhancements for the parallel version, ACL2(p) (see
[parallelism]), are the following. We thank David Rager for his
work in developing ACL2(p) and these improvements in particular.
The macro set-parallel-evaluation has been renamed
[set-parallel-execution].
Calls of the macro [set-waterfall-printing] are no longer [events],
so may not be placed at the top level of [books]. However, it
is easy to create events that have these effects; see
[set-waterfall-printing]. Note that now, :[ubt] and similar
commands do not change the settings for either
waterfall-parallelism or waterfall-printing.
The implementation of [deflock] has been improved. Now, the macro it
defines can provide a lock when invoked inside a
[guard]-verified or :[program] mode function. Previously, this
was only the case if the function definition was loaded from
raw Lisp, typically via a compiled file.
The underlying implementation for waterfall parallelism (see
[set-waterfall-parallelism]) has been improved. As a result,
even the largest proofs in the regression suite can be run
efficiently in :resource-based waterfall parallelism mode.
Among these improvements is one that can prevent machines from
rebooting because operating system limits have been exceeded;
thanks to Robert Krug for bringing this issue to our attention.
There is also a new flag for configuring the way waterfall
parallelism behaves once underlying system resource limits are
reached. This flag is most relevant to :full waterfall
parallelism. see [set-total-parallelism-work-limit] for more
information.
The [dmr] utility has the same behavior in ACL2(p) as it has in ACL2
unless waterfall-parallelism has been set to a non-nil value
(see [set-waterfall-parallelism]), in which case statistics
about parallel execution are printed instead of the usual
information.
The user can now build the regression suite using waterfall
[parallelism]. See the distributed file
acl2-customization-files/README for details, and see
[unsupported-waterfall-parallelism-features] for a disclaimer
related to building the regression suite using waterfall
parallelism.
When building ACL2 with both the hons and parallelism extensions
(what is called ``ACL2(p)'' or, equivalently, ``ACL2(hp)''),
the functions that are automatically memoized by the hons
extension are now automatically unmemoized and memoized when
the user toggles waterfall parallelism on and off,
respectively.
Calling [set-waterfall-parallelism] with a flag of t now results in
the same settings as if it were called with a flag of
:resource-based, which is now the recommended mode for
waterfall parallelism. Thanks to Shilpi Goel for requesting
this feature.
The prover now aborts in a timely way in response to interrupts
issued during a proof with waterfall parallelism enabled. (This
had often not been the case.) Thanks to Shilpi Goel for
requesting this improvement.
Among the enhancements for the HONS extension (see
[hons-and-memoization]) are the following.
The compact-print code has been replaced by new serialization
routines contributed by Jared Davis. This may improve
performance when including books that contain [make-event]s
that expand to very large constants. You can also now save
objects to disk without going into raw lisp; see [serialize]
for details.
Printing of certain messages has been sped up (by using Lisp function
force-output in place of finish-output). Thanks to Jared Davis
for contributing this improvement.
[Stobj] array writes are perhaps twice as fast.
It is now permitted to [memoize] functions that take user-defined
[stobj]s as inputs, provided that no [stobj]s are returned.
Even if stobjs are returned, memoization is permitted provided
the condition is nil, as when profiling (see [profile]). Thanks
to Sol Swords for an observation that led to this improvement
and for useful conversations, including follow-up leading us to
improve our initial implementation.
Fixes have been made for memoizing with a non-nil value of
:ideal-okp. Errors had occurred when memoizing with a
:condition other than t for a :[logic] mode function that had
not been [guard]-verified, even with a non-nil value of
:ideal-okp; and after successfully memoizing such a function
(without such :condition), it had not been possible to
[unmemoize] it. Thanks to Sol Swords for reporting issues with
the :ideal-okp argument of [memoize].
If a book defined a function that was subsequently [memoize]d in that
book, the function would no longer behaves as memoized upon
completion of book certification (unless that [certify-book]
command was undone and replaced by evaluation of a
corresponding [include-book] command). This has been fixed.
Thanks to David Rager for pointing out the problem by sending
an example.
We now support ACL2(h) built not only on 64-bit CCL but also on all
supported host Ansi Common Lisps (i.e., all supported host
Lisps except GCL). Thanks to Jared Davis for doing much of the
work to make this improvement. Note that performance will
likely be best for 64-bit CCL; for some Lisps, performance may
be much worse, probably depending in part on the underlying
implementation of hash tables.")
(NOTE-6-0
(RELEASE-NOTES)
"ACL2 Version 6.0 (December, 2012) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 5.0 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, changes at the system level,
Emacs support, and experimental versions. Each change is described
in just one category, though of course many changes could be placed
in more than one category.
NOTE. But we start with one major change that is outside the usual
categories:
LICENSE change
The ACL2 license has been changed from GPL Version 2 to a 3-clause
BSD license, found in the LICENSE file distributed with ACL2.
CHANGES TO EXISTING FEATURES
Function [fmt-to-string] and similar functions (see
[printing-to-strings]) now use the default right margin settings;
formerly the right margin had been set at 10,000. If you want the
former behavior, you can use the :fmt-control-alist, as illustrated
below.
(fmt-to-string \"~x0\"
(list (cons #\\0 (make-list 30)))
:fmt-control-alist
`((fmt-soft-right-margin . 10000)
(fmt-hard-right-margin . 10000)))
The use of attachments (see [defattach]) has been made more
efficient, avoiding some low-level checks (Common Lisp `boundp'
checks). Thanks to Shilpi Goel for constructing an example that we
used to help direct us to remove inefficiency. The following
results for that example --- a Fibonacci program run on a machine
interpreter in raw-mode (see [set-raw-mode]) --- give a sense of
the potential speedup, though we note that a full ACL2(h)
regression showed no significant speedup.
; Time before the change:
; 0.89 seconds realtime, 0.90 seconds runtime
; Time after the change:
; 0.75 seconds realtime, 0.75 seconds runtime
; Time when cheating to avoid the cost of attachments, by redefining a
; function to BE its attachment (so, this gives a lower bound on possible
; execution time):
; 0.72 seconds realtime, 0.72 seconds runtime
Functions read-acl2-oracle and read-acl2-oracle@par are no longer
untouchable (see [remove-untouchable]). We reported this change for
Version_5.0 but it was not made; thanks to Jared Davis for bringing
this to our attention. Function get-timer also is no longer
untouchable.
The function [butlast] now behaves more reasonably on arguments
violating its [guard]. For example, (butlast '(1 2 3) -1) is now
provably equal to (1 2 3) instead of to (1 2 3 nil). Thanks to
Jared Davis for suggesting a change to the definition of butlast.
The utilities mfc-ts and mfc-ap (see [extended-metafunctions])
formerly never used forcing (see [force]). Now, by default, forcing
is allowed during execution of these functions if and only if it is
permitted in the rewriting environment where they are called.
Moreover, these and the mfc-xx utilities --- mfc-rw, mfc-rw+, and
mfc-relieve-hyp --- are now macros that take (optional) keyword
arguments :forcep and :ttreep. The :forcep argument is :same by
default, providing the forcing behavior inherited from the
environment (as described above); but it can be the symbol t or
nil, indicating that forcing is to be enabled or disabled,
respectively. The :ttree argument is nil by default, but when it is
t, then a second value is returned, which is a tag-tree. See
[extended-metafunctions].
Many improvements have been made to the tau-system (see
[tau-system]), including support for arithmetic intervals bounded
by constants. Thus, for example, (and (<= 0 x) (<= x 15)) is a tau
predicate. The [documentation] has also been improved (see
[introduction-to-the-tau-system]). Also see [time-tracker-tau] for
discussion of how the new [time-tracker] utility can help discover
ways to detect slowdown related to the tau-system.
The [defthm] [events] printed by [defabsstobj], namely those that
remain to be proved, are now given with :rule-classes nil since
there is probably no intention to use them as rules. Thanks to
Robert Krug for suggesting that we consider this change.
The formal parameters for a macro definition (see [defmacro]) may now
include [state] and user-defined [stobj]s. (However, macro formals
may not be declared as stobjs; see [xargs].) Thanks to Jose Luis
Ruiz-Reina for raising this issue and to Rob Sumners for helpful
conversations --- both of these nearly 10 years ago!
The utilities [defun-inline], [defun-notinline], [defund-inline], and
[defund-notinline] have been simplified, by taking advantage of the
lifting of restrictions on formal parameters of macro definitions
mentioned above (involving symbols that happen to be [stobj]
names). Now, when any of the above four utilities is called with a
given set of formal parameters, those formals will be used not only
for the generated [defun] event but also for the generated
[defmacro] event. (Previously, they had been renamed for the
[defmacro] event in order to respect the stobj name restriction
that no longer exists.) Thanks to Jared Davis for pointing out the
value of making this change.
The [events] [add-invisible-fns] and [remove-invisible-fns] now
convert arguments as appropriate using the [macro-aliases-table].
For example, the event (add-invisible-fns append car) is now legal
(though probably not a good idea), because add-invisible-fns is now
sensitive to the fact that [append] maps to [binary-append] in the
[macro-aliases-table].
When :pe is applied to a built-in function that does not have a
defining event, such as [symbolp], :pe now gives more useful output
that points to the documentation instead of printing a call of
ENTER-BOOT-STRAP-MODE. Thanks to Anthony Knape for bringing this
issue to our attention.
The macros [memoize] and [unmemoize] now cause a warning rather than
an error in ACL2 (and work as before in ACL2(h)).
Terms are now parsed into :[type-prescription] rules in a manner that
removes [let] bindings both at the top level and in the conclusion
(but still not in the hypotheses of the rule). See
[type-prescription]. Thanks to Jared Davis for requesting such an
enhancement.
Printing of numbers is now appropriately sensitive to the print
radix; see [set-print-radix]. Thanks to Shilpi Goel for requesting
this enhancement.
The system function explode-atom no longer includes the radix
indicator. The new function explode-atom+ may be used for that
purpose.
NEW FEATURES
Among the new features for system hackers are analogues of system
function simple-translate-and-eval that do not return [state].
(Thanks to David Rager for requesting this feature and helpful
conversations on its implementation.) This and other low-level
changes are typically documented in comments in the corresponding
release note event, which in this case is (deflabel note-6-0 ...).
More built-in functions are now [guard]-verified (and in :[logic]
mode). Furthermore, a mechanism exists for marking yet more
built-in functions as guard-verified based on [books] contributed
by users; see Part II of
{http://www.cs.utexas.edu/users/moore/acl2/open-architecture/ |
http://www.cs.utexas.edu/users/moore/acl2/open-architecture/}. The
current state of that enterprise may be viewed by evaluating the
constant *system-verify-guards-alist*, which associates a community
book name with a list of functions. When ACL2 is built in the
normal way, each of those functions is marked as guard-verified
when ACL2 is started up; but a special developer build can be used
to check that the indicated book, together with its sub-books,
proves that those functions are guard-verified.
Metatheorems (see [meta]) may now have additional hypotheses, called
``meta-extract hypotheses'', that allow metafunctions to depend on
the validity of certain terms extracted from the context or the
logical [world]. See [meta-extract]. Thanks to Sol Swords for
providing an initial implementation, together with very helpful
discussions as well as a community book,
books/clause-processors/meta-extract-user.lisp, that extends the
power of meta-extract hypotheses.
New utilities [oracle-funcall], [oracle-apply], and
[oracle-apply-raw] call a function argument on specified arguments.
Thanks to Jared Davis for requesting this utility.
A new utility makes it convenient to track time spent inside
specified function calls or, more generally, during specified
evaluation. See [time-tracker].
New runic designators make it easy to refer to macro names when
building theories. Thus, for example, the object (:i append) may be
used in theory expressions to designate the [rune] (:induction
binary-append). See [theories]. Thanks to Jared Davis for a useful
discussion leading to this enhancement.
[Defabsstobj] [events] now take an optional :congruent-to keyword
argument, much like [defstobj]. Thanks to Sol Swords for requesting
this feature and for suggesting a very nice optimization that
avoids the need to prove additional lemmas.
[Flet] may now include inline and notinline declarations. Thanks to
Jared Davis for requesting this feature.
The utility gc-verbose controls printing of messages by the garbage
collector, for certain host Lisps. See [gc-verbose]. Thanks to
Shilpi Goel for requesting this utility.
Added definitions of functions [nat-listp] and [ACL2-number-listp].
Thanks to Harsh Raju Chamarthi for requesting these additions. Many
community books had varying definitions of these functions; these
additions guarantee that all books must agree on how these two
functions are defined. (Some community books have been changed in
order that they remain certifiable, given these additions.) Note
that a few built-in :[forward-chaining] rules were modified in
order to accommodate these additions, and the definition of
[integer-listp] was modified to call [eq] instead of [equal], like
the other such definitions.
See [get-command-sequence] for a new utility that returns a list of
[command]s between two given command descriptors.
HEURISTIC IMPROVEMENTS
We obtained a substantial speedup --- 13% observed for the regression
suite, and 8% observed for the ACL2(h) regression suite --- by
tweaking the [break-rewrite] implementation to eliminate virtually
all of its overhead when it is not in use (the default, which holds
until :[brr] t is evaluated). Thanks to David Rager for a
conversation involving ACL2(p) performance statistics that
suggested looking at changing [break-rewrite] to boost performance.
The heuristics for automatically expanding recursive function calls
have been changed during proofs by induction. Now, during
induction, more terms that suggested the induction scheme are
automatically expanded. Thanks to David Rager for providing an
example and having discussions with us that spurred us to develop
this heuristic improvement.
BUG FIXES
Fixed a soundness bug in [defabsstobj] based on [guard]s that
violated single-threadedness restrictions. Thanks to Sol Swords for
bringing this bug to our attention and supplying a proof of nil,
which we include as a comment in source file ld.lisp, in (deflabel
note-6-0 ...). We also thank Sol for helpful discussions about
[guard]s of functions introduced by defabsstobj, which has led us
to enhance the [documentation]; see [defabsstobj].
Fixed a soundness bug in [defabsstobj] based on interrupted updates
of abstract stobjs. As part of the fix a new keyword, :PROTECT, has
been introduced for defabsstobj exports, along with a new top-level
defabsstobj keyword, :PROTECT-DEFAULT; see [defabsstobj]. We do
some analysis that we expect will avoid the use of :PROTECT in many
cases, which is fortunate since the use of :PROTECT t may cause a
slight slowdown in (abstract) stobj updates. Thanks to Sol Swords
for bringing this bug to our attention and supplying a proof of
nil, which we include as a comment in source file
other-events.lisp, in the definition of function
set-absstobj-debug.
Fixed a raw Lisp error that occurred when tracing a stobj resize
function, thanks to an error report from Warren Hunt, Marijn Heule,
and Nathan Wetzler.
Fixed a raw Lisp error that occurred for certain ill-formed
signatures, as in the following example.
ACL2 !>(encapsulate
(((f (*) => * :guard t)))
(local (defun f (x) (consp x))))
***********************************************
************ ABORTING from raw Lisp ***********
Error: value (F (*) => * :GUARD T) is not of the expected type SYMBOL.
***********************************************
The notion of ``error triple'' (see [error-triple]) had been
implemented ambiguously, with the result that for a [stobj], st,
the result of evaluating the following two forms was the same: (mv
nil st state) and (mv t st state). Of course, these are just
examples; in general, a result of (mv erp val state) was sometimes
treated as an error triple even when val is a [stobj]. Now, (mv erp
val state) is an error triple only when erp and val are ordinary
(non-[stobj]) values. Thanks to Warren Hunt and Marijn Heule for
bringing this problem to our attention.
The ``with-error-trace'' utility, [wet], now works in the non-error
case when given a form that returns multiple values. (Note however
that [state] will be printed as REPLACED-STATE; and similarly, a
user-defined [stobj], say ST, will be printed as REPLACED-ST.)
Some possible error messages for [defabsstobj] have been fixed that
had been ill-formed. Thanks to Sol Swords for bringing this bug to
our attention.
Fixed a bug that sometimes caused the times displayed in the summary
for [certify-book] to be smaller than the actual times.
Fixed a bug in the [guard]s to system functions fmt-char and fmt-var,
which are no longer :[logic]-mode, guard-verified functions.
(GCL only) Fixed a bug present in Gnu Common Lisp for #u (see
[sharp-u-reader]).
CHANGES AT THE SYSTEM LEVEL
The [state] global variable 'distributed-books-dir has been renamed
'system-books-dir. On a related note, the [documentation] now
refers to ``community books'' rather than ``distributed books'',
and there is a corresponding new documentation topic; see
[community-books].
Fixed a bug in the implementation of [wet] (which is actually in the
community book books/misc/wet.lisp).
A directory, interface/, is no longer part of the ACL2 distribution.
Rather, it is a subdirectory of the ACL2 community books. Thus, if
you fetch those books in the usual way (see the installation
instructions on the ACL2 home page), you will find a directory
books/interface/. Subdirectory emacs/ of that interface directory
provides Emacs support for [proof-tree]s as well an acl2-mode. This
change has been reflected in ACL2 file emacs/emacs-acl2.el, so
users will probably not be impacted if they load that file into
Emacs.
The community books file books/Makefile-generic now causes, by
default, a backtrace to be printed when there is a raw Lisp error.
Some changes have been made to how regressions are run, i.e., to how
the community books are certified. (1) The standard regression now
includes community books directory books/centaur. To skip these
(for example, a Windows system has encountered difficulty with them
even after installing Perl), include ACL2_CENTAUR=skip with your
`make' command. (2) A new `make' (or environment) variable,
ACL2_JOBS, specifies the number of parallel jobs to run, serving as
a replacement for the -j argument of `make' that works for all
community books, including those under directory centaur; see
[books-certification-classic]. (3) It is no longer necessary to do
an ACL2(h) regression in order to build a copy of the documentation
generated by Jared Davis's xdoc utility at
books/xdoc-impl/manual/preview.html; a vanilla ACL2 regression will
build this manual. (4) It is no longer necessary to set the ACL2
environment variable for ACL2(h) regressions if you want to use the
executable saved_acl2h in the ACL2 sources directory.
The ACL2 home page now has a search utility for documentation and
books. Thanks to Shilpi Goel and David Rager for feedback on a
preliminary version of this utility.
(only for SBCL with 64-bit ACL2(h)) The value of SBCL command line
option --dynamic-space-size for ACL2(h) on 64-bit platforms has
been increased from 2000 to 16000 (as explained in a comment in the
ACL2 source definition of *sbcl-dynamic-space-size*).
EMACS SUPPORT
EXPERIMENTAL/ALTERNATE VERSIONS
Among the enhancements for ACL2(r) (see [real]) are the following.
Thanks to Ruben Gamboa for his helpful role in making the following
improvements made with Ruben Gamboa in support for non-standard
analysis in ACL2(r).
Constrained functions can now be introduce as non-classical. See
[signature].
[Defun-sk] now takes a new keyword argument, :CLASSICALP, that
determines whether or not the named function is classical. See
[defun-sk].
Incorporated a bug fix from Ruben Gamboa for [ceiling]. The default
(for `bad' arguments) had been 1, but now we follow normal ACL2
practice by returning 0 in that case.
Among the enhancements for the HONS extension (see
[hons-and-memoization]) are the following.
Macros [with-fast-alist], [with-stolen-alist], and
[fast-alist-free-on-exit] are now defined in ACL2(h), rather
than being defined in the community book
\"books/centaur/misc/hons-extra.lisp\". Thanks to Jared Davis and
Sol Swords for donating this code, and thanks to Jared for
helpful discussions leading to this change.
Among the enhancements for ACL2(p) (see [parallelism]) are the
following. We thank David Rager for his work in developing ACL2(p)
and for his helpful role in these improvements.
A bug has been fixed that could leave one in a [wormhole], awaiting
input, after an error, such as an error in an :in-theory hint
during a proof. Thanks to Shilpi Goel for bringing this bug to
our attention.
A key checkpoint for a given goal is now printed only once.
Previously, if a key checkpoint led to more than one goal
pushed for proof by induction, the key checkpoint would be
printed once for each such goal during the proof, and also once
for each such goal in the summary at the end.")
(NOTE-6-1
(RELEASE-NOTES)
"ACL2 Version 6.1 (February, 2013) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 6.0 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, changes at the system level,
Emacs support, and experimental versions. Each change is described
in just one category, though of course many changes could be placed
in more than one category.
CHANGES TO EXISTING FEATURES
More system functions are in :[logic] mode, [guard]-verified.
Evaluate
(strip-cars (cdr (assoc-equal \"system/top\" *system-verify-guards-alist*)))
for the list of functions checked to be guard-verifiable in the
community books. Thanks to those who have contributed to this
effort, as shown in file headers in directory system/ of the
community books.
The macro [defund] now avoids an error when :mode :program has been
specified in an [xargs] form of a [declare] form, for example:
(defund f (x) (declare (xargs :mode :program)) x). It does this by
avoiding the generation of [in-theory] [events] in such cases.
Thanks to David Rager and Jared Davis for requesting such a change,
and for ensuing helpful discussions.
Added a field :UNIFY-SUBST to metafunction contexts (see
[extended-metafunctions]), accessed with function mfc-unify-subst.
Thanks to Sol Swords for requesting this enhancement.
The functions [sys-call] and [sys-call-status] are now
[guard]-verified :[logic]-mode functions.
It had been the case that if any supporter of a dependent clause
processor (see [define-trusted-clause-processor]) is among the
ancestors of a given formula, then it was illegal to apply
functional instantiation (see [lemma-instance]) to that formula.
Now, this is illegal only if some such supporter is in the domain
of the functional substitution.
The tau system (see [tau-system], or if you are unfamiliar with the
tau system, see [introduction-to-the-tau-system]) now allows the
user to define and verify functions that compute bounds on
arithmetic expressions. See [bounders].
The utility print-summary-user has been replaced by
[finalize-event-user], which is described below. If you previously
attached a function to print-summary-user, say
my-print-summary-user, then you can get the effect you had
previously as follows.
(defun my-finalize-event-user (state)
(declare (xargs :mode :logic :stobjs state))
(prog2$ (my-print-summary-user state)
state))
(defattach finalize-event-user my-finalize-event-user)
It had been the case that when you [ld] a file, the connected book
directory (see [cbd]) was set to the canonical pathname of that
file's directory for the duration of the LD call. This could cause
problems, however, if the file is actually a soft link: an
[include-book] form in the book with a relative pathname for the
book would be resolved with respect to the absolute pathname for
that link, which is probably not what was intended. So soft links
are no longer followed when computing the above connected book
directory. The following example, which is how we discovered this
problem, may clarify. We attempted to execute the form (ld
\"top.lisp\") using ACL2(r) (see [real]) in community books directory
nonstd/arithmetic/, where all of the .lisp files are soft links to
files in arithmetic/. Thus, the form (include-book \"equalities\")
attempted to include arithmetic/equalities instead of
nonstd/arithmetic/equalities, which caused an error.
We no longer document the use of value :START for
[with-prover-step-limit]. This value has always been used by the
ACL2 implementation and may have semantics that change with new
ACL2 versions. If you have reason to use this value, please contact
the ACL2 implementors.
NEW FEATURES
By default, the prover now gives information about case splits. See
[splitter]. Thanks to many ACL2 users, most recently David Rager,
for requesting such a capability. Also thanks to David Rager and
Jared Davis for helpful discussions, and thanks to Robert Krug for
feedback on the initial implementation and documentation that led
us to make improvements.
New utilities [initialize-event-user] and [finalize-event-user] allow
the user to run [state]-modifying code at the start and end of
[events]. Thanks to Harsh Raju Chamarthi for requesting these
capabilities. Note that [finalize-event-user] replaces
print-summary-user.
HEURISTIC IMPROVEMENTS
Several heuristic improvements have been made to the tau system, even
if you do not explicitly use the new capability for computing
bounds on arithmetic expressions, mentioned above. See
[tau-system], or if you are unfamiliar with the tau system, see
[introduction-to-the-tau-system].
BUG FIXES
A soundness bug has been fixed that exploited the use of expansion
files (see [book-compiled-file]) together with [defstobj]. For an
example illustrating this bug, see the comment about
``Expansion/Defstobj Bug'' in the form (deflabel note-6-1 ...) in
ACL2 source file ld.lisp.
We fixed a soundness bug involving system function
[canonical-pathname] and (most likely) other functions in the
former value of constant *unattachable-primitives*. Thanks to Jared
Davis and Sol Swords for bringing this bug to our attention by way
of an example. We include a very slight variant of that example in
a comment within the form (deflabel note-6-1 ...) in ACL2 source
file ld.lisp.
There was a soundness bug that allowed attachments to prove nil in a
consistent logical [world] involving [defaxiom] [events]. This has
been fixed, by requiring that no function symbol ancestral in a
[defaxiom] formula is allowed to get an attachment. See
[defattach], in particular discussion of ``a restriction based on a
notion of a function symbol syntactically supporting an event'',
which concludes with a proof of nil that is no longer possible.
(ACL2(h) only) We fixed a soundness bug in the interaction of
memoization with congruent stobjs, in cases where the :congruent-to
field of [defstobj] was not the canonical representative in the
congruence class. For an example illustrating this bug, see the
comment about ``memoize/congruent stobj bug'' in the form (deflabel
note-6-1 ...) in ACL2 source file ld.lisp.
Functions defined by [defstobj] had failed to be compiled when
certifying books, except in host Lisps that compile on-the-fly
(CCL, SBCL). This has been fixed for all host Lisps. A related
change, probably less significant, was made for [defabsstobj].
Thanks to Sol Swords for reporting bugs that turned out to be
mistakes in a preliminary implementation of this change.
Fixed an assertion error involving linear arithmetic. Thanks to Sol
Swords for sending an example illustrating the bug (now appearing
as a comment in ACL2 source function linearize1).
Fixed a bug that was breaking the ACL2s build mechanism (see
[ACL2-sedan]) by causing certain needless evaluation of ``hidden
[defpkg]'' forms in [certificate] files when executing a call of
[include-book]. The bug could also affect rare error messages
arising from ill-formed [certificate] files. Thanks to Harsh Raju
Chamarthi for bringing this bug to our attention by sending us an
example script of the sort that was breaking during an ACL2s build.
Fixed handling of pathnames by some low-level code (system function
our-truename) that could cause errors, for example for host-Lisp
GCL on some platforms when environment variable HOME points to a
non-existent directory. Thanks to Camm Maguire for bringing this
issue to our attention and helping with the debugging.
Fixed a coding bug in generation of stobj resizing functions for a
stobj named OLD. The following example illustrates the bug.
(defstobj old
(fld :type (array (unsigned-byte 31) (8))
:initially 0 :resizable t))
(resize-fld 10 old)
; The following returned 8 but should have returned 10:
(fld-length old)
Fixed a bug in [defabsstobj-missing-events] (which macroexpanded
incorrectly). Thanks to Sol Swords for bringing this bug to our
attention.
Fixed two bugs in the handling of step-limits. Thanks to Hanbing Liu
for bringing the main such bug to our attention, which was that
ACL2 could report a step-limit violation during [certify-book] (in
fact, during any compound event such as a call of [encapsulate] or
[progn]), even without direct user involvement in managing
step-limits (see [set-prover-step-limit] and see
[with-prover-step-limit]). The other bug was that a bad argument to
[set-prover-step-limit] could result in a raw Lisp error, for
example: (progn (set-prover-step-limit '(a b))).
CHANGES AT THE SYSTEM LEVEL
The books/ directory no longer needs to exist in order to build an
ACL2 executable. Thanks to Robert Krug for pointing out that the
installation instructions had suggested that this was already the
case.
Many changes have been made to the [community-books]. For example,
some community books now include std/lists/rev.lisp, which contains
the rule revappend-removal, which may cause some proofs involving
[revappend] to fail where they formerly succeeded, or vice-versa.
When a proof fails that formerly succeeded, it may be useful for
you to look over the [rune]s printed in the event summary.
EMACS SUPPORT
EXPERIMENTAL/ALTERNATE VERSIONS
For ACL2(p), [wormhole-eval] is now locked by default; thanks to
David Rager for suggesting this change. But there is a way to avoid
the lock; see [wormhole-eval]. In particular, the lock is avoided
in the implementations of [accumulated-persistence] and
[forward-chaining-reports], which are not supported in ACL2(p) (see
[unsupported-waterfall-parallelism-features]).")
(NOTE-6-2
(RELEASE-NOTES)
"ACL2 Version 6.2 (June, 2013) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 6.1 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, changes at the system level,
Emacs support, and experimental versions. Each change is described
in just one category, though of course many changes could be placed
in more than one category.
CHANGES TO EXISTING FEATURES
The macro [top-level] has been changed, so that evaluation of a form
(top-level x) results in an error when evaluation of x results in
an error. Thanks to Jared Davis for observing that when evaluating
a file using [ld], an interrupt of a call of a [top-level] call in
that file would not prevent evaluation of later forms in the file.
The macro [the] no longer causes an error when [guard]-checking is
:NONE. For example, it had been the case that evaluation of (the
integer t) always caused an error; but now, there is no error after
executing command :[set-guard-checking] :NONE. Thanks to Jared
Davis for asking for a way to avoid such errors.
The error printed when attempting to ``reincarnate'' a package ---
that is, to define a package that is not part of the ACL2 logical
[world] but exists in raw Lisp because it was once part of the
world --- is now much more instructive. In particular, it shows
pathnames for the previous and proposed [defpkg] events, and it
shows the symbols that are imported by one but not the other.
Thanks to Jared Davis for requesting this improvement.
Functions [open-input-channel] and [open-output-channel] no longer
cause an error when failing to open a channel because of a
permissions problem, but instead return (mv nil state). Thanks to
Jared Davis for requesting this change. (Note: this change does not
apply if the host Lisp is non-ANSI, i.e., if the host Lisp is
non-ANSI GCL.)
The advanced [meta-extract] mechanisms, provided for using facts from
the [world] or metafunction context, have been enhanced in the
following ways, in collaboration with Sol Swords. See
[meta-extract] for more details.
It is now permissible to use calls of meta-extract-global-fact in
hypotheses of [clause-processor] rules, much as they are used
in hypotheses of [meta] rules. See [meta-extract]. Thanks to
Sol Swords for requesting this feature.
The utility meta-extract-global-fact is now a macro, which expands to
a corresponding call of the new function,
meta-extract-global-fact+. This new function takes an
alternate, extra [state] as an argument; it is not to be
executed, and it operates on the alternate state, whose logical
[world] is intended to be the same as that of the ``live''
(usual) state.
A new sort of value for the obj argument is supported for
meta-extract-global-fact (and meta-extract-global-fact+), which
results in a term equating a function application to its
result. See [meta-extract], in particular the discussion of
:fncall.
It is now possible for trace$ to avoid printing prefixes of the form
\"n> \" and \"<n \", while also (optionally) avoiding indentation. See
[trace$], in particular the discussion of :fmt!. Thanks to Shilpi
Goel for requesting this feature.
It was possible for the [guard-debug] feature to generate duplicate
calls of extra-info in hypotheses generated for guard verification.
We have eliminated duplicates of this sort.
When [in-theory] returns without error, it returns a value
(:NUMBER-OF-ENABLED-RUNES k), where k is the length of the new
current theory. (Formerly, k was returned.) This value is thus
printed when an in-theory event is submitted at the top level.
Thanks to Gisela Rossi for feedback that led us to make this
change.
A new keyword parameter for [ld] is :ld-missing-input-ok. Its default
value is nil, which causes an error, as before, upon failure to
open a specified file. Other legal values are t and :WARN; see
[ld-missing-input-ok] and see [ld].
Extended *acl2-exports*, in particular adding UNSIGNED-BYTE-P and
SIGNED-BYTE-P (thanks to a suggestion by Jared Davis)
Even if the function f is defined to take one or more [stobj]
arguments, the form (ec-call (f ...)) is now legal if all arguments
of the call of f are non-stobj objects, in any context where only
ordinary object return values are expected.
When the second argument of [certify-book] is a symbol, that symbol
formerly needed to be ? or t, in the \"ACL2\" package. Now, the
[symbol-package-name] of the second argument is ignored: any symbol
whose [symbol-name] is \"?\" or \"T\" is treated the same in that
argument position as the symbol ? or t in the \"ACL2\" package,
respectively. Thanks to Warren Hunt and Nathan Wetzler for
suggesting consideration of a more relaxed criterion for that
second argument.
(For system hackers, not standard ACL2 users:) Utilities
[initialize-event-user] and [finalize-event-user] now each take a
list of three arguments, (ctx body state). Thanks to Harsh Raju
Chamarthi for requesting this change.
NEW FEATURES
It is now permissible to specify a [stobj] field that is itself
either a stobj or an array of stobjs. A new primitive, [stobj-let],
is provided in order to access or update such fields; see
[stobj-let]. Thanks to Warren Hunt and Sol Swords for requesting
the ability to specify nested stobjs.
New accessor function (mfc-world mfc) returns the world component of
a metafunction context. See [extended-metafunctions].
A new [xargs] keyword, :SPLIT-TYPES, can be used to ``split'' the
[type] declarations from the [guard] in the following sense. By
default, or when :SPLIT-TYPES has value nil, one gets the existing
behavior: the terms corresponding to type declarations are
conjoined into the guard. However, if :SPLIT-TYPES t is specified,
then that is not the case; instead, guard verification will require
that these terms are proved under the hypothesis that the guard
holds. In this way, one can add type declarations to assist the
host Lisp compiler without cluttering the function's guard. See
[xargs]. Thanks to Jared Davis for requesting this feature.
Advanced users may want to see
[quick-and-dirty-subsumption-replacement-step] for a way to turn
off a prover heuristic. Thanks to those who have mentioned to us
potential issues with this heuristic, most recently Dave Greve.
HEURISTIC IMPROVEMENTS
We made changes to the ``ancestors check'' heuristic (source function
ancestors-check-builtin), as follows.
The heuristic could prevent a [rewrite] rule's hypothesis from being
rewritten to true, even when that hypothesis is of the form
(force <term>). Now, forcing will take place as expected; see
[force]. Thanks to Robert Krug for bringing this issue to our
attention and sending an example, which we include as a comment
in the ACL2 source code (see (deflabel note-6-2 ...)).
The heuristic is now delayed until after we check whether the
hypothesis is already known, using [type-set] reasoning alone
(in particular, not using rewriting), to be true or to be
false. We believe that this is now the ``right'' order for
those two operations. We saw a slight speed up in the
regression tests (about a percent) with this change, but that
might be in the noise.
A technical change makes the heuristic slightly less aggressive in
preventing backchaining. Roughly speaking, ordering checks
based on function symbol counts could suffice to permit
backchaining, where now variable counts also suffice. Thanks to
Robert Krug for showing us an example where backchaining led to
a term with no free variables that was nevertheless subject to
the ancestors check, preventing it from being rewritten.
(For those who use [defattach] to attach to ancestors-check) We have
used defrec to introduce an `ancestor' data structure. A new
function, strip-ancestor-literals, should be used to obtain the
literals from a list of ancestors, although strip-cars will
still work at this time.
When we rewrite the current literal of the current clause we assume
the falsity of the other literals and of the conclusions produced
by forward chaining. We have changed the order in which those
assumptions are made, which affects the type-alist used during
rewriting. This has three effects: the new type-alist, which is
sometimes stronger than the old one, may allow additional rules to
fire, the choice of free vars may be different, and the order of
the literals in forced subgoals may be different. Should ``legacy''
proofs fail under the new type-alist, we recommend looking for
rules that are fired in the new proof that were not fired (on that
same subgoal) in the old one. Thanks to Dave Greve for sending us
an example that led us to make this change.
BUG FIXES
We fixed a soundness bug that could be exploited by calling system
functions acl2-magic-mfc or acl2-magic-canonical-pathname. Thanks
to Sol Swords for bringing this bug to our attention.
We fixed a soundness bug in the handling of [stobj]s, in which
strings were recognized as stobjs in raw Lisp. Thanks to Jared
Davis for sending us a proof of nil that exploited this bug. We now
have a much simpler example of this bug, as follows.
(defstobj st fld)
(defthm bad (stp \"abc\") :rule-classes nil)
(defthm contradiction
nil
:hints ((\"Goal\" :in-theory (disable (stp)) :use bad))
:rule-classes nil)
We fixed bugs in extended metafunctions (see
[extended-metafunctions]). The macro mfc-ap no longer takes a
:TTREEP keyword argument, because this argument could allow
returning a tag tree that does not properly account for forcing.
The remaining mfc-xx macros --- mfc-relieve-hyp, mfc-rw+, mfc-rw,
and mfc-ts --- still take a :TTREEP keyword argument, but the
corresponding functions when :TTREEP is t ---
mfc-relieve-hyp-ttree, mfc-rw+-ttree, mfc-rw-ttree, and
mfc-ts-ttree --- were introduced with incorrect output signatures.
A complication is that mfc-relieve-hyp-ttree was improperly defined
in raw Lisp in a way that actually matched the incorrect signature!
All of these bugs have been fixed. Perhaps any of them could have
made it possible to prove nil, though we have not tried to do so.
(Windows only) On Windows, it had been possible for ACL2 not to
consider two pathnames to name the same file when the only
difference is the case of the drive, e.g., `C:' vs. `c:'. This has
been fixed. Thanks to Sol Swords for reporting this issue.
Fixed a bug in the storing of rules for the tau system; see
[tau-system]. (The error message mentions
PARTITION-SIGNATURE-HYPS-INTO-TAU-ALIST-AND-OTHERS.) Thanks to Sol
Swords for reporting this bug and sending a simple example to
illustrate it.
It had been possible to admit the missing [defthm] events printed by
[defabsstobj], and yet get an error when subsequently submitting
the same defabsstobj event, stating: ``Note discrepancy with
existing formula''. The problem could occur when an expression of
the form (or X Y) occurred in one of those missing events, because
ACL2 created it from the term (if X 't Y) but then translated (or X
Y) to (if X X Y), resulting in a mismatch. This has been fixed.
Thanks to Jared Davis for reporting this bug using a simple
example.
A hard Lisp error was possible for certain illegal functional
substitutions (see [lemma-instance]). Thanks to Sol Swords for
reporting this bug.
We fixed a bug in the case that an exported function of a
[defabsstobj] event had a [guard] of t. Thanks to Jared Davis for
sending a simple example when reporting this bug.
We now avoid an infinite loop that could occur when attempting to
close the standard character output channel (see [standard-co]).
Instead, an error message explains how to accomplish what was
probably intended. Thanks to Shilpi Goel for bringing this issue to
our attention.
(Windows only) Fixed a bug that was causing a hard error on Windows
when ACL2 encountered filenames starting with the tilde character
(~), for example, (ld \"~/acl2-customization.lsp\"). Thanks to Sol
Swords for bringing this bug to our attention. Also thanks to Harsh
Raju Chamarthi for a useful conversation that led to a better fix
than our first one.
CHANGES AT THE SYSTEM LEVEL
ACL2 may now be built on recent versions of a new host Lisp, ANSI Gnu
Common Lisp (GCL). Traditional (non-ANSI) GCL was the original host
Lisp underlying ACL2, and we are grateful for GCL support that we
received from the late Bill Schelter and, more recently and
particularly for ANSI GCL, from Camm Maguire.
The `make' process suggested for book certification has changed
substantially, thanks in large part to contributions from Jared
Davis and Sol Swords. We have seen the new process provide better
performance on machines with many cores, and we expect maintenance
advantages such as eliminating the need for Makefiles in individual
book directories. The ``classic'' process, which was based on
community books file books/Makefile-generic, is still supported
(see [books-certification-classic]) but may disappear in a future
release of ACL2. See [books-certification]. Most changes should be
invisible to the user, other than improved `make'-level
parallelism, with the exception of the following.
o Variable ACL2_JOBS is no longer supported, nor is it necessary;
simply use `make' option `-j' instead.
o Regressions now use `make' option -k by default, which causes the
regression to keep going after errors, rather than -i, which
ignores errors. If you encounter problems because of this
change, use ACL2_IGNORE=-i with your `make' command.
o The `regression' target works for the experimental extension,
ACL2(h) (see [hons-and-memoization]); target `regression-hons'
no longer exists.
Please let us know if you run into problems with the new
infrastructure, as we consider the legacy infrastructure to be
deprecated and we will probably eliminate much of it in the future.
In particular, circular dependencies were formerly prohibited at
the directory level, but that is no longer the case, and we expect
such cycles to occur in the future.
Although ACL2 users don't typically modify raw Lisp variables, we
have arranged to reset Lisp variable *default-pathname-defaults* if
necessary at startup so that it will not interfere with ACL2, in
particular by messing up the initial connected book directory (see
[cbd]). Thanks to Jared Davis, Sol Swords, and Raymond Toy for
helping us to identify this issue.
EMACS SUPPORT
EXPERIMENTAL/ALTERNATE VERSIONS
In ACL2(h), [print-object$] no longer uses the serialize printer
except in system applications as before (e.g., write out .cert
files). Thanks to Dave Greve for bringing this issue to our
attention.
Jared Davis contributed changes related to the [memoize] utility of
ACL2(h), including some low-level changes as well as the following.
o [Never-memoize] specifies that a given function should never be
memoized.
o Removed memoize-let, which may never have ever been used.
o Removed the :inline keyword option to memoize, which was just an
alias for the :recursive option.
For ACL2(p), some anomalous behavior may no longer occur because
prover calls (more specifically, trips through the ACL2
``waterfall'') will return only after all sub-computations
(threads) have finished. Thanks to David Rager for contributing
this improvement.
ACL2(pr), which includes [parallelism] (as for ACL2(p)) and
non-standard analysis support for the [real]s (as for ACL2(r)), now
builds and can certify the community nonstd/ books. Thanks to David
Rager for his contribution to this capability.")
(NOTE-6-3
(RELEASE-NOTES)
"ACL2 Version 6.3 (October, 2013) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes since Version 6.2 into the
following categories of changes: existing features, new features,
heuristic improvements, bug fixes, changes at the system level,
Emacs support, and experimental versions. Each change is described
in just one category, though of course many changes could be placed
in more than one category.
CHANGES TO EXISTING FEATURES
The evaluation of a term from a [bind-free] hypothesis had been
expected to produce an alist binding free variables to terms. While
that is still legal, it is also legal for that evaluation to
produce a list of such alists: then each is considered, until one
of them permits all remaining hypotheses to be relieved. See
[bind-free]. Thanks to Sol Swords for requesting this enhancement.
ACL2 continues to provide a way to specify keyword command
abbreviations for the top-level loop; see [ld-keyword-aliases].
However, [ld-keyword-aliases] is now a [table] rather than a
[state] global; it is thus no longer a so-called [ld] special. The
functionality of set-ld-keyword-aliases has essentially been
preserved, except that it is now an event (see [events]), hence it
may appear in a book; it is [local] to a book (or [encapsulate]
event); and the [state] argument is optional, and deprecated. A
non-local version (set-ld-keyword-aliases!) has been added, along
with corresponding utilities add-keyword-alias and
add-keyword-alias! for adding a single keyword alias. See
[ld-keyword-aliases]. Thanks to Jared Davis for correspondence that
led us to make this change.
The [proof-checker] command (exit t) now exits without a query (but
still prints an event to show the :INSTRUCTIONS). Thanks to Warren
Hunt for feedback leading us to make this change.
We made the following minor changes to the behavior of dmr; see
[dmr]. First, if dmr monitoring is enabled, then (dmr-start) will
have no effect other than to print a corresponding observation, and
if monitoring is disabled, then (dmr-stop) will have no effect
other than to print a corresponding observation. Second, it had
been the case that when (dmr-start) is invoked, the debugger was
always automatically enabled with value t (see
[set-debugger-enable]), and the debugger remained enabled when
(dmr-stop) was invoked. Now, the debugger is only enabled by
(dmr-start) if it is not already enabled and does not have setting
:never. Moreover, if such automatic enabling takes place, then the
old setting for the debugger is restored by (dmr-stop) unless
[set-debugger-enable] has first been called after that automatic
enabling. Finally, if the value of [state] global variable
'debugger-enable is :bt, then the new value will be :break-bt, not
t.
When a call of [progn] is executed in the ACL2 loop, its constituent
[events] and their results are printed, just as was already done
for calls of [encapsulate]. Thanks to Jared Davis for a
conversation causing us to consider this change.
(CCL only) When [set-debugger-enable] is invoked with an argument
that prints a backtrace and CCL is the host Lisp, the backtrace
will be limited to 10,000 stack frames. (We have seen more than
65,000 stack frames before this change.) This limit is the value of
raw Lisp variable *ccl-print-call-history-count*, which may be
assigned another positive integer value to serve as the maximum
number of stack frames to be printed.
Improvements have been made pertaining to the disabling (inhibiting)
of individual types of warning. Now, inhibited warnings are
implemented in a straightforward way using a separate [table] for
this purpose, the inhibit-warnings-table, rather than using the
[ACL2-defaults-table]. See [set-inhibit-warnings], and see
[set-inhibit-warnings!] for a variant that is not [local] to an
[encapsulate] or a book in which it occurs. Thanks to Sol Swords
for sending examples showing how [set-inhibit-warnings] did not
always behave as one might reasonably expect when books are
involved.
It had been the case that [lp] took a single argument, 'raw. This
argument was not documented and also caused an error, so it has
been eliminated.
The functionality of [make-event] has been significantly expanded.
First: if the expansion is of the form (:OR e1 e2 ...), then event
forms e1, e2, and so on are evaluated, in order, until the
evaluation of some ek completes without error. In that case, the
expansion is treated simply as ek. With this capability,
alternative expansions can be attempted and the successful one does
not need to be evaluated again. See the new version of community
book books/make-event/proof-by-arith.lisp for an example. Second,
an expansion may be of the form (:DO-PROOFS e), in which case the
event e is evaluated with proofs not skipped; see
[ld-skip-proofsp]. Third, new keyword :EXPANSION? can be used to
avoid storing expansions in certificate files. See [make-event].
When a [defun] event prints a failure message in the summary, that
message now indicates when the failure is due to a failed proof of
guard verification or a failed proof of the measure theorem. Thanks
to Shilpi Goel for requesting this enhancement.
NEW FEATURES
ACL2 can now be instructed to time activities using real time (wall
clock time) instead of run time (typically, cpu time). See
[get-internal-time]. Thanks to Jared Davis for asking to be able to
obtain real-time reports in event summaries.
A new utility, [sys-call+], is similar to existing utility [sys-call]
in that it executes a command. Unlike sys-call, however, sys-call+
returns values that include output from the command (in addition to
the exit status), rather than simply printing the command. See
[sys-call+].
The new macro [verify-guards+] extends the functionality of
[verify-guards] by permitting macro-aliases (see
[macro-aliases-table]). See [verify-guards+]. Thanks to Jared Davis
for requesting this feature and suggesting the use of [make-event]
in its implementation. We have also modified [verify-guards] to
print a friendlier error message when its argument is a
macro-alias.
See [last-prover-steps] for a new utility that returns the number of
prover steps most recently taken.
HEURISTIC IMPROVEMENTS
The processing of :use and :by [hints] has been changed in the
following two rather subtle ways, thanks to suggestions from Sol
Swords.
o For :by hints, the simplest check was an equality check, rather
than a more general subsumption check. That equality check was
made after removing so-called ``guard holders''
([must-be-equal], [prog2$], [ec-call], [the]) from both the
previous theorem and the purported theorem. Now, guard-holder
removal has been strengthened, so that the results are also put
into so-called quote-normal form, for example replacing (cons
'3 '4) by '(3 . 4).
o For a [lemma-instance] provided to a :use or :by hint that is a
:functional-instance, if a :do-not hint (see [hints]) has
specified that preprocess-clause is not to be used, then
preprocessing will not be used on the constraints.
We eliminated certain warnings about being ``weak'' for every
:[type-prescription] rule whose conclusion designates that the
function call can be equal to one of its arguments, e.g., (or
(integerp (foo y)) (equal (foo y) y)). In many cases (such as the
one above), such warnings about ``weak'' simply aren't correct.
BUG FIXES
Fixed a soundness bug that was permitting a [stobj] to be bound by a
[let] or [mv-let] form, without being among the outputs of that
form. Thanks to Jen Davis and Dave Greve for reporting this bug.
Their report included an example which forms the basis for a proof
of nil, included as a comment in the form (deflabel note-6-3 ...)
in ACL2 source file ld.lisp.
(GCL only) Fixed an obscure soundness bug due to an error in the GCL
implementation of [set-debugger-enable]. For details, see the
relevant comment in the ACL2 source code under (deflabel note-6-3
...).
Fixed a bug in the case of a field of a (concrete) stobj that is an
abstract stobj (see [nested-stobjs]). Thanks to David Rager for
bringing this bug to our attention.
Splitter output for type if-intro (see [splitter]) could formerly
occur even when at most one subgoal is generated. This has been
fixed.
Fixed a bug in [wof], hence in [psof] (which uses wof), that was
causing the printing of a bogus error message.
A small logical bug has been fixed in the logical definition of
[sys-call-status]. Formerly it always returned (mv nil state)
whenever the oracle of the state is non-empty (see [state]).
Fixed a bug that was causing an error upon evaluation of the form
(set-prover-step-limit nil). Thanks to David Russinoff for
reporting this error.
The :measure (if supplied) is now ignored when checking redundancy
with respect to a non-recursive definition that is not defined
within a [mutual-recursion]. (See [redundant-events] and see
[xargs].) It had been possible to get a low-level ACL2 error in
this situation. Thanks to Jared Davis for reporting this bug with a
helpful example.
Eliminated a potential error when using [comp] to compile an
uncompiled function defined under [progn!], which we observed in
LispWorks.
CHANGES AT THE SYSTEM LEVEL
The ACL2 sources are now publicly available between ACL2 releases,
using svn; see the new ``acl2-devel'' project hosted by Google code
at {http://acl2-devel.googlecode.com |
http://acl2-devel.googlecode.com}. Although such a copy of ACL2 is
likely to work well with the latest svn (trunk) revision of the
ACL2 community books (see [community-books]), please take seriously
the warning message printed at startup: ``The authors of ACL2
consider svn distributions to be experimental; they may be
incomplete, fragile, and unable to pass our own regression.'' That
message also provides instructions for bug reports. If you decide
to use svn versions of either the community books or ACL2, then you
should use both, as they tend to be kept in sync. We fully expect
ACL2 releases to continue from time to time, as usual. Thanks to
Jared Davis for his efforts in setting up the new acl2-devel
project and svn repository, and to him and David Rager for
convincing us to distribute ACL2 sources via svn between releases.
Thanks to a suggestion from Jared Davis, over 30 built-in functions
are now declared to be inline in order to boost performance. (The
list may be found by searching ACL2 source file axioms.lisp for
``(declaim (inline''.)
Better support has been provided for command line arguments,
especially those supplied directly by the user when calling ACL2.
For one, problems with quoting have been solved using \"$@\" in place
of $*. Also, the function [save-exec] now allows specification of
arguments, both for the host Lisp as well as ``inert'' arguments
that can be passed along to calls of programs (as with [sys-call]).
A keyword argument, :return-from-lp, specifies a form to evaluate
before quitting the read-eval-print loop at startup. See
[save-exec]. Also see the source function user-args-string and its
comments, source file acl2-init.lisp, for more information. Thanks
to Jared Davis for suggesting the use of \"$@\", as well as
modifications to [save-exec] and helpful conversations about that.
A rather extensive overhaul has taken place for the function
proclaiming mechanism. As before, this is only used when the host
Lisp is GCL. However, building an executable is now faster for some
Lisps, including GCL, by avoiding repeated recompilation and
perhaps repeated initialization.
(CCL only) We increased stack sizes when the host Lisp is CCL. The
default for recent CCL versions is equivalent to specifying `-Z 2M'
on the command line, but saved ACL2 scripts (including experimental
versions ACL2(h), ACL2(p), ACL2(r), and combinations of them) to
`-Z 64M', representing a 32-fold increase. Thanks to Jared Davis
for pointing us to community books file
books/centaur/ccl-config.lsp and to Sol Swords for helpful
discussions.
(SBCL only) Fixed save-exec for host Lisp SBCL to provide the same
export of variable SBCL_HOME that was provided in the original
saved_acl2 script.
(GCL only) We made changes, following suggestions from Camm Maguire
(whom we thank for these suggestions), to support ACL2 builds on
recent versions of GCL (2.6.8 and 2.6.10; we recommend against
using GCL 2.6.9, since issues there were fixed in 2.6.10).
Specifically, we no longer set the hole size, and we allocate
contiguous pages sufficient to run an ACL2 regression without
failing due to memory limitations.
EMACS SUPPORT
Modified file emacs/emacs-acl2.el to eliminate some warnings that
were appearing in a recent Emacs version, replacing (end-of-buffer)
by (goto-char (point-max)) and next-line by forward-line. Thanks to
Warren Hunt for bringing the warnings to our attention.
EXPERIMENTAL/ALTERNATE VERSIONS
(Allegro CL only) ACL2(h) now avoids blow-ups in hash table sizes
that could be caused by [fast-alist-fork]. Thanks to Jared Davis
for helping to debug this problem, and to David Rager for
contributing the community book
books/parsers/earley/earley-parser.lisp, which highlighted this
problem.
(SBCL only) Fixed a bug that was causing a Lisp break after turning
on [waterfall-parallelism]. Thanks to David Rager for confirming
that our proposed fix is correct.")
(NOTE-6-4
(RELEASE-NOTES)
"ACL2 Version 6.4 (January, 2014) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes to ACL2 since Version 6.3 into
the following categories of changes: existing features, new
features, heuristic improvements, bug fixes, changes at the system
level, Emacs support, and experimental versions. Each change is
described in just one category, though of course many changes could
be placed in more than one category.
See also [note-6-4-books] for a summary of changes made to the ACL2
Community Books since ACL2 6.3, including the build system.
Changes to Existing Features
[Gag-mode] no longer saves prover output when PROVE output is
inhibited (see [set-inhibit-output-lst]). This may improve
performance slightly when certifying community books using their
Makefile or [build::cert.pl]; in particular, GCL 2.6.8 running on a
Mac can now certify the book
books/tau/bounders/elementary-bounders.lisp without running out of
space, even without explicitly turning off [gag-mode] (which had
been done shortly before the Version 6.3 release).
When [include-book] fails to find a readable [certificate] (.cert)
file, the error message now distinguishes between the case that
this file is missing and the case that read permission is missing.
(GCL only) Time reporting has been improved when the host Lisp is Gnu
Common Lisp. A key change was made in the computation of runtime
(for example, to report in event summaries), so that it includes
the ``child runtime''. See [get-internal-time]. Also, the utility
[time$] now gives improved information by including child runtime
information, which can be significant; for example, it probably
includes compile time, while the ``seconds runtime'' statistic
(still) does not. Recent versions of GCL might also provide system
runtime and child system runtime. See [time$]. Thanks to Camm
Maguire for suggesting these improvements to time$ and providing an
initial implementation for them.
Fixed a bug in an ACL2 system function, our-truename, which returns
the ``true name'' for a file name, when supplied with an optional
second argument. Thanks to Camm Maguire for bringing this bug to
our attention.
The wording in theory warnings has been improved, to avoid giving the
impression that you are newly disabling a built-in rule in the case
that it merely remains disabled.
As requested by Sol Swords, erroneous evaluations of system function
magic-ev-fncall that had produced a message, msg, will now also
return that message. The following example, sent by Sol,
illustrates the fix: before, evaluation of (magic-ev-fncall 'cons
'(a) state nil nil) printed a message (to the comment window) and
then returned (mv t nil), but now it returns mv t <msg>, shere
<msg> denotes the message (printed with the [fmt] ~@ directive).
Fixed :[pbt] to avoid printing the bodies of [defconst] forms. Thanks
to Jared Davis for pointing out the large output when the body is a
large character string.
A new output type, history, now controls the printing of
history-related information; see [set-inhibit-output-lst]. The
unused output type, expansion, is no longer supported, i.e., is no
longer a member of the list *valid-output-names*. Because of this
change, printing of information when undoing, as by :[u], will now
take place even when event output is inhibited (if history output
is not inhibited); we thank Sol Swords for requesting that change.
The :[loop-stopper] field of a rule of class :[rewrite], should still
be a list of lists (var1 var2 fn1 fn2 ... fnk), where var1 and var2
are variables and the fni are symbols. But formerly each fni was
required to be a function symbol; now, it can be a macro alias for
a function symbol (see [add-macro-alias]). For example, the
following is a valid :[loop-stopper] field: ((x y +)).
The restrictions on utilities [oracle-apply] and [oracle-funcall]
have been updated in order to avoid potentially confusing or
inappropriate results, by imposing the following new requirements
on their first argument, which must still be a function symbol.
That symbol must not be if (formerly the illegal symbol was
[return-last]); it must not be a key of the alist,
*ttag-fns-and-macros*; it must not be untouchable (see
[remove-untouchable]); and it must not be a [stobj] creator (see
[defstobj]).
The [table] guard on [dive-into-macros-table] has been strengthened
in order to avoid calling untouchable functions (see
[remove-untouchable]).
New Features
We have added a tool for writing out useful information about a
book's event names when certifying the book. See [bookdata]. Thanks
to Dave Greve for requesting this tool and participating in its
specification.
There are new analogues of [add-include-book-dir] and
[delete-include-book-dir]: [add-include-book-dir!] and
[delete-include-book-dir!], respectively. The new utilities are
similar to their existing counterparts, except that their effects
are not [local] to enclosing [books] or [encapsulate] events.
Thanks to Shilpi Goel for requesting this enhancement.
The class of [congruence] rules has been broadened considerably, so
that one can restrict to patterns. For example, a congruence rule
can now state that an equivalence is maintained for the term
(mv-nth 1 (f (cons u v) y 'a)) when rewriting y. See
[patterned-congruence]. Thanks to Sol Swords for requesting this
feature.
Heuristic Improvements
(None to report this time.)
Bug Fixes
Fixed a soundness bug in the handling of hypotheses of conditional
:[definition] rules invoked during rewriting by applying :[expand]
[hints]. See (defxdoc note-6-4 ...) in community book
system/doc/acl2-doc.lisp for a proof of nil in ACL2 Version_6.3
that exploits this bug.
It had been possible to update a [stobj] (either an ordinary stobj or
an abstract stobjs) so that it no longer satisfies its recognizer
predicate. This soundness bug has been fixed. Thanks to Jared Davis
and Sol Swords for pointing out this bug, making useful
observations about the issue, and sending proofs of nil, one of
which may be found in a Lisp comment in the defxdoc form for
note-6-4.
Fixed a long-standing soundness bug (found at least as far back as
Version 1.9!) in the checking done for [congruence] rules. There
had failed to be a check that the new variable on the right-hand
side of the conclusion is indeed new. The following example is
shown in detail as a comment in function
interpret-term-as-congruence-rule, ACL2 source file defthm.lisp,
where it is used to prove nil in Version 6.3.
(implies (e y1 y2)
(equal (h y2 y1)
(h y2 y2)))
Fixed a bug in the ACL2 character reader that was causing an
end-of-file error when reading from a string ending in \"#\\c\", for c
a character or non-terminating sequence of characters. Thanks to
Jared Davis for sending the following example, whose evaluation in
raw Lisp had caused an error.
(let* ((*readtable* *acl2-readtable*)
(stream (make-string-input-stream \"#\\\\a\"))
(x1 (read stream nil :EOF))
(x2 (read stream nil :EOF)))
(list x1 x2))
(GCL only) Improved the automatic proclaiming mechanism used for GCL
builds, in particular to avoid computing a return type when a term
is detected that could come from a call of [non-exec], and to do a
more complete job for calls of [return-last].
(CCL only) A CCL bug was treating filenames of the form \"~/user/...\"
as \"~/...\". Thanks to Gary Byers for sending us a CCL-specific form
that is now included in the ACL2 sources, which avoids this
problem.
Attempts to submit [congruence] rules had unfortunate consequences in
the case that the function ``symbol'' is [if] or [quote]: for if,
rules were appropriately ignored because of the special handling
that ACL2 already gives to calls of [if] for congruence-based
reasoning, while for quote, it was possible to get a hard Lisp
error. Now, attempts to submit such rules will result in a clear
ACL2 error.
It had been possible to get a confusing raw Lisp error when
submitting a [defstobj] event whose first argument is not a symbol,
as in: (defstobj (fld :type integer :initially 0)). That user error
is now reported gracefully by ACL2.
When an [include-book] form is executed for a non-existent book, we
no longer get a bogus warning about a missing compiled file. (Of
course the compiled file is missing when the book itself is
missing! So there's no need to report this fact.) Thanks to Caleb
Eggensperger for bringing this issue to our attention.
Changes at the System Level
The ACL2 system [documentation] has been reworked for the [xdoc]
framework developed by Jared Davis. While the ACL2 User's Manual
can still be built, it is now possible for the ACL2 community to
contribute to the ACL2 system documentation, in community book
books/system/doc/acl2-doc.lisp; see comments near the top of that
book. Now that both the ACL2 system documentation and much of the
community books documentation are written in [xdoc] format, we hope
the ACL2 community will add links from the ACL2 system
documentation topics to book documentation topics. Note that :[doc]
still works at the terminal, but it is based on the new system, and
other terminal-based access to the documentation has been
eliminated (for example :more). Thanks to Jared for all his work
contributing to this enhancement.
Fixed community books books/Makefile-generic and also books/Makefile,
which now has filename books/GNUmakefile, to work with Cygwin
(Windows). Thanks to Harsh Raju Chamarthi for his substantial help.
The guard for system function ev-fncall-w now includes an arity
check.
EMACS Support
There is now an Emacs utility for browsing the hypertext
documentation for ACL2 and the community books. This browser,
ACL2-Doc, essentially serves as a replacement for Emacs Info, which
can no longer be used to browse the documentation. ACL2-Doc can be
used not just for the ACL2 User's Manual but also for the
ACL2+Books Manual. It is loaded automatically into Emacs if you
load the file emacs/emacs-acl2.el. See [ACL2-doc] and
[documentation].
Experimental/Alternate Versions
(None to report this time.)")
(NOTE-6-5
(RELEASE-NOTES)
"ACL2 Version 6.5 (August, 2014) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes to ACL2 since Version 6.4 into
the following categories of changes: existing features, new
features, heuristic improvements, bug fixes, changes at the system
level, Emacs support, and experimental versions. Each change is
described in just one category, though of course many changes could
be placed in more than one category.
See also [note-6-5-books] for a summary of changes made to the ACL2
Community Books since ACL2 6.4, including the build system.
Changes to Existing Features
The [brr@] command now supports inputs :initial-ttree and
:final-ttree. Thanks to David Rager for a request leading to these
enhancements. See [ttree] for a discussion of the tag-tree
structures returned for these inputs.
(GCL only) A restriction for structure-sharing (as described in a
remark, ``Remark on print-circle-files''; see [print-control])
involving GCL has been removed, since this is no longer required
for the latest GCL versions (2.6.8 and 2.6.10). Thanks to Jared
Davis and Camm Maguire for useful discussions and this GCL
improvement.
The keyword commands :exit and :quit are disabled inside [brr], in
order to avoid accidental exits from ACL2. Thanks to David Rager
for suggesting such a change.
For calls of [make-event] made during the [include-book] phase of
[certify-book], keyword :check-expansion no longer causes
evaluation of the first argument of make-event; rather, the value
of :check-expansion is simply used as the expansion. Thanks to Sol
Swords for suggesting this change, which made it reasonable to
ignore such make-event forms when determining the ``rolling back''
before that include-book phase, as described in the next section.
The form (reset-prehistory nil) now is a no-op if [state] global
'skip-reset-prehistory has a non-nil value. Thanks to Sol Swords
for requesting this feature (in support of infrastructure for
certifying the [community-books]).
The output from :[pr], :[pr!], :[pl], and :[show-bodies] has been
tweaked. Thanks to a suggestion from Ben Selfridge, such output now
shows the hypotheses (the Hyps field) above the left-hand side and
right-hand side of a [rewrite] rule (Lhs and Rhs, respectively).
The Equiv field has also been moved up before the Lhs field in such
output for rewrite rules, and this field has been added for [elim]
rules. Finally, the Hyps field now appears above the Term field in
such output for [type-prescription] rules.
Rules of class :[linear] may now be [monitor]ed. Thanks to David
Rager for requesting this enhancement.
When forcing (see [force]) is applied, we now always see the
appropriate [executable-counterpart] [rune],
(:executable-counterpart force), in the proof output and summary;
this hadn't previously been the case. Thanks to Robert Krug for
bringing this issue to our attention.
The default value for the :write-port keyword argument of
[certify-book] is now t, as was already claimed by the
documentation. Thus, a .port file will be written when a book is
certified, making it more likely that a subsequent [include-book]
will complete without error even if the book has been modified
without recertification. Note that a change by Sol Swords to the
build system for the [community-books] now sets an environment
variable to guarantee that write-port is true, independent of this
change. On a related note: the unadvertised environment variable
ACL2_WRITE_PORT is now handled more appropriately, by interning its
upcased argument into the ACL2 package.
The following changes can make it easier to include books that are
uncertified or have corrupted compiled files. Thanks to Sol Swords
for sending helpful, relevant examples and for subsequent
discussions helping to lead to these changes.
* It is no longer illegal to call set-compiler-enabled within [books].
See [compilation], which shows how to do this in order to avoid
loading the compiled file not only for a book specified by
[include-book] but also for all books included under that book.
Also see [compilation] for an analogous utility,
(set-port-file-enabled nil state), to avoid loading .port
files. (For background on .port files, see
[uncertified-books]).
* In situations where it is legal to include an uncertified book
(typically, any time other than during [certify-book], ACL2
nonetheless could fail to do so when an error occurred while
reading a [certificate] file. ACL2 can now instead include the
book successfully as an uncertified book.
* When hard raw Lisp errors occur during loading of compiled files on
behalf of an [include-book] event, that event can now complete
successfully much as though the compiled file were simply
missing.
(SBCL only) The function [setenv$] is now supported in SBCL, which
had been the one supported host Lisp for which setenv$ had not been
supported. Thanks to Jared Davis for pointing the way to this
improvement.
Built-in [equality-variants] have been modified in order to support
suitable guard-checking. For example, evaluation of the form
(member-eq 3 '(4 5)), or equivalently, (member 3 '(4 5) :test 'eq),
had produced a value of nil, but now we get what one should have
expected: a guard violation (since [member-eq] is intended to
compare symbols). Thanks to Yan Peng for raising a question on the
acl2-help mailing list that led us to make this improvement.
When the :[pe] command is supplied the macro alias for a function
symbol (see [macro-aliases-table]), the system will now print
[events] not only for the macro symbol but also for the
corresponding function symbol. Thanks to Cuong Chau, Jared Davis,
Shilpi Goel, Sol Swords, and Warren Hunt for requesting this
enhancement.
Some evaluations of forms (mbe :logic L :exec E) are more efficient
or avoid guard violations, by evaluation of the :exec form (E)
instead of the :logic form (L). If the [mbe] call is in a
:[program] mode function definition, the :exec code will be
evaluated, where unlike before, this is true even when
guard-checking is :all or :none (see [set-guard-checking]). If the
mbe call is in a :[logic] mode function definition, the change is
that the :exec code will be evaluated when there is a superior call
of a :program mode function, except when guard-checking is :all or
:none or in a couple of technical cases (see a comment in the
source code for constant **1*-as-raw* [formerly *mbe-as-exec*] for
details). This use of :exec code had been defeated when the
superior :program mode function had an ``invariant-risk'' of making
ill-guarded stobj updates. However, there is no change in the case
of safe-mode, which is used during evaluation of [defconst],
[value-triple], and [defpkg] forms, and during macroexpansion: the
:logic and :exec forms are still both evaluated and checked for
equality. Thanks to Jared Davis for reporting this issue and for
helpful chats about it. For more information, see the comment about
``mbe and invariant-risk'' in the form (defxdoc note-6-5 ...) in
[community-books] file books/system/doc/acl2-doc.lisp.
The utility [save-exec] has a new (optional) keyword argument,
:init-forms, which specifies a list of forms to evaluate when first
entering the ACL2 read-eval-print loop, [lp]. Thanks to Jared Davis
for requesting this enhancement.
New Features
A [defstobj] event may now include the keyword argument
:non-memoizable. When its value if t, then for ACL2(h) builds (see
[hons-and-memoization]), code will run somewhat faster. In a little
test doing just reads and writes to a stobj array in ACL2(h), it
took 26% less time when the stobj to be written was introduced by
[defstobj] using :non-memoizable t. Thanks to Warren Hunt for
requesting this feature and helping to develop the test.
See [set-print-base-radix] for a utility that may be preferable to
[set-print-base], since it essentially calls [set-print-radix]
automatically. Thanks to David Rager, Shilpi Goel, and David Hardin
for participating in an acl2-help mailing list discussion that
motivated this feature.
Heuristic Improvements
One of the steps performed by [certify-book] has traditionally been
to check for local incompatibilities (see [local-incompatibility])
after admitting all the events in the book. This step involved
rolling back the logical [world] to what it was at the start of
certification, and then including the book (see [include-book]). As
an optimization, we now avoid rolling back the world more than
necessary; see [certify-book], specifically the discussion of Step
3. We thank Sol Swords for requesting this optimization and for
making a suggestion that improved it, pertaining to [make-event]
(described above). We also thank Jared Davis for alerting us to an
issue that turned out to be caused by a bug in our initial
implementation. Sol has reported a nearly 20% reduction in time for
certifying a certain large collection of books.
The test for redundancy of [encapsulate] [events] has been made more
efficient. Also, while the criterion itself remains unchanged, the
documentation has been made more accurate; see
[redundant-encapsulate]. We observed more than a 2% reduction in
time for the ``everything'' regression target, but we observed more
than 23% of the time eliminated for the form (time$ (include-book
\"doc/top\" :dir :system)) after building the documentation. Thanks
to David Rager for bringing that particular book to our attention,
as one that took a long time to include.
The function [pairlis$] is now tail-recursive, hence potentially more
efficient. More precisely, its definition for the logic remains
unchanged, but using [mbe], for execution it calls a new
tail-recursive function, pairlis$-tailrec. Thanks to Jared Davis
for requesting this improvement.
[Linear] arithmetic has been strengthened slightly so that
immediately after simplification has ``settled down'' (see
[hints-and-the-waterfall]), the unrewritten conclusion of a
:[linear] rule may be used when normally this would not be the
case. Thanks to Robert Krug for reminding us of examples we had
encountered that could benefit from some such a change, and for
pointing us to some relevant source code. This improvement
generally causes an extra pass through the simplifier; hence we
have observed approximately a 2% slowdown in the regression suite.
Note that machinery is now in place for installing additional
``desperation heuristics''; perhaps the ACL2 community will have
some to suggest.
Bug Fixes
We fixed a soundness bug in how the [tau-system] processed calls of
if. Thanks to Dmitry Nadezhin for reporting this bug by sending a
simple example that exploited it to prove nil. To see that example,
see the comment about ``tau soundess bug'' in the form (defxdoc
note-6-5 ...) in [community-books] file
books/system/doc/acl2-doc.lisp.
We fixed a soundness bug for nested [stobj]s (see [stobj-let]). In
the case of a stobj producer variable that is not a child stobj, it
had been possible to update that stobj without returning it. Thanks
to Sol Swords for reporting this bug and providing a corresponding
proof of nil, which is included in a comment in the form (defxdoc
note-6-5 ...) in [community-books] file
books/system/doc/acl2-doc.lisp.)
We fixed a soundness bug in the case of a [stobj] with a field that
is a resizable array of stobjs. Thanks to Sol Swords for sending a
proof of nil exploiting this bug, together with some helpful
analysis attributing the bug to a mistake in the generated logical
definition of the corresponding resize function. (His example is
included in a comment in the form (defxdoc note-6-5 ...) in
[community-books] file books/system/doc/acl2-doc.lisp.)
(ACL2(h) only) We fixed a soundness bug involving the interaction of
[stobj-let] and [memoize], which thus is only a bug in ACL2(h) (see
[hons-and-memoization]), not in ACL2. The fix was to add code to
stobj-let that clears the memoization table for the parent stobj if
any child stobj is updated. An example proof of nil before this fix
may be found in the ACL2 source file translate.lisp, in a comment
in the function stobj-let-fn-raw.
(Allegro CL and CMUCL only) We fixed bugs in function [princ$] when
invoked in an ACL2 image with Allegro CL or CMUCL as the host Lisp
implementation. In Allegro CL, when printing a complex number in
base 16, lower case characters were produced, for example printing
#C(c d) instead of the characters predicted by the axioms, namely
#C(C D). In some recent versions of CMUCL, after executing the
forms (set-print-base 16 state) and (set-print-case :downcase
state), hex digits were printed in lower case, unlike other host
Lisps and contrary to the ACL2 axioms: for example, 1000 base 10
was printed as 3e8 rather than as predicted by the ACL2 axioms,
3E8. Thanks to Jared Davis for bringing these bugs to our
attention, and also for pointing out excessive printing of a big
note about such printing in Allegro CL. We now avoid that note
altogether, which had warned that printing numbers in base 16 can
be slow for Allegro CL. In fact, that performance issue has been
eliminated: for example, after evaluating (defconst *c* (expt 2
200000)) and (set-print-base 16 state), the form (time$ (pprogn
(princ$ *c* *standard-co* state) state)) reports taking about 3
seconds before the change but about 1/100 seconds after the change.
Thanks to David Margolies of Franz Inc. for passing along a remark
from a colleague that showed how to make this improvement.
The utility [sys-call+] can now only be called if there is an active
[trust-tag], which is the restriction that was already in place for
[sys-call]. This plugs a potential soundness hole.
We have made several system functions untouchable (see
[remove-untouchable]), in order to prevent soundness bugs. We thank
Jared Davis and Sol Swords for sending us an example that used a
call of one of these functions to prove nil. We have placed that
example into a comment in Community Books file
system/doc/acl2-doc.lisp, form (defxdoc note-6-5 ...).
The brr command, :wonp, had not been installed for use after :eval
even though this was claimed in the documentation (see
[brr-commands]). This has been fixed. Thanks to David Rager for
bringing this issue to our attention.
Fixed a bug in [make-event] that could cause [include-book] to fail
with a bogus message about ``the set of ttags permitted in the
current context.'' Thanks to Sol Swords and Anna Slobodova for
reporting this bug, and to Sol for sending a small example that
illustrated the problem.
Fixed a bug that was wrongly disallowing certain calls of exported
functions for abstract stobjs (see [defabsstobj]). Thanks to Sol
Swords for reporting this bug, supplying an example illustrating
the bug, and suggesting a nice fix. A slight variant of his example
is included in a comment in Community Books file
system/doc/acl2-doc.lisp, form (defxdoc note-6-5 ...).
When a macro symbol mac was a macro-alias for a function symbol f
(see [macro-aliases-table]), then the form (verify-guards+ mac)
caused an error when encountered while including an uncertified
book. This problem has been fixed. Thanks to Jared Davis for
pointing out the problem and sending a simple example to illustrate
it. Technical Note: the actual problem was that [verify-guards+]
generates a call of [make-event] with an :expansion? argument, and
that argument needed to be ignored (as it now is, after the fix)
when including an uncertified book.
The [walkabout] utility could cause hard Lisp errors when the current
package is other than \"ACL2\". This has been fixed. Thanks to Sol
Swords for bringing this bug to our attention and suggesting a fix.
Changes at the System Level
(SBCL only) Fixed the executable script generated for SBCL so that
SBCL_HOME is set to the SBCL obj/sbcl-home/ directory if it exists,
since that fix seems needed for some recent versions of SBCL
(1.1.14 in particular).
File GNUmakefile in the ACL2 sources directory wasn't passing the
value of shell variable ACL2 from target certify-books-fresh to
target certify-books, and similarly for target
books/system/doc/render-doc.cert (invoked by target DOC). This has
been fixed. We thank Jared Davis and Camm Maguire for helpful
discussions.
The \"make DOC\" command was not completing correctly when variable
ACL2 was not set. Also, for host Lisp CMUCL at least, it stalled at
the terminal unless a quit command was issued twice (as ACL2 was
stuck without exiting). Those problems have been resolved. Thanks
to Jim Ward for bringing these issues to our attention
Improved the error message when encountering an illegal comma while
reading input (i.e., for a comma not within a suitable nesting of
backquotes). Thanks to Jared Davis for bringing this issue to our
attention and for a helpful discussion.
(GCL only) Arranged for state global 'tmp-dir to be set to GCL's
si::*tmp-dir*, even on Windows; this may be important for
compilation on Windows. Thanks to Camm Maguire for pointing out the
need to set 'tmp-dir for ACL2 built on GCL on mingw.
(GCL only) Now, [gc$] may be called with no arguments, in which case
the missing argument for system::gc is t.
EMACS Support
Improvements to the [ACL2-Doc] browser include the following.
* A new `w' command displays the topic name in the minibuffer, together
with the manual name (ACL2+Books Manual or ACL2 User's Manual).
* Improved the `control-t .' command so that the default topic is
selected just as in acl2-doc mode. (Technically: the same
syntax table is used for `control-t .' as is used in the
acl2-doc buffer for that command and the `g' command.)
* Improved the search commands so that the display doesn't move when
the next occurrence is already displayed on the screen.
* Eliminated the deprecated commands `Control-x a A', `Control-x a a',
and `Control-t G'.
Experimental/Alternate Versions
For ACL2(r), Ruben Gamboa found a bug in constraints for functions
introduced with defun-std, and also kindly provided a fix, which
has been incorporated.
Modified ACL2(hp) so that two system functions that had been
[unmemoize]d when turning on [waterfall-parallelism] ---
fchecksum-obj and expansion-alist-pkg-names-memoize --- now remain
memoized. This can greatly improve performance when using ACL2(hp)
with [waterfall-parallelism] on, in particular community book
books/system/doc/render-doc-combined.lisp.
Made miscellaneous small improvements to ACL2(h).
The utilities hons-shrink-alist and hons-shrink-alist! have
essentially been renamed to [fast-alist-fork] and
[fast-alist-fork!], respectively. The old names are deprecated but
remain as macros that are macro-aliases for the respective new
names (see [macro-aliases-table]). New utilities,
[fast-alist-clean] and [fast-alist-clean!] are similar to the above
but take just one argument and, if it is a fast alist, associates
the result with the hash table link of that argument. Thanks to
Jared Davis for providing a concrete proposal, together with the
new names, for what had been only a concept.")
(NOTE-7-0
(RELEASE-NOTES)
"ACL2 Version 7.0 (January, 2015) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes to ACL2 since Version 6.5 into
the following categories of changes: existing features, new
features, efficiency improvements, bug fixes, changes at the system
level, Emacs support, and experimental versions. Each change is
described in just one category, though of course many changes could
be placed in more than one category.
A particularly major change with this release is that by default,
ACL2 executables are [hons-enabled]: see [hons-and-memoization]. We
expect this change to be backward compatible for current ACL2
users, other than a change to the name of the executable, as
described below.
* As before, there are two ways to build ACL2: either [hons-enabled],
to produce ACL2(h) with executable name saved_acl2h; or not
hons-enabled, to produce ``classic ACL2'', which we now call
ACL2(c), with executable name saved_acl2. [Note: These defaults
were changed after Version_7.0.]
* Unlike before, the default build of ACL2 is now ACL2(h), hence with
name saved_acl2h [after Version_7.0, once again saved_acl2]. It
is still possible to build ACL2(c) (hence with name saved_acl2)
[after Version_7.0, saved_acl2c], but this is not the default.
* The change to building ACL2(h) by default may require you to change
scripts and environment variables to point to saved_acl2h
rather than saved_acl2. [This change is only for Version_7.0,
not later versions.]
Note that after the next ACL2 release, we might only support
[hons-enabled] ACL2 builds.
See also [note-7-0-books] for a summary of changes made to the ACL2
Community Books since ACL2 6.5, including the build system.
Changes to Existing Features
Three new theorems have been built into ACL2 to allow some additional
simple arithmetic reasoning. For example, the following failed
before this change, typically causing the user to include an
arithmetic book; but that is no longer necessary.
(thm (implies (natp x)
(equal (expt 2 (+ 1 -1 x))
(expt 2 x))))
Thanks to Jared Davis for suggesting these, and for providing seven
small modifications to the community books to keep proofs from
failing after the changes. (So, if you have a proof failure
involving `plus' (+) that formerly succeeded, consider disabling
one or more of these rules.) Here are the three new built-in
theorems.
Theorem: <commutativity-2-of-+>
(defthm commutativity-2-of-+
(equal (+ x (+ y z)) (+ y (+ x z))))
Theorem: <fold-consts-in-+>
(defthm fold-consts-in-+
(implies (and (syntaxp (quotep x))
(syntaxp (quotep y)))
(equal (+ x (+ y z)) (+ (+ x y) z))))
Theorem: <distributivity-of-minus-over-+>
(defthm distributivity-of-minus-over-+
(equal (- (+ x y)) (+ (- x) (- y))))
[Type-set] reasoning has been improved for a few built-in functions,
including first-n-ac, [substitute], [nthcdr], and [subseq], and
thus for some functions whose computed type depends on one of
these: for example, [take] and therefore, also [butlast] and
[subseq-list], are now known to return [true-listp] results. Thanks
to Jared Davis for a request that led us to these changes. In
particular, the definitions of first-n-ac and substitute-ac have
been modified to call [revappend] instead of [reverse], and the
following :[type-prescription] rules have been added to source file
axioms.lisp (and can be seen using :[pe]).
* true-listp-first-n-ac-type-prescription
* stringp-substitute-type-prescription
* true-listp-substitute-type-prescription
* true-listp-nthcdr-type-prescription
* stringp-subseq-type-prescription
* true-listp-subseq-type-prescription
Technical note on the above change: in some cases, the built-in
:[type-prescription] rule has been changed, essentially for the
better, but new rules have also been added. Consider for example
the function, [substitute]. This function calls substitute-ac,
which in turn now calls [revappend] instead of [reverse], which
allows ACL2 to deduce a :type-prescription rule saying that
substitute returns a string or a true-list. However, new
:type-prescription rules stringp-substitute-type-prescription and
true-listp-substitute-type-prescription allow the stronger
conclusion that substitute returns a string or true-list,
respectively depending on whether [type-set] reasoning can deduce
that the given sequence is or is not a string. The deduced
:type-prescription rule can still be of some use in cases that
type-set reasoning cannot establish whether or not the input
sequence is a string.
We removed support for processing legacy [documentation] strings
(those starting with \":Doc-Section\"), since the [xdoc] system has
been stable for some time. Thanks to Jared Davis for assisting in
that effort and to David Rager for his encouragement. The ACL2
system and [community-books] still have code to support such
processing, but it is essentially commented out: specifically, each
such piece of code is prefixed by #+acl2-legacy-doc. We expect to
delete such code entirely before the next release.
The [with-output] macro now takes a new keyword, :evisc, that
specifies [evisc-tuple]s. Thanks to Warren Hunt for requesting a
way to submit [defun] forms in a way that avoids printing large
[guard] goals during guard verification. The following example
illustrates a way to arrange this.
(defmacro defun/ (&rest args)
(mv-let (evisc args)
(cond ((eq (car args) :evisc)
(mv (cadr args) (cddr args)))
(t (mv '(:gag-mode (evisc-tuple 3 4 nil nil)) args)))
`(with-output :evisc ,evisc
(defun ,@args))))
; example:
(defun/ h (x)
(declare (xargs :guard t))
(append (cons (make-list 10) x) x))
The utility :[pl2] no longer automatically instantiates free
variables; similarly for calls of :[pl] on a term. Thanks to Eric
Smith for sending an example showing the problem with the previous
implementation.
When the [ld-evisc-tuple] is non-nil, the utilities :[pe], :[pc], and
:[pcb!] now abbreviate their output accordingly. See
[set-evisc-tuple]. Thanks to David Rager for bringing the need for
this change to our attention.
The utility [disabledp] now accepts runic abbreviations such as (:d
append). (See [theories] for a discussion of runic abbreviations.)
Thanks to Shilpi Goel for requesting this enhancement.
Gc-verbose now takes an optional second argument, which is only
relevant when the host Lisp is CCL, where that argument specifies
verbosity for EGC.
Nests of [car] and [cdr] calls are now printed (``untranslated'')
differently. The old method availed itself of all 28 of the car-cdr
macros. The new method only introduces 6 of them: cadr, caddr,
cadddr, cddr, cdddr, cddddr. It never introduces such macros as
caar or cddaar, preferring cars and cdrs when necessary. Lisp
programmers tend to recognize cadr, caddr, and cadddr as the
accessors for the 1st, 2nd, and 3rd (0-based) elements of a list.
See community book books/system/untranslate-car-cdr.lisp for
further discussion and a correctness proof.
It is now possible to create more efficient :[meta] rules by writing
metafunctions that create ``implicit hypotheses.'' See
[meta-implicit-hypothesis].
We improved a few built in rules: lower-case-p-char-downcase,
upper-case-p-char-upcase, lower-case-p-forward-to-alpha-char-p, and
upper-case-p-forward-to-alpha-char-p. We also improved the rule
alpha-char-p-forward-to-characterp by replacing it with two rules,
alpha-char-p-forward-to-standard-char-p and
standard-char-p-forward-to-characterp. The new rules are, as
before, in ACL2 source file axioms.lisp.
The reader macro sharp-comma (#,), which has been deprecated since
ACL2 Version 3.5 (May, 2009), has been eliminated. Use sharp-dot
(#.) instead; see [sharp-dot-reader].
A [defthm] or [defaxiom] event is now redundant when there is already
a syntactically identical event in the logical [world], even if the
rules suggested by the two [events] differ. See [redundant-events].
Thanks to Jared Davis and Sol Swords for sending the following
example, which illustrates the change. Previously, the final event
was not redundant, and hence failed. Now, it is redundant, even
though the :typed-term suggested by the new [type-prescription]
rule is (booleanp (foop x)) where the existing rule's :typed-term
is (foop x).
(defund foop (x) (consp x))
(defthm booleanp-of-foop
(booleanp (foop x))
:rule-classes :type-prescription)
(in-theory (disable booleanp-compound-recognizer))
(defthm booleanp-of-foop
(booleanp (foop x))
:rule-classes :type-prescription)
In the case that summary output is inhibited but error output is not
(see [set-inhibited-summary-types]), failed [events] did not print
an error message. Now they do.
When a call of [encapsulate] with empty [signature] introduces no
[events], it now has no effect on the ACL2 logical [world].
Formerly, such an [encapsulate] form would create an event even in
this case. For example, the form (encapsulate nil (local (defun f
(x) x))) formerly created an event in the world, as well as a
[command] when executed at the top-level; but now it is truly a
no-op. See [encapsulate]. Note: An idiom sometimes used for testing
is (encapsulate () (local ...) (local ...) ...), that is, a trivial
encapsulate where each sub-event is [local]. With this change, that
idiom is now properly supported. (Formerly, the second such
encapsulate was considered redundant with the first; but that is no
longer the case, since the first will not be stored in the
[world].)
We replaced an error with a warning for cases where a classic
[congruence] rule is unnecessary. Thanks to Jared Davis for sending
us an example suggesting the need for a change. (See ACL2 source
function chk-acceptable-congruence-rule for his example and more
explanation.)
We removed support for three [declare] forms that had been permitted
in ACL2(h) only, but were not advertised: dynamic-extent, inline
and notinline, because they seem difficult or impossible to support
correctly. For alternatives to using inline and notinline
declarations, see [defun-inline] and [defun-notinline].
The nu-rewriter contained special provisions for rewriting
expressions composed of [nth], [update-nth], and
[update-nth-array], together with [let] expressions and other
applications of non-recursive functions or [lambda] expressions. An
email query was sent to the acl2 mailing list on 10/24/2014, giving
people an opportunity to object to the removal of this feature.
Nobody objected, so we have removed it in order to simplify the
ACL2 code base. Thanks to David Rager for suggesting this sort of
code clean-up. Note that some system functions, for example
all-equal, have been deleted in support of this change.
[Guard]s have been added for some system functions that support the
implementation of the [tau-system]: lower-bound-<=, upper-bound->=,
lower-bound->, upper-bound-<, and squeeze-k. Thanks to Dmitry
Nadezhin for supplying these improvements (which he also used in
modifications to the community book,
books/tau/bounders/elementary-bounders.lisp).
New Features
The new command :btm has been added to the list of valid
[brr-commands], to show the bottom-most frame in the path. Thanks
to David Rager for requesting this feature.
A new [xargs] keyword, :[measure-debug], decorates each termination
proof goal with [extra-info] calls that show the source of the
goal. Thanks to Jared Davis (first in 2008!), Sol Swords, and Anna
Slobodova for requesting this feature.
A new reader macro, #{\"\"\"...\"\"\"}, has been contributed by Jared Davis
to support the writing of strings without escape characters. See
his community book books/system/fancy-string-reader-test.lisp for
examples.
(For those who program in raw Lisp) A new Lisp variable,
*hard-error-is-error*, has a default of nil that preserves existing
behavior; but it can be set to a non-nil value in order to cause
so-called ACL2 ``hard errors'' to result in Lisp errors whose
condition, when printed with format directive ~a, is the same error
message that ACL2 would otherwise print. See [hard-error]. Thanks
to Jared Davis for requesting this feature.
A new value for [include-book] keyword argument :uncertified-okp is
:ignore-certs, which specifies that all certificate files are to be
ignored during inclusion of this book and all of its sub-books. See
[include-book]. Thanks to Sol Swords for requesting this feature
and for helpful discussions on its details.
Efficiency Improvements
The heuristics have changed for guessing the :typed-term field for a
:[type-prescription] rule when that field is not explicitly
specified. Specifically, consider the case that the conclusion of
the rule is a function call (p u) for some term u, such that there
is an enabled [compound-recognizer] rule for p. Formerly, the
:typed-term was u in this case. Now, it must be the case that the
most recent enabled such [compound-recognizer] rule is `strong', in
the following sense: if ts1 is the [type-set] implied by assuming
the conclusion true and if ts2 is the [type-set] implied by
assuming the conclusion false, then ts1 and ts2 are complementary.
Thanks to Jared Davis for an email that prompted us to make this
change.
We have made several efficiency improvements (arguably heuristic in
nature), which may apply in many settings but especially in
handling of several forms during the execution of [include-book]
--- most notably with-output forms, as (with-output ... FORM) is
now essentially just FORM during include-book. For some details,
including statistics showing up to 1/3 of [include-book] time
eliminated by these changes (and even significant time saved
outside include-book), see the comment about ``efficiency
improvements'' in Community Books file system/doc/acl2-doc.lisp,
form (defxdoc note-7-0 ...). Thanks to Sol Swords for noticing
inefficiencies that led us to these improvements, and for helpful
discussions.
The [dmr] utility has been made much more efficient, yielding a
performance penalty of perhaps 10% instead of perhaps more than a
factor of 30 (3000%).
We made a low-level implementation tweak that resulted in a speed-up
of 2.6% in wall-clock time for a CCL-based regression (using
``make'' with -j 8 and target ``everything''). (Technical note: We
eliminated the Lisp special variable *attached-fn-called*, using
another variable *aokp* instead. Special variable bindings can
apparently be expensive!)
Some space has been saved in ACL2 executables by avoiding the
duplication of certain constants. Specifically: for each event
(defconst name (quote val)) in the ACL2 source files, val is stored
in the Lisp image in several places, but not all of these had been
identical: they were all [equal], but not all [eq]. (We believe
that these were already all eq for user-defined [defconst] events.)
For example, in Linux builds of ACL2(h) on host Lisp CCL, we have
seen a space saving of approximately 18.9 MB, which is 12.6%.
Thanks to Jared Davis for pointing out duplicate strings that he
noticed using his [spacewalk] tool.
Bug Fixes
We fixed two bugs in [spec-mv-let]. The first was pointed out to us
by Jared Davis using essentially the following example, where the
result should be nil given that spec-mv-let is intended to have the
semantics of [mv?-let].
ACL2 !>(set-ignore-ok t)
T
ACL2 !>(let ((a t)
(xval nil))
(spec-mv-let (yval)
xval
(mv?-let (xval)
a
(if xval
yval
nil))))
T
ACL2 !>
The second [spec-mv-let] bug was to allow the two lists of bound
variables to intersect. In the following example, given that
spec-mv-let is semantically just mv?-let, the result should have
been 46, not 34. This has been fixed. Thanks to David Rager for
encouraging these two fixes and checking them over.
ACL2 !>(set-ignore-ok t)
T
ACL2 !>(spec-mv-let
(x)
17
(mv?-let (x)
23
(if t
(+ x x)
\"bad\")))
34
ACL2 !>
The guard for function [alpha-char-p] was strengthened to require
that its argument is a standard character. The previous guard
required only that the argument is a character, and was a soundness
bug; for a proof of nil before this fix, see the comment about
``alpha-char-p'' in Community Books file system/doc/acl2-doc.lisp,
form (defxdoc note-7-0 ...).
Errors were possible when evaluating functions [pkg-imports] and
[pkg-witness] while including a book with a compiled (or expansion)
file. Such errors have been eliminated.
Fixed a bug in [oracle-apply-raw].
(GCL CLtL1 only) Fixed a bug that was preventing
[set-debugger-enable] from taking full effect in non-ANSI GCL.
(GCL only) The utility [gc-verbose] was broken, but has been fixed.
Fixed a bug in [provisional-certification] that incorrectly caused an
error during the convert step for [verify-guards+] forms. More
generally, this error occurred when encountering a [make-event]
form with a non-nil value supplied for the :expansion? keyword.
Thanks to David Rager for reporting this bug.
A raw Lisp error could occur with [guard]-checking turned off,
because type declarations were mistakenly left in the executable
counterparts (so-called ``*1* functions'') when ACL2 processed
function definitions. The following example shows how a type
violation could occur in some Lisps (we saw this in SBCL but not in
CCL, for example).
(defun f (x)
(declare (xargs :guard (natp x)))
(let ((y (1+ x)))
(declare (type (integer 0 *) y))
y))
(set-guard-checking nil)
; Possible raw Lisp error:
; \"The value -2 is not of type UNSIGNED-BYTE.\"
(f -3)
Thanks to Jared Davis for sending us an example that brought this bug
to our attention.
Fixed a bug that was causing a low-level assertion, saying:
``Implementation error: see 'replace-free-rw-cache-entry.'' Thanks
to Anna Slobodova for bringing this bug to our attention via an
example, and to Sol Swords for simplifying that example.
The [iprint] feature, which allows abbreviated output to be read back
in, did not work as one might expect when using the [break-rewrite]
feature (see [brr]). Thanks to David Rager for reporting this
problem. More generally: the problem was that values associated
with [iprint] indices during a [wormhole], for example after
breaking on a [rewrite] rule, were forgotten when exiting the
wormhole. (Technical note for those interested: the fix restores
the main iprinting structure after exiting a wormhole, just before
reading the next top-level form. That restoration uses raw Lisp,
with logic-only code based on [read-ACL2-oracle].) The example
below failed before the fix but now works.
(set-evisc-tuple (evisc-tuple 3 3 nil nil)
:iprint t
:sites :all)
(defthm my-rule (equal (car (cons x x)) x))
(brr t)
(monitor '(:rewrite my-rule) t)
(thm (equal (car (cons a a)) a) :hints ((\"Goal\" :do-not '(preprocess))))
; Now entering a :brr break:
(make-list 10) ; printed without evisceration
; Set evisceration with iprinting:
(set-evisc-tuple (evisc-tuple 3 3 nil nil)
:iprint t
:sites :all)
(make-list 10) ; printed with evisceration
(a!) ; quit break-rewrite
; The following formerly caused a hard Lisp error, because although #@3#
; was printed in the output from (make-list 10) just above, iprint index 3
; was lost when exiting the break-rewrite wormhole. Now, this works
; because iprinting information from the wormhole is retained.
'#@3#
There was a bug in how so-called ``hidden packages'' were handled by
[encapsulate] forms (see [hidden-death-package]), which was
preventing package axioms from being visible in certain contexts.
(Technical remark: packages that were hidden after the second pass
but not the first were treated as not-hidden, even though their
package axioms were not introduced.) That, in turn, could cause an
[include-book] form to fail when the book contains a
[deftheory-static] form. Here is an example failure. First, in a
fresh ACL2 session evaluate the form (defpkg \"FOO\" nil) and then
evaluate the form (certify-book \"foo\" 1), where file foo.lisp is as
follows.
(in-package \"ACL2\")
(defun foo::foo (x) x)
(deftheory-static foo-theory
(current-theory :here))
Now evaluate the following sequence of forms. In previous versions of
ACL2, the final ([include-book]) form failed.
(encapsulate () (local (include-book \"foo\")) (defun h (x) x))
(encapsulate () (local (include-book \"foo\")) (defun h2 (x) x))
(include-book \"foo\") ; failed before the fix
We have cleaned up handling of interrupts and aborts when inside the
[break-rewrite] loop, or indeed any [wormhole]. Thanks to David
Russinoff for bringing to our attention a case in which ACL2 quit a
proof with ``Aborting due to an interrupt'' when in fact no
interrupts had taken place. Here is an example where that no longer
happens but did, previously. (For a different example, see the
comment in the ACL2 sources definition of macro
bind-acl2-time-limit.)
(defun foo (x) (cons x x))
(brr t)
(monitor '(:definition foo) t)
(thm (equal (foo y) z))
(defun h (x) (declare (xargs :mode :program)) (car x))
; Raw Lisp error:
(h 3)
; Previously, unexpected proof abort \"due to interrupt\":
(thm (equal (append (append x y) x y) (append x y x y)))
When aborting with :[a!] inside the [break-rewrite] loop from within
the [proof-checker], a raw Lisp error could subsequently occur
saying, ``Attempt to execute *wormhole-cleanup-form* twice!''. This
has been fixed. Thanks to Sol Swords for reporting a bug in our
original fix. Here is an example that formerly caused that
behavior.
(defthm silly (implies (null x) (equal (append x y) y)))
(defconst *c* (make-list 10))
:brr t
:monitor (:rewrite silly) t
(verify (equal (append x (append *c* y)) (append y (append *c* x))))
bash
:go
:a!
bash ; formerly caused error
The utility [redo-flat] no longer worked when interrupting a proof
(with Control-c), due to a bug in Version 7.0. This has been fixed.
Thanks to Dave Greve for reporting this problem.
Changes at the System Level
As mentioned near the top of this [documentation] topic, default
builds of ACL2 are now [hons-enabled].
(GCL only) GCL Versions prior to 2.6.12 are no longer supported.
Modified code used in distributing Debian releases that allows books
certified in one directory to be distributed in another. This
change, together with the fact that such relocation is not truly
supported, is explained in comments in source function
make-certificate-file-relocated. Thanks to Camm Maguire for
discussions leading to this change.
(GCL only) Modified how home directory is calculated. Thanks to Camm
Maguire for help in making this change.
(SBCL only) Fixed a check done at build time that was preventing
builds in SBCL 1.2.2 because of its new backquote implementation.
Thanks to Harsh Raju Chamarthi and Pete Manolios for bringing this
issue to our attention.
Development snapshots of ACL2 (and of the [community-books]) are now
available between releases from {an ACL2 github repository |
https://github.com/acl2/acl2}; they are no longer available via
svn. Thanks to David Rager and Jared Davis for taking the lead on
this conversion. As a result, the banner printed at startup for
those snapshots has changed slightly. For a quick start guide for
using git with ACL2, see [git-quick-start].
(CCL only) Control-d now quits ACL2 in raw Lisp just as it has done
for a long time in the loop and, for ACL2(h) (i.e., [hons-enabled]
ACL2), even in raw Lisp.
(Should essentially affect GCL only) Significant re-work has been
done for function proclaiming, which is still only done when the
host Lisp is GCL. In particular, the build process now has extra
steps even for other Lisps though for them, the extra steps are
trivial (technical details may be found in the comment labeled
``Essay on Proclaiming'' in source file acl2-fns.lisp). We now use
GCL's automatic proclaiming mechanism to calculate function types
during the build (boot-strap), as we have seen it perform better
than our own. Thanks to Camm Maguire for helpful discussions, in
particular for explaining that mechanism and for pointing out that
the re-proclaiming that had been done previously during the build
could lead to buggy behavior.
For Makefile targets for testing such as regression, the default ACL2
image used is now the same one that would be built for the same
Makefile variables. In particular, the command make regression is
equivalent to make regression ACL2_HONS=h, which uses the
executable saved_acl2h, not saved_acl2 as was formerly the case.
Thanks to Harsh Raju Chamarthi for finding a bug in a first attempt
to make this change.
EMACS Support
Hons-enabled and Experimental Versions
(For [hons-enabled] executables only) Fixed a soundness bug related
to function memoization. For a proof of nil exploiting this bug in
Version 6.5, see the comment about ``pons-addr-of-argument'' in
Community Books file system/doc/acl2-doc.lisp, form (defxdoc
note-7-0 ...). Thanks to Jared Davis for improving our original
fix: by noting its applicability to [hons-clear] (not just
[hons-wash]); by tweaking our fix so that it works even if a
control-c interrupts (hons-clear or) hons-wash; and later by
finding another bug in source function pons-addr-of-argument and
suggesting a fix, which we incorporated.
(For [hons-enabled] executables only) Fixed a soundness bug due to
the fact that function never-memoize-fn returned nil in the logic
but returned t in raw Lisp. For a proof of nil exploiting this bug
in Version 6.5, see the comment about ``never-memoize-fn'' in
Community Books file system/doc/acl2-doc.lisp, form (defxdoc
note-7-0 ...).
Static honsing for [hons-enabled] ACL2, an efficiency enhancement
formerly only available for CCL, is now incorporated into builds on
sufficiently recent GCL versions.
ACL2 executables that were [hons-enabled] could fail to use
previously-compiled definitions for [memoize]d functions when
[include-book] is invoked. This has been fixed.
(For [hons-enabled] executables only built on other than CCL or SBCL)
Calls of [memoize] only compile the memoized definition when the
original function is compiled, rather than unconditionally as
before.
Several changes been made to function memoization (see [memoize]).
Here is a list of changes visible at the user level; for
implementation details, see [note-7-0-memoize].
* It is now legal to call [memoize] on functions with special raw-Lisp
code (such as [len]) provided the value of the :inline keyword
argument is nil.
* Bug fix: Fixed bug that was making [memsum] attribute the count of
making of hash tables to ``Heap bytes allocated'' instead of to
``Number of calls to mht.''
* Memoize keyword :trace is no longer supported, as the [trace$]
utility provides much more flexibility.
* Bug fix: Fixed a bug in handling of the :commutative argument of
[memoize] that could cause a hard Lisp error. For a book that
exhibits this bug, see the comment about ``:commutative'' in
Community Books file system/doc/acl2-doc.lisp, in the form
(defxdoc note-7-0 ...).
* When [memoize] is called with keyword argument :commutative having
value t, the benefit of that argument can apply to rational
number arguments even when not using static honsing. Moreover,
now only one argument needs to be a rational or to be
``static'' according to the implementation (technically: to
have an hl-staticp value).
* Bug fix: Calls of [memoize] with keyword argument :commutative t were
sometimes inappropriately treated as redundant
[redundant-events]. This has been fixed. Here is a simple
example of what formerly went wrong.
(defn f (x y) (equal x y))
(memoize 'f :commutative t)
(unmemoize 'f)
(memoize 'f :commutative t) ; was redundant, so did not memoize
* (For those who memoized directly in raw Lisp) Memoize-fn now requires
its first argument to be a defined (fboundp) function symbol.
(It seemed odd and needlessly arcane to allow memoize-fn to
define an undefined function.)
* (For those who memoized directly in raw Lisp) Memoize-fn now causes
an error when it fails.
* Bug fix: It had been possible to lose a memoization setting of :aokp
t when many functions were memoized. For an example, see the
comment about ``rememoize-all'' in Community Books file
system/doc/acl2-doc.lisp, in the form (defxdoc note-7-0 ...).
* We eliminated undocumented utilities memoize-on and memoize-off,
which were not used as far as we know.
* When a memoized function call fails to satisfy the specified
condition, that call is no longer counted as a ``hit'', at
least by default. This can be changed with raw Lisp variable,
*condition-nil-as-hit*.
* The utility [memsum] had reported one more pons call and (CCL only)
one more byte than was correct, and could perhaps report one
call when there were actually zero. That has all been fixed.
* Bug fix: Some sorting of results based on ``self'' time and ``other
functions'' time had been wrong. (Technical remark: the problem
was that the implementation confused ``ticks'' with ``time''.)
This has been fixed.
* Statistics reporting (see [memsum]) often has a more uniform look. It
is now done with a right margin of 79 instead of 70. For
[memsum], thanks to a suggestion from Warren Hunt, the defun
formerly printed to start each entry is now omitted, and after
the name is printed at the start, a newline is printed before
the ``hits'' or ``hits/calls'' information is printed. A
related change: when *report-hits* and *report-calls* are both
nil, ``calls'' is no longer printed. Other cosmetic changes
were also made to [memsum] output.
* The output from [memsum] on the line ``Time of all outermost calls''
no longer includes a percentage, which had been at best
misleading and at worse nonsensical. Suppose for example that f
calls g, which does all the work. Then memsum had reported 50%
of the ``Time of all outermost calls'' for each of f and g,
even though 100% of the time was spent under each.
* On Mac OS (Darwin), the physical memory is now accurately computed
(using shell command ``sysctl hw.memsize'', which works in some
versions of Mac OS, maybe all recent ones; tested on 10.6 and
10.7). Before, the physical memmory value had been assumed to
be 2^32 bytes. The physical memory value is used in CCL for
triggering garbage collections. (Technical remark: this is
implemented in function start-sol-gc.)
* Bug fix: in the pons summary, misses had been reported instead of
hits on the ``hits/calls'' line.
* Fixed [memsum] so that package names are printed with the symbols.
Also, printing is done with respect to the current package, not
the \"ACL2\" package.
* It is now legal to [profile] functions that take [state] as an
argument. Thanks to Sol Swords for requesting this change. In
the course of making this change, we took a conservative
approach and put the same requirement regarding illegal
memoization of functions involving user-defined [stobj]s: that
is, when memoization must have value nil for the :condition
keyword, it must also have value nil for the :inline keyword.
We can perhaps remove this additional restriction if necessary.
* For every built-in memoized function defined in the ACL2 logic, the
memoization is done in the usual way (during the ACL2 build),
using the [memoize] event during the ACL2 build. Such functions
can thus be [unmemoize]d by users in the usual way. Thanks to
David Rager for requesting this enhancement.
* A new memoize keyword, :stats, can control whether statistics will be
saved for reporting with (memsum).
* Memoization in [hons-enabled] ACL2(p) is no longer affected by calls
of [set-waterfall-parallelism].
(ACL2(p) only, either [hons-enabled] or not) The function
[Cpu-core-count] is now sensitive to environment variable
ACL2_CORE_COUNT. See [cpu-core-count]. Thanks to Jared Davis for
requesting this enhancement.
Support for multi-threading has been added for memoization. Thanks to
Jared Davis for contributing an initial implementation. Note that
this may slow down [hons-enabled] ACL2(p) by several percent on
memoization-intensive applications. Undocumented function
mf-multiprocessing is available for low-level system hackers to
turn on/off this feature, which by default is off for
[hons-enabled] ACL2 and on for [hons-enabled] ACL2(p).
(ACL2(p) only, either [hons-enabled] or not) We fixed a bug in
[pand], which we believe was also a bug in [por], [pargs], and
[plet]. (Technical remark: this bug had a low-level cause,
pertaining to maintenance of a Lisp variable, *ld-level*, that
holds the number of nested calls of [ld].) Thanks to Jared Davis
for reporting this bug and to David Rager for assisting in its
repair. Below is a slightly simplified version of Jared's example,
which formerly caused an assertion error but now works as expected.
(defmacro pand* (x y)
`(spec-mv-let (yval)
,y
(mv?-let (xval)
,x
(if xval
yval
nil))))
(defn f3 (x)
(pand* x x))
(defn f4 (x)
(pand x
(f3 x)))
(value-triple (f4 5))
(Only for [hons-enabled] executables on Windows) Certain memory
management is avoided on Windows (technically: by avoiding a call
of source function start-sol-gc), where it was causing errors.
Thanks to Harsh Raju Chamarthi and Sol Swords for testing on
Windows that led us to this change.
Subtopics
[Note-7-0-memoize]
ACL2 Version 7.0 Notes on Changes to Memoization Implementation")
(NOTE-7-0-MEMOIZE
(NOTE-7-0)
"ACL2 Version 7.0 Notes on Changes to Memoization Implementation
See [memoize] for a user-level introduction to function memoization.
Here we summarize technical changes made in Version 7.0 of ACL2 to
the implementation of function memoization; most ACL2 users should
have no need to read further in this topic. We thank Jared Davis
for helpful conversations.
The function memoize-init now resets the table *memo-max-sizes*,
which is used when creating memo tables and pons tables. This
change may be irrelevant, since generally memoize-init is only
called at startup. But it seemed appropriate to reset it along with
all other globals involved in the memoization implementation.
Lisp variable *print-pretty* is no longer globally set to t by
certain memoization code. Probably this change will not generally
be observable.
The utility [clear-memoize-statistics] now resets data for the pons
summary, but implementation function clear-memo-tables no longer
does so (it only calls clear-memoize-tables).
Avoided some recklessness in computing statistics related to ponsing
(specifically, replaced very-unsafe-incf by macro safe-incf-pons,
which is a wrapper for safe-incf).
Clear-memo-tables no longer takes &rest arguments, since it is merely
a wrapper for [clear-memoize-tables], which does not (and did not)
take &rest arguments.
For the utility pons-summary, we no longer use our-syntax-nice; so
far example, *print-case* is not bound to :downcase.
Function internal-real-ticks (formerly internal-real-time) now uses
[logand] in its implementation, which should improve performance.
It also replaces, for non-static-hons implementations, the call
(get-internal-real-time) by (the mfixnum (get-internal-real-time)),
which can also help performance.
More principled, consistent use is made of our-syntax for suitable
printing.
Added ``TO DO'' comments near the top of source file
memoize-raw.lisp. Thanks to Jared Davis for suggesting some of
these.
We improved many comments in source file memoize-raw.lisp.
We did some renaming, including the following (note that this is
probably not a complete list):
- number-of-arguments -> mf-len-inputs
- number-of-return-values -> mf-len-outputs
- *compute-array* -> *callers-array*
- maybe-count-pons-calls -> incf-pons-calls
- maybe-count-pons-misses -> incf-pons-misses
- print-alist -> mf-print-alist
- shorten -> mf-shorten
- outside-p -> outside-caller-p
- ofni -> mf-make-symbol
- ofnum -> mf-num-to-string
- internal-real-time -> internal-real-ticks
- dcls -> mf-dcls
- hl-without-interrupts -> without-interrupts [which already existed]
- *ma-initial-max-symbol-to-fixnum* -> *initial-max-symbol-to-fixnum*
- REPLACEMENT:
*initial-max-memoize-fns* -> *initial-2max-memoize-fns*
We eliminated some dead code, including the following functions
(probably not a complete list): our-syntax-brief, ofnm, uses-state,
global-restore-memoize, prine-alist, set-gc-threshold, our-gctime,
and short-symbol-name, and all variants of format functions with
names starting with \"of\" except for ofni (now mf-make-symbol) and
ofnum (now mf-num-to-string). Also, we moved memoize-here-come to
community book books/centaur/memoize/old/profile-raw.lsp. Regarding
our-syntax-brief: there had been one call, in print-call-stack, but
that call did not seem appropriate so we deleted it.
The variable *count-pons-calls* was deleted. It had been set to t and
was only used during macroexpansion of incf-pons-calls and
incf-pons-misses (formerly maybe-count-pons-calls and
maybe-count-pons-misses), where that macroexpansion was done at
ACL2 build time --- hence user setting of *count-pons-calls* had no
effect.
We eliminated a needless error check that prevented loading
memoize-raw.lisp without #+hons, since we don't currently ever
expect to try to do that.
Miscellaneous additional code cleanup has been done. Here is a
(probably very incomplete) list.
* Float-ticks/second-init uses a default rather than duplicating the
default's code, and has improved treatment of errors.
* Removed unused :before field of memoize-info-ht-entry record.
* The implementations of number-of-arguments and
number-of-return-values (now called mf-len-inputs and
mf-len-outputs, respectively) have been made cleaner, in
particular, starting with an empty
*number-of-arguments-and-values-ht*.
* New macros such as ma-index provide some abstraction, to give the
illusion that *memoize-call-array* is two-dimensional.
* We broke up some defintions, in particular substantially shortening
memoize-fn by moving parts of it into new functions
memoize-fn-inner-body, memoize-fn-outer-body, and
memoize-fn-def. A benefit: it is easy to see the definition
that is actually created when memoizing, by tracing
memoize-fn-def.
* Added raw Lisp interface function mf-note-arity for informing
memoize-fn of input and output arities.
* Coerce-index asserts that an index is in range rather than treating
an out-of-range index as a symbol.
* We renamed some variables to make them clearer. In particular, it is
whether a variable stores time or ticks.
* We now make complete and correct (we hope) the use of suitable fixnum
and mfixnum declarations, many of which had been missing or
incorrect.
* Both [memoize] and [unmemoize] are now safe for control-c and
unexpected errors.
* We no longer set ccl::*save-definitions* or
ccl::*fasl-save-definitions* to t. This may improve
performance, but it may require explicitly calling
mf-note-arity, as is now done in books/centaur/aig/bddify.lisp.
However, this removes CCL-only behavior; in particular, we
removed dependence on #+Clozure in
books/centaur/aig/bddify.lisp for profiling count-branches-to.
* We use #+ccl instead of #+Clozure, for consistency with most of the
rest of ACL2.
* We no longer set ccl::*save-source-locations* or
ccl::*record-source-file* to t, as there is no clear advantage
to doing so, and in fact there is a comment near the end of
source file acl2.lisp suggesting that there could be slowdown
from setting (at least) the first of these variables to t.
* We slightly modified internal-real-time to improve its performance
(see comments there).
* We fixed a performance bug in function addr-for (parenthesis error
was needlessly putting us in the ``large-case'').
* Fixed a typo: declaim of fixnum type for *initial-max-memoize-fns*
had instead been for nonexistent variable
*initial-2max-memoize-fns*.
* In memoize-fn, we removed support for :condition to be a function
symbol, which was at best confused.
* The table *never-memoize-ht* is now populated mostly automatically,
by initialize-never-memoize-ht.
* Slight optimization: the form (update-attached-fn-called
,*attached-fn-temp*), which had been in the definition of
memoize-fn but now is in memoize-fn-inner-body, is conditioned
on ,*attached-fn-temp*.")
(NOTE-7-1
(RELEASE-NOTES)
"ACL2 Version 7.1 (May, 2015) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes to ACL2 since Version 7.0 into
the following categories of changes: existing features, new
features, heuristic and efficiency improvements, bug fixes, changes
at the system level, Emacs support, and experimental versions. Each
change is described in just one category, though of course many
changes could be placed in more than one category.
The default build is [hons-enabled], as for the previous release; but
the generated executable is now saved_acl2, as discussed below.
Please note that ACL2(c) (``classic ACL2'', i.e., ACL2 that is not
[hons-enabled]) now builds as saved_acl2c, is deprecated, and will
likely be unsupported or even eliminated in future releases.
See also [note-7-1-books] for a summary of changes made to the ACL2
Community Books since ACL2 7.0, including the build system.
Changes to Existing Features
For both [add-include-book-dir] and [add-include-book-dir!], the
second argument is no longer evaluated (which we think could
perhaps have been exploited to get unsound behavior, by arranging
for the value of the second argument to depend on [state]).
Moreover, that argument can not only be a string, but also can be a
sysfile: an object (:system . filename), where filename is a file
name. When filename is a relative pathname, the meaning of such an
object is the file with that pathname under the system books
directory.
The event summary had not been printed when a proof is interrupted
(that is, with Control-C). Now, summary information is printed for
two summary types (see for example [set-inhibited-summary-types]):
rules and hint-events.
By default, (memsum) is now truncated to 100 entries rather than to
20 entries. (Implementation note: raw Lisp variable
*memoize-summary-limit* is 100 instead of 20.)
Calls of THE no longer cause a [guard] violation when guard-checking
is nil. Also see [the] and see [set-guard-checking].
Type declarations for [let] and [mv-let] forms are now
[guard]-checked. Consider for example the definition: (defun foo ()
(let ((x t)) (declare (type integer x)) x)). Previously, evaluation
of the call (foo) had failed to result in a guard violation error;
now, it does, provided guard-checking is on (i.e., not nil or
:none; see [set-guard-checking]).
The symbols ctx, hist, pspv, unquote, and value have been added to
[*ACL2-exports*]. Thanks to Jared Davis for suggesting these
additions.
Consider :use or :by [hints] in which a variable bound using the
:instance keyword is in the wrong package. For example, for the
hint :use ((:instance foo (x 3))), suppose that the lemma foo
mentions the variable bar::x, but not x. This situation formerly
caused an error, but now, x indicates the variable bar::x from the
lemma foo. See [lemma-instance], in particular Condition (4), which
has been updated accordingly. Thanks to David Rager for a remark
that led us to implement this enhancement.
The [ld] special ld-error-action may now have a value (:exit N),
where N is a natural number. If an error occurs for a call of ld,
then this value causes the ACL2 process to quit with exit status N.
See [ld-error-action]. Note that ld-error-action is set to this new
value when using the cert.pl utility provided with the community
books; see [build::pre-certify-book-commands]. Thanks to David
Rager for presenting an example showing how this change can make it
easier to locate certain certification failures, and thanks to Sol
Swords for helping in the design of this enhancement.
A \"[Theory]\" warning is still printed when [definition]s of certain
built-in functions, such as [mv-nth], are [disable]d; similarly for
some built-in [executable-counterpart] rules. However, we now print
such warnings only when the disabling occurs, rather than every
time an [in-theory] event or hint is evaluated. For example, if you
evaluate (in-theory (disable mv-nth)) followed by (in-theory
(disable append)), then the second event will no longer produce a
warning about mv-nth. Thanks to Eric Smith for (most recently)
suggesting such a change.
(SBCL only) ACL2 built on SBCL now reports bytes usage, both in
[time$] and in [memsum], essentially exactly as has already been
done for ACL2 built on CCL. Thanks to Jared Davis for suggesting
this enhancement.
(SBCL only) [Fast-alists] can now be garbage collected (we believe)
in SBCL, as they had already been done in CCL. (Implementation
note: The change was to use weak hash tables in the implementation
of SBCL fast-alists.) Thanks to Jared Davis for suggesting this
enhancement.
The utility [ec-call] can now be applied to calls of symbols
introduced with [defun-inline], or with [define] using keyword
argument :inline t, thanks to a request from Jared Davis. For
example, the following is now legal.
(defun-inline foo (x)
(cons x x))
(defun bar (x)
(ec-call (foo x)))
The [proof-checker] is now sensitive to the current
[case-split-limitations].
New Features
The Common Lisp function [sleep] is now defined in ACL2. Thanks to
Jared Davis for requesting this addition.
Custom error messages may now be created for guard violations. See
[set-guard-msg].
The new macro [assert*] is like [assert$], except that assert* only
generates a [guard] proof obligation, not a runtime check. Assert*
is defined using a new macro [mbt*], which is a variant of [mbt]: a
call of mbt* logically returns t, but generates the same [guard]
proof obligation as mbt. Thanks to Shilpi Goel for a query that led
us to add these macros.
Heuristic and Efficiency Improvements
We fixed an inefficiency that could occur in calls of [program]-mode
functions that update [stobj]s. See the discussion of
invariant-risk in the [documentation] topic, [program-wrapper].
Thanks to Jared Davis for bringing this issue to our attention.
We improved the ``worse-than'' heuristic, providing modest speed-up
and eliminating the use of memoization for it. Thanks to Jared
Davis for useful discussions on the topic, and to Camm Maguire for
an observation that led us to do some investigations that led to
this improvement. For more information see comments in source
function worse-than-builtin-clocked (source file type-set-b.lisp).
We avoid the cost of translating ACL2 terms (see [term]) to
user-level syntax after applying the ``preprocess'' simplifier (see
[hints-and-the-waterfall]), and also after applying either :use or
:by [hints]. Thanks to David Rager for helpful discussions towards
this change. Note: On rare occasions, this might change the prover
flow as follows.
* Consider the case that the input goal, \"Goal\", simplifies with the
``preprocess'' simplifier to a new goal that prints the same as
\"Goal\". Formerly, this case avoided labeling the new goal as
\"Goal'\"; it was as though the new goal was actually the user
input. The new criterion for avoiding \"Goal'\" is somewhat
weaker: the internal syntax must suitably match for \"Goal\" and
its simplification, rather than their displayed forms.
* Consider the application of a :use or :by hint. In such cases, the
resulting constraint (if any) is simplified with the
``preprocess'' simplifier. Formerly, the rules used by that
simplifier were not recorded if the printed version of the
simplified constraint was equal to the original constraint,
which was really a bug since the comparison was between the
user-level syntax of the simplified constraint and the internal
syntax of the original constraint. Now, ACL2 compares the
internal syntax of each.
We fixed an inefficiency that could occur in processing of
[make-event] forms. Thanks to Sol Swords for reporting and
diagnosing the problem. (Technical note: The fix involves avoiding,
in most cases, looking up world global 'boot-strap-flg by using a
new state global instead of the same name.)
We changed the heuristics for equality subsitution so that so-called
cross-fertilization, where an equality substitution is made on only
one side of the goal's conclusion, is not made when generalization
is turned off, as with the hint :do-not '(generalize). Instead, the
equality is used throughout the goal in that case. Thanks to David
Hardin for bringing an example to our attention that led us to make
this change.
Some clause-building (essentially, goal-building) operations already
avoided duplication, but now consider clauses to be ``duplicates''
when the only difference is commuted arguments of [equal] or [iff].
(Note: This change was made in support of [assert*] and [mbt*],
mentioned above.)
(SBCL only) It had been the case for host Lisp SBCL that the use of
[defun-inline] to define functions in [books] had failed to result
in inlined code, when those functions were called after including
those books. This has been fixed (and appears not to have been a
problem for host Lisp CCL). Thanks to Jared Davis for bringing this
issue to our attention.
Bug Fixes
A potential soundness issue could result from the application of
[meta]functions and [clause-processor]s: although ACL2 checked that
their outputs contain only legal [term]s, it did not check for the
absence of calls of certain ``forbidden'' function symbols. For
example, [sys-call] should be prohibited unless there is an active
trust tag (see [defttag]), but a metafunction was able to introduce
a call of sys-call. We have added the necessary checks, in a way
that we hope has negligible impact on performance. To avoid that
impact or to learn more about this issue, see
[set-skip-meta-termp-checks]; this new utility, which requires a
trust tag, avoids not only the new checks but even the
above-mentioned checks for legal terms.
The edited log below illustrates a bug that we have fixed, involving
the processing of [include-book] [events] in the certification
[world] whose filename starts with the tilde (~) character.
~/temp/incl$ cat sub/bad.acl2
(include-book \"~/acl2/acl2/books/arithmetic/top\")
~/temp/incl$ acl2h
[[.. output elided ..]]
ACL2 !>(ld \"sub/bad.acl2\")
[[.. output elided ..]]
ACL2 !>(certify-book \"foo\" 1)
HARD ACL2 ERROR in ABSOLUTE-PATHNAME-STRING-P: Implementation error:
Forgot to apply expand-tilde-to-user-home-dir before calling absolute-
pathname-string-p. Please contact the ACL2 implementors.
ACL2 Error in TOP-LEVEL: Evaluation aborted. To debug see :DOC print-
gv, see :DOC trace, and see :DOC wet.
ACL2 !>
Fixed several issues with the :puff command, and updated its
documentation accordingly. See [puff].
Fixed a bug in the [proof-checker]'s wrap command. Thanks to Keshav
Kini for sending a simple example that illustrated this bug.
(Allegro CL only) Fixed a bug in [trace!], which for example was
evidenced when evaluating (trace! (nth :native t)).
Fixed a bug in the printing of user-level terms that failed to
account for [untrans-table] entries for [nth], [update-nth], and
[update-nth-array], when printing the first argument as a symbolic
constant corresponding to a [stobj] argument. Thanks to Warren Hunt
for reporting this issue with an example much like the following.
When submitting the forms below, ACL2 output for the final form
displayed the user-level term (update-nth *fld* v st) instead of
the expected form, (!nth *fld* v st).
(defstobj st fld)
(defmacro !nth (x y z)
`(update-nth ,x ,y ,z))
(add-macro-fn !nth update-nth)
(thm (equal (update-fld v st)
xxx)
:hints ((\"Goal\" :in-theory (disable update-nth))))
Fixed a failure to [guard]-check [type] declarations for [let] and
[mv-let] forms. Consider for example:
(defun foo (x)
(let ((a (car x)))
(declare (type string a))
a))
Previously, the call (foo '(3 4)) did not cause a guard violation,
even though it should have done so. (Indeed, the event
(verify-guards foo) failed, and continues to fail.)
Fixed a bug in redundancy checking for [mutual-recursion] events that
specify :[ruler-extenders] in an [xargs] [declare] form. Thanks to
Sol Swords for sending an example that illustrates the bug: a
[mutual-recursion] event that, when executed twice, caused an error
the second time rather than being redundant (see
[redundant-events]). The bug was actually in how ACL2 stores
information about the [ruler-extenders] used in definitions: the
:ruler-extenders specified for the first [defun] was being
mistakenly stored for the second defun. This mishandling of
redundancy for [mutual-recursion] events appears to be the only
consequence of that bug.
The following bug was probably not observable, but violated our claim
that the system behaves as logically specified. When a [guard]
check failed during execution, the error message that was printed
could differ slightly from what is logically specified. (Technical
detail: the error actually printed by source function ev-fncall-rec
was appropriately showing the original guard, but the specification
function ev-fncall-rec-logical was showing the untranslation of the
translated guard.) This has been fixed.
The save and retrieve commands for the [proof-checker] (see
[ACL2-pc::save] and [ACL2-pc::retrieve]) now cause an error when
the supplied name is not a symbol; similarly for the :event-name
argument of [verify]. The behavior wasn't as expected for
non-symbol names; for example, after issuing the instruction (save
'abc) in the [proof-checker], the command (retrieve 'abc) failed to
resume the proof-checker session. (Notice the erroneous use of the
quoted symbol 'abc, i.e., (quote abc), rather than of the symbol
abc.) Thanks to Keshav Kini for bringing this problem to our
attention.
We fixed the following two bugs in the processing of backchain limits
stored for rules. Thanks to Dave Greve for bringing these to our
attention.
* For rules of class :[type-prescription], the specification of
:backchain-limit-lst within the :[rule-classes] could be
ignored or cause a hard Lisp error.
* For rules of class :[meta], preceding calls of
[set-default-backchain-limit] were ignored.
Fixed a bug in the processing of certain operations on pathnames
containing \"..\".
Changes at the System Level
By default, the ACL2 executable once again is named saved_acl2,
though unlike previous versions, this executable is [hons-enabled].
Correspondingly, the ACL2(c) executable (that is, the executable
that is not [hons-enabled]) is by default saved_acl2c. Thanks to
David Hardin for suggesting these changes.
Links from the home page to user's manual topics now point to the
ACL2+Books combined manual, not the ACL2 (only) User's Manual,
except for the one link that explicitly points to the latter.
Thanks to David Hardin for feedback leading to this change, which
was incorporated into the ACL2 Version 7.0 home page several days
after the release of that version.
Garbage collection notification has been turned off by default, not
only for ACL2(c) as before, but also for (the default build)
ACL2(h). Thanks to Eric Smith for suggesting this change. See
[ACL2-customization] and see [gc-verbose] for how to turn such
notification back on in your own environment.
It is now possible to move the system books directory after
certifying its books, without invalidating their status as
certified. Users should generally not notice this change. We thank
Harsh Raju Chamarthi and Camm Maguire for reporting problems with
hacks we have produced over the years to support distribution of
books with their [certificate] files. Those hacks are no longer
necessary: as a byproduct of this change, we have deleted both the
[community-books] directory books/fix-cert/ and the source function
make-certificate-file-relocated. For a bit more detail see the
final remark in the topic [full-book-name]. We also thank Eric
Smith, Jared Davis, and Sol Swords for reporting bugs in our
initial implementations of this enhancement.
The certify-books target for make now excludes other expensive
directories in addition to workshops.
(SBCL only) Modified the handling of environment variable SBCL_HOME.
Thanks to Jared Davis for pointing out a problem leading to this
change, namely, failure on his platform when evaluating (require
:sb-sprof) in raw Lisp.
Intended compiler optimizations are now guaranteed to be in place. We
observed, thanks to communication from Jared Davis, that when ACL2
is built using SBCL 1.2.10, ACL2 starts up without the compiler
optimizations that had been installed during the build. Perhaps
that has been true for other SBCL versions or even other Lisps.
Now, ACL2 explicitly restores those optimizations when it starts
up. We observed a 5% time reduction for SBCL-based regression after
this change.
Environment variable ACL2_WRITE_PORT is now ignored when doing
[provisional-certification]. Thanks to Sol Swords for discussing
this issue, which arose from a failure in [community-books]
directory books/workshops/2011/verbeek-schmaltz/sources/, which
uses [provisional-certification].
(GCL only) A few tweaks were made in support of GCL changes starting
with pre-releases of GCL 2.6.13 in late April 2015 (but these
tweaks are backward compatible with older GCL releases). Resulting
ACL2 builds for a new GCL show dramatic speed-ups for a single
user, perhaps cutting between a third and half the time, with less
dramatic improvements when running regressions with -j 8. Thanks to
Camm Maguire for pointing us to the changes and for improving GCL.
EMACS Support
The commands Control-t e and Control-t Control-e, defined in file
emacs/emacs-acl2.el, now check that the *acl2-shell* buffer exists,
has a live process, and has a last line matching the specification
in *acl2-insert-pats*, which has Emacs documentation (using
Control-h v) but is set to a default based on shell prompts. Thanks
to David Rager, Jared Davis, and Shilpi Goel for helpful
discussions leading to this change.
We installed the following two patches to file emacs/emacs-acl2.el,
both contributed by Keshav Kini.
* Emacs highlighting for forms starting with \"(def\" now works when the
\"def\" symbol has a package prefix, for example,
\"(fty::deflist\".
* The Control-d character is no longer explicitly bound to the default,
delete-char, but instead is unbound in comint-mode-map, so that
the global binding of Control-d will take effect. Thus, users
who bind Control-d themselves will no longer have that binding
overridden in shell-mode (or comint-mode).
We made several improvements to the [ACL2-doc] Emacs browser for ACL2
[documentation].
* Fixed a bug that could occur when Emacs variable
large-file-warning-threshold is nil. Thanks to Bob Boyer for
bringing this bug to our attention.
* Links are now in color (blue, by default). See [ACL2-doc] for
instructions on how to change or remove this color. Thanks to
Jared Davis for suggesting the use of color. We are open to
suggestions for improvements; this might be just a first step.
* Allow limiting search and index commands to ancestors (sub-topics,
sub-sub-topics, etc.) of a command (including the command
itself), by supplying a prefix argument.
* New \"p\", \"<\", and Control-TAB commands are analogues of \"n\", \",\", and
TAB --- for search, index, and next-link commands, respectively
--- to go backward instead of forward.
Experimental Versions
(For ACL2(p) users only; see [parallelism]) If parallel execution is
enabled (see (@see set-parallel-execution)), as it is by default in
ACL2(p), then hons-wash and hons-clear may be no-ops (other than to
print a warning), in order to avoid thread-unsafe behavior.
(However, In CCL you are unlikely to see this restriction unless
you are running more than one thread.) To get around this
restriction, you can instead use [hons-wash!] or [hons-clear!],
which however require a [trust-tag]. Thanks to Bob Boyer for
bringing this issue to our attention.")
(NOTE-7-2
(RELEASE-NOTES)
"ACL2 Version 7.2 (January, 2016) Notes
NOTE! New users can ignore these release notes, because the
[documentation] has been updated to reflect all changes that are
recorded here.
Below we roughly organize the changes to ACL2 since Version 7.1 into
the following categories of changes: existing features, new
features, heuristic and efficiency improvements, bug fixes, changes
at the system level, Emacs support, and experimental versions. Each
change is described in just one category, though of course many
changes could be placed in more than one category.
See also [note-7-2-books] for a summary of changes made to the ACL2
Community Books since ACL2 7.1, including the build system.
Changes to Existing Features
The utility [with-guard-checking] is now limited to forms that do not
reference the ACL2 [state]. A related new utility,
[with-guard-checking-error-triple], may be used for forms that
evaluate to [error-triple]s. For an example showing a bug when
with-guard-checking was applied to forms that access [state], see
the comment about ``with-guard-checking'' in Community Books file
system/doc/acl2-doc.lisp, in the form (defxdoc note-7-2 ...). We
thank Jared Davis for sending us an example showing that our
preliminary fix was not adequate; for details, and for how a trust
tag can avoid the new restriction (at the potential cost of
unsoundness), see the remark for advanced users in the
documentation for [with-guard-checking].
Several built-in functions are now in :[logic] mode with [guard]s
verified: [term-order], merge-sort-term-order, [arity], [termp],
[term-listp], and [term-list-listp] --- new functions arities-okp
and plist-worldp-with-formals; and (thanks to Eric Smith for the
suggestions) collect-by-position, make-lambda-application, >=-len,
all->=-len, strip-cadrs, and alist-to-doublets. (Technical note:
This enhancement followed the usual process: adding or extending
community books in directory books/system/, including any new such
books in books/system/top.lisp, and updating source constant
*system-verify-guards-alist*.)
Deprecated utilities clear-hash-tables and wash-memory have been
eliminated. For clear-hash-tables, you can get the same effect by
first invoking [clear-memoize-tables], and then invoking either
(hons-clear t) or instead, if your executable uses static honsing,
(hons-wash). For wash-memory you can invoke (clear-memoize-tables)
and then (hons-wash). Thanks to Jared Davis for helpful
discussions.
The [command]s :[ubt] and :[ubu] have been changed. Their previous
functionality is available with the commands :[ubt?] and :[ubu?],
respectively. Now, :[ubt] and :[ubu] behave much more like :[ubt!]
and :[ubu!] (which have not been changed), in that they do not
cause queries; however, unlike :[ubt!] and :[ubu!], the [command]s
:[ubt] and :[ubu] do report errors. Thanks to Eric Smith for
requesting this change.
Now, :[puff*] has an optional argument that can avoid rollback of the
world when there is an error. See [puff*].
After invoking :[redef] and redefining functions in a
[mutual-recursion] event, it was necessary to answer Y repeatedly
in order to complete the redefinitions. A new option, Y!, will
complete the remaining such redefinitions without further query.
Thanks to Eric Smith for requesting this feature.
A harmless but somewhat annoying superfluous declaration (DECLARE
(XARGS :NON-EXECUTABLE T)) was, by default, included in the
generated [defun] for a [defun-sk] event. This has been fixed.
Thanks to Eric Smith for bringing this issue to our attention.
The [proof-checker] command show-rewrites (or sr; see
[ACL2-pc::show-rewrites]) now shows additional bindings of free
variables that would be generated when a third argument of t is
supplied for the rewrite (or r; see [ACL2-pc::rewrite]) command.
Thanks to Ben Selfridge for noting that this information was
missing. Note that we also made a few trivial formatting changes
for sr.
The redundancy check for [encapsulate] [events] has changed in two
small ways. One change is described below (see ``Redundancy
checking for [encapsulate]''). The other change is the redundancy
check now properly identifies a previous subsidiary [make-event]
form with its expansion, ignoreing the record-expansion wrapper.
See the example labeled ``Redundant after Version_7.1 (as of
mid-September 2015)'' in community book
books/make-event/local-elided.lisp.
A new mechanism for controlling the checking for [invariant-risk]
replaces the raw Lisp global variable *ignore-invariant-risk*,
which is obsolete. See [set-check-invariant-risk]. In particular,
the default is now to print a (new) warning when encoutering
potential slowdown due to invariant-risk. Note that more functions
are now subject to the invariant-risk check; see the discussion
below in the section on Bug Fixes that pertains to invariant-risk.
The (undocumented) system utility with-ubt!, which continues to be
used in [trace!] and [disassemble$] and is now also used in
[set-check-invariant-risk], now binds [ld] special
[ld-pre-eval-print] to nil. Thus, when with-ubt! is invoked,
subsidiary forms will not be printed to the screen even when the
above LD special is non-nil.
Formerly, [certify-book], [include-book], and [puff] operated with
guard-checking off; technically, with [state] global
guard-checking-on bound to nil. Now, that value is bound to t,
which matches the default value in the top-level loop. Thanks to
Eric Smith for suggesting this change to certify-book and to Jared
Davis for a helpful conversation about it.
For [guard] proof obligations, all conjuncts from [stobj]
declarations (supplied as :stobjs keywords in [xargs] declarations)
preceded all other conjuncts (i.e., from [type] declarations or
[xargs] :guard declarations). Previously, this was only true within
a given [declare] form. Thanks to Dave Greve for bringing this
issue to our attention.
A new runic abbreviation has been added: :r, which abbreviates
:rewrite. For example, you may use (:r app-assoc) in a theory
expression to denote the [rune] (:rewrite app-assoc). See
[theories].
It is now possible to [monitor] rules by supplying a symbol or other
runic designator other than a theory (see [theories]), thus
relaxing the previous requirement that a [rune] is supplied. For
example, the form :monitor nth t is legal, as is :monitor (:d nth)
t, where before the corresponding command would necessarily have
been :monitor (:definition nth) t. Thanks to Eric Smith for
requesting this enhancement.
Suitable [warnings] are now printed when attempting to [monitor]
[simple] rules of class :[definition]. These had only been printed
for simple rules of class :(tsee rewrite), because of potential
inefficiency in computing for such warnings in the case of large
[mutual-recursion] [events], but that problem has been addressed in
the ACL2 source code using [fast-alists].
ACL2 sometimes produces smaller .cert files, by avoiding certain
macroexpansion. Formerly, for each macro call encountered in a
certification world or [make-event] expansion, ACL2 performed
repeated single-step macroexpansion until an event form was
obtained, and replaced the original form with that result. The
reason for this replacement was to modify certain [include-book]
forms involving relative pathnames (though only under specific
conditions). Now, no such replacement is made except when such a
modification is made to an include-book call. This change could
result in smaller [certificate] (.cert) files; for example, if a
[portcullis] [command] is a macro call, (foo), that expands into a
very large [defun] or [defthm] event, the certificate file will
contain (foo) rather than its macroexpansion. Of course, this
change could result in longer times for processing an
[include-book] forms, because now macroexpansion may need to be
done when they are processed; but such macroexpansion has always
been necessary for all forms within a book, so such behavior is at
least more consistent than before. If you really want a portullis
macro call to be expanded, wrap it in a [make-event] call, for
example, (make-event '(foo)) instead of (foo).
The macros [defund] and [defthmd] now produce less output. In fact,
the output is the same as for [defun] and [defthm], respectively,
except for the printing of the return value, which (as before)
looks like (:DEFUND NAME) or (:DEFTHMD NAME). Thanks to Jared Davis
for suggesting such a change.
Remaining traces of legacy documentation have generally been
eliminated, including all vestiges of the obsolete command, defdoc.
([Documentation] is now generally provided through the [xdoc]
system.) In particular, optional and keyword arguments, doc, have
been eliminated for the following macros.
* [defabsstobj]
* [defabsstobj-missing-events]
* [defaxiom]
* [defchoose]
* [deflabel]
* [defstobj]
* [defstub]
* [deftheory]
* [defthm]
* defthm-std (defined only in ACL2(r); see [real])
* [defttag]
* [in-arithmetic-theory]
* [include-book]
* [push-untouchable]
* [regenerate-tau-database]
* [remove-untouchable]
* [reset-prehistory]
* [thm]
* [verify-guards]
Note that [defabbrev], [defconst], [defmacro], [defpkg], and [defun]
may still be supplied documentation strings, as a nod to Common
Lisp. In particular, for defun and defmacro this can ease the
porting of Common Lisp code to ACL2.
Several source-level definitions have changed, many of them
unadvertised. Some are for unadvertised event commands like
defthm-fn, which no longer have a doc argument (see ``traces of
legacy documentation have generally been eliminated'' above).
Others, like flambda-applicationp, are macros that were formerly
defined with [defabbrev] but now are defined with [defmacro];
thanks to Eric Smith for suggesting such simplifications.
In prover output, terms of the form (not (not expr)) had been printed
simply as expr. That could cause confusion; for example, the
following form would lead to the checkpoint (EQUAL (ALISTP X)
(ALISTP X)), where actually the checkpoint was (EQUAL (NOT (NOT
(ALISTP X))) (ALISTP X)). This ``feature'' has been eliminated.
Thanks to Shilpi Goel for bringing this issue to our attention and
supplying an illustrative example.
A warning was formerly printed when encountering a macro call with
duplicate keys, for example (foo 3 :y 4 :y 5) where :y is a keyword
argument of the macro, foo. Now, this is an error by default, in
order to make it easier for users to catch bugs due to accidental
repetition of a keyword argument. However, the utility
[set-duplicate-keys-action] can be used to allow such duplicate
keys, with or without a warning. Thanks to Jared Davis for
requesting these changes.
Warnings are no longer printed for :use hints applied to functional
instances of enabled rules. Thanks to Eric Smith for suggesting
this change.
The second (optional) argument of show-accumulated-persistence may
now have a new value, :list, which causes the results to be
displayed as a single list with entries of the form (frames tries
xrune). Thanks to David Rager for requesting a way to display
useless [rune]s, sorted in a manner that can help with automating
the creation of in-theory forms that disable unnecessary runes;
also thanks for his helpful discussions in designing its
functionality. See [accumulated-persistence]; in particular,
(show-accumulated-persistence :useless :list) can display a list of
runes to consider disabling.
The utility [print-gv] now takes additional keyword arguments,
:conjunct and :substitute, which respectively show a specific
conjunct of the [guard] evaluation that produced nil, and avoid
[flet] in favor of substituting actuals (even at the risk of
duplication). See [print-gv], and see [set-print-gv-defaults] for a
utility that sets default values for the keyword arguments. Thanks
to Eric Smith for requesting these enhancements and for helpful
discussions. Note that the system default value for the
:evisc-tuple keyword is now the value of the form
(print-gv-evisc-tuple).
[State] global variable global-enabled-structure is now untouchable
(see [remove-untouchable]).
Users may see a change in the order, number, and size of termination
proof obligations because of an optimization that removes trivial
equality tests generated by [case] and [cond] statements. (The
removal of the tests can affect subsumption, which is how the order
and number of proof obligations may change.)
Once again, all documented constant, function, and macro symbols in
the \"ACL2\" package are included in the constant, [*ACL2-exports*].
Community book books/misc/check-acl2-exports.lisp has been updated
for the current documentation system to enforce this invariant in
the future. Thanks to Jared Davis for pointing out that the symbol
[extend-pe-table] was missing from *acl2-exports* and would be a
good addition; that led us to this change. As also suggested by
Jared, we added the symbols [exists] and [forall] to
*acl2-exports*, as well.
The quantifier [forall] or [exists] used in the body of a [defun-sk]
call must now be in the \"ACL2\" package. Many users will not notice
this change, since the symbols forall and exists in the \"ACL2\"
package are now in the list [*ACL2-exports*]; see the paragraph
just above. Thanks to Alessandro Coglio for a remark leading to
this change.
Definitions are no longer redundant that have different values
specified for their [xargs] keyword, :normalize. (See
[redundant-events].) Although we are not aware of a need to make
this change, this change eliminates a possibile unsoundness.
It is now the case that open-output-channel and open-output-channel!
will attempt to create missing directories as needed. (This had
formerly been observed to be the case in CCL but not other Lisp
implementations.) Thanks to Jared Davis for requesting this
enhancement.
New Features
It is now possible to make ACL2 avoid the well-formedness checks done
when metafunctions and clause processors are run. By default, when
a metafunction or clause processor is run, ACL2 calls [termp] or
[term-list-listp], respectively, on the new value to make sure it
is well-formed. Now, if you prove and provide a
:[well-formedness-guarantee] with the :meta or :clause-processor
rule-class, you can skip these checks. This can speed up the use of
metafunctions and clause processors on big terms and formulas.
It is now possible to ensure the integrity of statistics produced by
[memsum] after functions are [memoize]d. See
[protect-memoize-statistics]. Thanks to Alessandro Coglio for
noticing oddities in those statistics and to Jared Davis for
providing an implementation of this new feature.
Function [read-file-into-string] provides an efficient way to return
the contents of a file as a string, without returning an ACL2
[state]. Thanks to Jared Davis for pointing out a logical flaw in
the initial implementation.
A new function, get-skipped-proofs-p, can tell system programmers
whether or not a given event name was introduced with proofs
skipped, as with [skip-proofs] or using [set-ld-skip-proofsp]. See
[system-utilities]. Thanks to Eric Smith for requesting such a
capability.
A new [table] permits the association of names with substitute event
forms, for use by [history] commands that print event forms,
including :[pe], :[pc], :[pcb], and :[pcb!]. See [extend-pe-table].
Thanks to Eric Smith for requesting such a capability. Note that
:[pe!] now avoids use of this table.
A new macro, ffn-symb-p, has been introduced and then used in the
source code to simplify some definitions. Thanks to Jared Davis for
a remark that led us to define and introduce this macro. See
[system-utilities] for a description of this and many other
low-level system utilities.
It is now possible to give [hints] that specify the use of
termination or [guard] theorems for existing function symbols. See
[lemma-instance], [termination-theorem-example], and
[guard-theorem-example]. Also see [gthm] and [tthm] for related
query utilities. Thanks to Alessandro Coglio and Eric Smith for
requesting these features.
See [set-print-gv-defaults] for a new utility for setting default
values for the keyword arguments of [print-gv]. Thanks to Eric
Smith for requesting this feature and for helpful discussions.
For [history] commands and the function [disabledp], the notion of
``[disable]d'' is now computed inside the [break-rewrite] loop with
respect to the [enable]d status at the current point of the current
proof attempt, rather than with respect to the global state. Thanks
to David Rager for suggesting this enhancement. Note that this
change only affects [history] commands and [disabledp], not other
utilities (for example [tau-status] and [guard-obligation]).x
New system utility [getpropc] is a convenient abbreviation for
[getprop].
A new utility causes some warnings to be printed in a ``raw''
s-expression format. See [set-raw-warning-format]. Thanks to Shilpi
Goel for requesting this utility.
The macro accumulated-persistence-oops undoes the effect of
accidentally clearing statistics with (accumulated-persistence t)
or (accumulated-persistence :all). See [accumulated-persistence].
Thanks to Jared Davis for requesting this feature.
Heuristic and Efficiency Improvements
The redundancy check for [defconst] has been sped up in cases with a
very large term, as in the following example. Thanks to David Rager
and Jared Davis for helpful related discussions.
(defun make-tree (n)
(declare (type (integer 0 *) n))
(if (zp n)
nil
(let ((x (make-tree (1- n))))
(cons x x))))
(make-event
`(defconst *a* (hons-copy ',(make-tree 50))))
; Redundant, and formerly very slow:
(make-event
`(defconst *a* (hons-copy ',(make-tree 50))))
Processing of [defpkg] forms may be faster, thanks to a change
suggested by Jared Davis (who observed significant speedup in
SBCL).
Optimizations have been made that can speed up [include-book] for
some large books, as follows. In particular, for the form (time$
(include-book \"centaur/sv/tutorial/alu\" :dir :system)) we have seen
a 25% reduction (on Mac OS) for the first item below, and an
additional 29% reduction (also on Mac OS) for the second item.
* Various optimizations have been made for [theory] manipulation,
including some to make processing for efficient for [defund]
and [defthmd]. Thanks to Sol Swords for bringing this issue to
our attention in GitHub Issue #401 and for reporting bugs in
our initial implementations.
* Redundancy checking for [encapsulate] [events] can be much faster.
The only functional change (with one small exception, described
in an item above) is to check for a sub-event of the proposed
encapsulate event that is attempting to introduce a new name;
if no such name is found, then the redundancy check is skipped,
and the proposed encapsulate event is evaluated. This new check
is quite thorough (see [redundant-encapsulate]), so we expect
it to be rare that an encapsulate event that was formerly
redundant is no longer redundant.
[Certify-book] is faster in some cases; for example, we found the
time required to certify a book whose only event is (include-book
\"centaur/gl/gl\" :dir :system) was reduced from 57 seconds to 10
seconds. (Implementation note: The change was to avoid installing
worlds in function defpkg-items. That had probably been done in
order to speed up calls of simple-translate-and-eval in
defpkg-items-rec, but that speed-up seems to be dwarfed by the
expense of extend-world1 in such cases.)
We tweaked a part of the so-called ``clausify'' process for doing
Boolean simplification towards producing subgoals of a given goal,
namely, the so-called ``subsumption-replacement-loop''
(specifically, source function find-subsumer-replacement). Thanks
to Jared Davis for helpful discussions that led us to make this
change.
[Defevaluator] is faster, especially so when many functions are to be
interpreted by the new evaluator. The new version is a refactored
version of community book books/tools/defevaulator-fast.lisp used
with the permission of its original authors Sol Swords and Jared
Davis. Thanks!
The Common Lisp code generated for [stobj] accessors and updaters has
been improved in the case that the :type is T or of the form (array
T ...). In particular, we have seen efficiency improvements for
host Lisp CCL when the value read from or written to the array is a
fixnum (integers that are sufficiently small in absolute value).
Thanks to Bob Boyer and Gary Byers for helpful discussions that led
to this improvement.
Bug Fixes
We fixed a soundness bug pertaining to [local] [defpkg] [events]. See
community books directory misc/hidden-defpkg-checks/ for an example
that exploits this bug to prove nil in Version 7.1 and perhaps some
other previous ACL2 versions. Thanks to Sol Swords for helping us
set up that test (specifically, suggesting addition of the comment
``; no_port'' after an [include-book] call that is not to be put
into a .port file).
The use of [set-deferred-ttag-notes] during [make-event] expansion
could cause some TTAG NOTE messages never to be printed. Thanks to
Jared Davis for a remark that led us to discover this bug, which
could be considered a soundness bug since the TTAG NOTE mechanism
is a key part of the soundness story. With this change, the effects
of set-deferred-ttag-notes persist past make-event expansion.
It was possible to use :[program] mode functions to write past the
end of an array, leading to unsoundness. This has been fixed. Now,
updaters for [stobj] array fields are marked as having so-called
``invariant-risk'', even when the element type of the array is t
(unconstrained). Also marked with invariant-risk are built-in
functions [aset1] and [aset2]. See [program-wrapper],
[invariant-risk] and [set-check-invariant-risk], which is discussed
above in the section Changes to Existing Features. Thanks to Jared
Davis and Sol Swords for sending an example to illustrate the bug.
When ACL2 was interrupted while debugging was on (see
[set-debugger-enable]), it was possible later to get the following
error repeatedly:
HARD ACL2 ERROR in TIME-TRACKER: It is illegal to specify :START for
tag :TAU, because tracking for this tag is already in an active state.
This problem has been fixed, by defining a new keyword argument for
[time-tracker], :start!, and using it to track the use of the
[tau-system]; see [time-tracker] and [time-tracker-tau].
ACL2 would cause an error at startup when the value of environment
variable ACL2_SYSTEM_BOOKS was a string starting with the tilde
character (~). This has been fixed. Thanks to Shilpi Goel and
Warren Hunt for bringing this bug to our attention.
(GCL only) It had not been possible to define a [stobj] with more
than 64 fields in GCL. We have removed that restriction. (Technical
note: GCL disallows calls of the function, vector, with more than
64 arguments. So instead we now build a list of stobj fields that
is coerced to a vector, rather than calling vector directly.)
Fixed [deftheory-static] by declaring the [world] to be ignorable,
thus avoiding errors for forms that don't reference the world.
Thanks to Jared Davis for pointing out this bug with the example,
(deftheory-static my-theory '(car-cons)).
Fixed a bug that was causing the hiding-cars component of the
[ld-evisc-tuple] to be ignored when printing evaluation results.
We avoid an error in the case that [skip-proofs] is used around a
definition with no tests above a recursive call, as in the
following example.
(skip-proofs (defun foo (x)
(declare (xargs :measure (acl2-count x)))
(identity
(cond ((zp x) 17)
(t (foo (1- x)))))))
Thanks to Dave Greve for bringing this bug to our attention. Note
that such a definitional event may be unsound (not surprisingly,
because of the use of skip-proofs). For example, the following form
succeeds: (thm nil :hints ((\"Goal\" :induct (foo x)))).
Several improvements have been made to avoid errors in the execution
of :[puff] and :[puff*]. Thanks to Eric Smith for reporting this
issue. (Technical implementation note: a bug in source function
find-longest-common-retraction1-event, used in reverting logical
[world]s, was fixed in support of this work.)
When the [default-defun-mode] was :[logic], then a [mutual-recursion]
form with [xargs] declaration of :[program] mode, which also had
one or more [defund] [events], would cause a error when attempting
to [disable] new function symbols after admitting their
definitions. This has been fixed. Thanks to Jared Davis for
bringing this bug to our attention (GitHub Issue #464).
We fixed some printing bugs for :[psof], :[pso], and raw proof format
(see [set-raw-proof-format]). Both :[psof] and :[pso] were printing
explicit splitter notes (see [splitter]) --- and worse yet, and
thanks to David Rager for pointing this out, :[psof] was printing
them to the terminal. Those explicit splitter notes were not
appropriate during proof replay, where instead parenthetical
phrases like ``(if-intro)'' are sufficient; those phrases continue
to be printed during proof replay, just as when [gag-mode] is off.
Raw proof format had a couple of whitespace bugs, but more
important was its failure to indicate any information about
splitters; so now it prints the same explicit splitter notes as are
printed for gag-mode.
Insufficient checking has been fixed for [signature]s. Thanks to
Jared Davis for sending the example ((f * *) => * :formals (x)
:guard (natp x)), which was not flagged as illegal by ACL2 even
though the specified arity of 2 did not match the length of the
specified :formals. There could also be mismatches between the
[stobj]s specified, for example, with (((f * st1) => * :formals (x
st2) :guard (natp x))), that were not flagged as illegal.
The inclusion of uncertified books was leading to some incorrect
messages about other books that are also uncertified. This has been
fixed (though the messages can still be verbose at times). Thanks
to Eric Smith for sending an example to bring this problem to our
attention.
There were some incorrect error messages produced for bad calls of
[ec-call]; these have been fixed.
Fixed a bug in [memoization] that could occur when multiprocessing is
turned on, as in the call (acl2::mf-multiprocessing t) in community
book books/centaur/vl/server/server-raw.lsp. Thanks to Sol Swords
for reporting a bad report from [memsum] when profiling function
include-book-fn before including system book \"doc/top\".
[Guard] violation error messages printed 'ACL2_INVISIBLE::|The Live
State Itself| where they should have printed STATE; similarly for
the utility [print-gv], which also failed to print entirely in
user-level ``untranslated'' syntax. These problems have been fixed.
Thanks to Eric Smith for bringing the ``STATE'' bug to our
attention.
Infinite loops occurred for calls of (close-output-channel
*standard-co* state) after redirecting standard output using
set-standard-co. A clean error now occurs instead.
We fixed a bug in [state-global-let*] --- actually, in its supporting
system utility acl2-unwind-protect --- that allowed capture of a
lexical variable, temp, to produce bad results, for example as
follows.
(defun foo (temp state)
(declare (xargs :stobjs state :mode :program))
(state-global-let*
((x 3))
(pprogn
(fms \"TEMP = ~x0~%X = ~x1~%\" (list (cons #0 temp) (cons #1 (@ x)))
*standard-co* state nil)
(value nil))))
(foo 17 state) ; should show TEMP = 17 and X = 3, but caused Lisp error
ACL2 no longer prints a message for a failed :induct hint (in the
case that [gag-mode] is off), saying that a definition is
[disable]d when that is not the case.
(CCL only, probably only 32-bit CCL) We fixed a bug manifested with
an error, ``is not of the expected type (UNSIGNED-BYTE 32).''
(Technical note: Function ccl::set-lisp-heap-gc-threshold requires
a fixnum, but was passed a bignum.) Thanks to Harsh Raju Chamarthi
for sending us a log that exhibited this bug, namely
books/oracle/stv-invariant-extraction-pitfall/alu.lisp, which seems
to have evoked the bug by using an unusually large amount of
memory.
One might reasonably expect that for a [rewrite] or [linear] rule
with a hypothesis of the form (force ...) or (case-split ...), an
attempt to relieve that hypothesis should be successful when
forcing is enabled. The situation is a bit tricky if the hypothesis
has free variables, but even then, one would expect success if the
:match-free value is the default, :all, or if no suitable bindings
are found. Such attempts had however not always been successful;
but they are now, and the relevant documentation on
[free-variables] has been clarified. For an example exhibiting the
bug, see the comment about ``free variables'' in Community Books
file system/doc/acl2-doc.lisp, in the form (defxdoc note-7-2 ...).
An inappropriate warning has been eliminated for some
[type-prescription] rules, for example the following.
(defthm foo
(implies (alistp mem)
(or (equal (assoc loc mem) nil)
(consp (assoc loc mem))))
:rule-classes :type-prescription)
The warning had claimed that the rule ``may be weaker than you
expect'' because the theorem itself ``is not provable using
type-set reasoning''. But the theorem is provable when
[guard-holders] are removed, as could generally be expected; so
now, the check is applied after removing guard-holders from the
theorem.
The [guard]s stored for [macros] now include [type] declarations.
Formerly the guards stored for macros were based only on the
:[xargs] :guard keyword. Consider for example the following
definition.
(defmacro foo (x)
(declare (type integer x))
x)
(defun bar (y)
(foo y))
Formerly, no error occurred when processing the definition of bar,
because the guard stored for foo was t. Now, the guard stored for
foo is (integerp x); since the variable y is not an integer (it is
a symbol), the attempted [defun] for bar causes an error.
Changes at the System Level
ACL2 is now defined to incorporate its [hons-enabled] features. We
formerly supported building ACL2 without these features, resulting
in so-called Classic ACL2, also called ``ACL2(c)''. Such builds are
no longer supported: although it is still technically possible to
build ACL2(c), we do not stand behind such builds; in particular,
we do not test them, and we have removed the GNUmakefile target,
saved_acl2c.
(CCL only) Starting with CCL Version 16384, EGC (the ephemeral
garbage collector) is enabled in ACL2 by default, in place of a
``start-sol-gc'' memory management scheme, but with some of the
delay in full garbage collection that had been provided by that
scheme. That scheme is still available to users, under a different
name and inside the ACL2 loop; see [set-gc-strategy]. (Note that
both set-gc-strategy and gc-strategy have been added to
[*ACL2-exports*].) Thanks to Gary Byers for CCL improvements
leading to this change, and to him, Bob Boyer, Jared Davis, and Sol
Swords for helpful discussions. The default behavior can be
restored to the previous behavior at ACL2 build time, by setting
Make variable ACL2_EGC_ON=nil when building an ACL2 executable.
A new mechanism allows importing of theorems into the ACL2 source
code, thus extending the existing mechanism for importing
termination and guard verification for system functions (see the
item above about [term-order], merge-sort-term-order, and so on).
Using this mechanism, some theorems have been imported from a new
community book, books/system/termp.lisp. (For an example of how
ACL2 developers use this mechanism, see the call of system-events
in ACL2 source file boot-strap-pass-2.lisp.)
File GNUmakefile in the (top-level) ACL2 sources directory now sets
environment variable TIME_CERT so that regressions will generate
timing information.
(SBCL only) The --control-stack-size argument for ACL2 executables
saved for SBCL is now 64 (formerly 16). Thanks to Jared Davis for
requesting this increase.
The existing utility [get-event-data] is now documented. Moreover, it
can be used for determining whether an interrupt (Control-C)
occurred during execution of an event. (This capability is used in
a new utility, [removable-runes].) See [get-event-data].
The startup banner now shows the git commit hash for development
snapshots. Thanks to Bob Boyer for suggesting such a modification
and to Jared Davis for bringing to our attention the appropriate
git command for retrieving the hash.
(CMUCL only) It is now the case for CMUCL that [setenv$] modifies the
environment of the underlying Lisp process. Thanks to Jared Davis
for this suggestion, and for pointing out that CCL and SBCL [at
least] already have this behavior.
A new optimize declaration for [defun], (:stack-access 3), can result
in some speed up for evaluations done when the host Lisp is CCL
(but is likely to be a no-op in other host Lisps). Thus, you may
write: (defun foo (x) (declare (optimize (:stack-access 3))) ...).
Thanks to Gary Byers and the CCL team for their excellent compiler
work, including the new stack-access feature, and to Bob Boyer and
Warren Hunt for helpful discussions. To build ACL2 on CCL with this
feature, add the variable setting ACL2_STACK_ACCESS=3 to the make
command that you invoke to build ACL2. NOTE: The use of
ACL2_STACK_ACCESS relies on recognition by CCL of the :stack-access
keyword for optimize expressions, hence will only have effect for
CCL versions starting with 16678.
(CMUCL only) Updated saved_acl2 for CMUCL to use maximum heap for CMU
Common Lisp snapshot-2016-01 and beyond. Thanks to Raymond Toy for
updating CMUCL such that one can specify with -dynamic-space-size 0
that the maximum heap is used.
EMACS Support
We made several improvements in the [ACL2-doc] browser.
* A bug has been fixed in the S command (acl2-doc-re-search).
* The help message is displayed more often (but only, we think, when
appropriate) in the echo area (i.e., below the mode line).
* The q command (acl2-doc-quit) now can be run from any buffer in
acl2-doc mode, for example after typing the H command.
Moreover, all such buffers will be buried after q; formerly, if
you quit from the main acl2-doc buffer you could have been left
in the acl2-doc-history buffer.
[Verify-termination] calls are now indented like [defun] calls.
Thanks to Alessandro Coglio for suggesting this change to
emacs/emacs-acl2.el.
The [ACL2-doc] Emacs browser now allows handling of topics with
square brackets. This fix was necessary because a new topic,
SV::4VEC-[=, broke acl2-doc; it wouldn't initialize. The fix simply
replaces characters #\\[ and #\\] with #\\< and #\\>, respectively.
It's not a perfect fix, but it seems awkward to try to escape #\\[
(which Emacs Lisp thinks starts a vector). See community book
system/doc/render-doc-base.lisp.
Experimental Versions
Fixed some interleaved output that could appear with
[waterfall-parallelism] enabled. Thanks to Eric Smith for reporting
this problem and to David Rager for a helpful chat.")
(NOTE1
(RELEASE-NOTES)
"Acl2 Version 1.1 Notes
The new features are extensively documented. The relevant topics are:
It is especially important to read all of of the [documentation] for
[books] before trying to use books. However, the new :more keyword
command is so handy for reading long [documentation] strings that
we recommend you start with :[doc] more if reading at the terminal.
Some documentation has been written for [guard]s which you might
find interesting.
Subtopics
[Books]
Books are files of ACL2 [events]---they are the main way to split up
large ACL2 developments into separate modules.")
(NOTE2
(RELEASE-NOTES)
"Acl2 Version 1.2 Notes
Hacker mode has been eliminated and [programming] mode has been
added. [Programming] mode is unsound but does syntax checking and
permits redefinitions of names. See :[doc] load-mode and :[doc]
g-mode.
The arguments to [ld] have changed. [Ld] is now much more
sophisticated. See [ld].
For those occasions on which you wish to look at a large list
structure that you are afraid to print, try (walkabout x state),
where x is an Acl2 expression that evaluates to the structure in
question. I am afraid there is no [documentation] yet, but it is
similar in spirit to the Interlisp structure editor. You are
standing on an object and commands move you around in it. E.g., 1
moves you to its first element, 2 to its second, etc.; 0 moves you
up to its parent; nx and bk move you to its next sibling and
previous sibling; pp prettyprints it; [q] exits returning nil; [=]
exits returning the thing you're standing on; (= symb) assigns the
thing you're standing on to the [state] global variable symb.
Several new [hints] have been implemented, including :by and :do-not.
The old :do-not-generalize has been scrapped in favor of such new
[hints] as :do-not (generalize elim). :By lets you say ``this goal
is subsumed by'' a given lemma instance. The :by hint also lets you
say ``this goal can't be proved yet but skip it and see how the
rest of the proof goes.'' See [hints].")
(NOTE3
(RELEASE-NOTES)
"Acl2 Version 1.3 Notes
[Programming] mode has been eliminated. Instead, all functions have a
``color'' which indicates what can be done with the function. For
example, :red functions can be executed but have no axioms
describing them. Thus, :red functions can be introduced after
passing a simple syntactic check and they can be redefined without
undoing. But nothing of consequence can be proved about them. At
the other extreme are :gold functions which can be executed and
which also have passed both the termination and the [guard]
verification proofs. The color of a function can be specified with
the new [xargs] keyword, :color, which, if omitted defaults to the
global setting of ld-color. Ld-color replaces load-mode. Setting
ld-color to :red causes behavior similar to the old :g-mode.
Setting ld-color to :gold causes behavior similar to the old
:v-mode. It is possible to prototype your system in :red and then
convert :red functions to :blue individually by calling
[verify-termination] on them. They can then be converted to :gold
with [verify-guards]. This allows us to undertake to verify the
termination and [guard]s of system functions. See :[doc] color for
an introduction to the use of colors.
Type prescription rules have been added. Recall that in Nqthm, some
[rewrite] rules were actually stored as ``[type-prescription]s.''
Such rules allow the user to inform Nqthm's primitive type
mechanism as to the kinds of shells returned by a function. Earlier
versions of Acl2 did not have an analogous kind of rule because
Acl2's type mechanism is complicated by [guard]s. Version 1.3
supports [type-prescription] rules. See [type-prescription].
Three more new [rule-classes] implement congruence-based rewriting.
It is possible to identify a binary relation as an equivalence
relation (see [equivalence]), to show that one equivalence relation
refines another (see [refinement]) and to show that a given
equivalence relation is maintained when rewriting a given function
call, e.g., (fn ...xk...), by maintaining another equivalence
relation while rewriting the kth argument (see [congruence]). If r
has been shown to be an [equivalence] relation and then (implies
hyps (r (foo x) (bar x))) is proved as a :[rewrite] rule, then
instances of (foo x) will be replaced by corresponding instances of
(bar x) provided the instance occurs in a slot where the
maintainence of r-equivalence is known to be sufficient and hyps
can be established as usual.
In Version 1.2, [rule-classes] were simple keywords, e.g., :[rewrite]
or :[elim]. In Version 1.3, [rule-classes] have been elaborated to
allow you to specify how the theorem ought to be used as a rule.
That is, the new [rule-classes] allows you to separate the
mathematical statement of the formula from its interpretation as a
rule. See [rule-classes].
Rules used to be named by symbols, e.g., [car] and car-cons were the
names of rules. Unfortunately, this was ambiguous because there are
three rules associated with function symbols: the symbolic
definition, the executable counterpart, and the
[type-prescription]; many different rules might be associated with
theorems, depending on the rule classes. In Version 1.3 rules are
named by ``[rune]s'' (which is just short hand for ``rule names'').
Example [rune]s are (:definition car), (:executable-counterpart
car), and (:type-prescription car . 1). Every rule added by an
event has a different name and you can [enable] and [disable] them
independently. See [rune] and see [theories].
The identity function [force], of one argument, has been added and
given a special interpretation by the functions responsible for
establishing hypotheses in backchaining: When the system fails to
establish some hypothesis of the form (force term), it simply
assumes it is true and goes on, delaying until later the
establishment of term. In particular, pushes a new subgoal to prove
term in the current context. When that subgoal is attacked, all of
the resources of the theorem prover, not just rewriting, are
brought to bear. Thus, for example, if you wish to prove the rule
(implies (good-statep s) (equal (exec s n) s')) and it is your
expectation that every time exec appears its first argument is a
good-statep then you might write the rule as (implies (force
(good-statep s)) (equal (exec s n) s')). This rule is essentially
an unconditional rewrite of (exec s n) to s' that spawns the new
goal (good-statep s). See [force]. Because you can now specify
independently how a theorem is used as a rule, you need not write
the [force] in the actual theorem proved. See [rule-classes].
Version 1.3 supports a facility similar to Nqthm's [break-lemma]. See
[break-rewrite]. You can install ``[monitor]s'' on [rune]s that
will cause interactive breaks under certain conditions.
Acl2 also provides ``[wormhole]s'' which allow you to write functions
that cause interaction with the user but which do not require that
you have access to [state]. See [wormhole].
The rewriter now automatically backchains to stronger recognizers.
There is no user hook to this feature but it may simplify some
proofs with which older versions of Acl2 had trouble. For example,
if the rewriter is trying to prove (rationalp (foo a b c)) it is
now smart enough to try lemmas that match with (integerp (foo a b
c)).")
(NOTE4
(RELEASE-NOTES)
"Acl2 Version 1.4 Notes
Once again [ld] only takes one required argument, as the bind-flg has
been deleted.
Three commands have been added in the spirit of :[pe]. :[Pe!] is
similar to :[pe] but it prints all [events] with the given name,
rather than just the most recent. The command :[pf] prints the
corollary formula corresponding to a name or [rune]. The command
:[pl] (print lemmas) prints rules whose top function symbol is the
given name. See [pe!], see [pf], and see [pl].
Book naming conventions have been changed somewhat. The once-required
.lisp extension is now prohibited! Directories are supported,
including a notion of ``connected book directory''. See
[book-name]. Also, the second argument of [certify-book] is now
optional, defaulting to 0.
[Compilation] is now supported inside the Acl2 loop. See [comp] and
see [set-compile-fns].
The default color is now part of the Acl2 [world]; see :[doc]
default-color. Ld-color is no longer an [ld] special. Instead,
colors are [events]; see the documentation for red, pink, blue, and
gold.
A [table] exists for controlling whether Acl2 prints comments when it
[force]s hypotheses of rules; see :[doc] force-table. Also, it is
now possible to turn off the forcing of assumptions by disabling
the definition of [force]; see [force].
The event defconstant is no longer supported, but a very similar
event, [defconst], has been provided in its place. See [defconst].
The event for defining [congruence] relations is now [defcong]
(formerly, defcon).
Patterns are now allowed in :expand [hints]. See the documentation
for :expand inside the documentation for [hints].
We have improved the way we report rules used by the simplifier. All
[rune]s of the same type are reported together in the running
commentary associated with each goal, so that for example,
executable counterparts are listed separately from definitions, and
rewrite rules are listed separately from [linear] rules. The
preprocessor now mentions ``simple'' rules; see [simple].
The mechanism for printing warning messages for new rewrite rules,
related to subsumption, now avoids worrying about nonrecursive
function symbols when those symbols are [disable]d. These messages
have also been eliminated for the case where the old rule is a
:[definition] rule.
Backquote has been modified so that it can usually provide
predictable results when used on the left side of a rewrite rule.
Time statistics are now printed even when an event fails.
The Acl2 trace package has been modified so that it prints using the
values of the Lisp globals *print-level* and *print-length*
(respectively).
[Table] has been modified so that the :clear option lets you replace
the entire [table] with one that satisfies the val and key guards
(if any); see [table].
We have relaxed the translation rules for :measure [hints] to
[defun], so that the the same rules apply to these terms that apply
to terms in [defthm] [events]. In particular, in :measure [hints]
[mv] is treated just like [list], and [state] receives no special
handling.
The [loop-stopper] test has been relaxed. The old test required that
every new argument be strictly less than the corresponding old
argument in a certain [term-order]. The new test uses a
lexicographic order on term lists instead. For example, consider
the following rewrite rule.
(equal
(variable-update var1
val1 (variable-update var2 val2 vs))
(variable-update var2
val2 (variable-update var1 val1 vs)))
This rule is permutative. Now imagine that we want to apply this rule
to the term
(variable-update u y (variable-update u x vs)).
Since the actual corresponding to both var1 and var2 is u, which is
not strictly less than itself in the [term-order], this rule would
fail to be applied in this situation when using the old test.
However, since the pair (u x) is lexicographically less than the
pair (u y) with respect to our [term-order], the rule is in fact
applied using our new test.
Messages about [events] now contain a space after certain left
parentheses, in order to assist emacs users. For example, the event
(defthm abc (equal (+ (len x) 0) (len x)))
leads to a summary containing the line
Form: ( DEFTHM ABC ...)
and hence, if you search backwards for ``(defthm abc'', you won't
stop at this message.
More tautology checking is done during a proof; in fact, no goal
printed to the screen, except for the results of applying :use and
:by [hints] or the top-level goals from an induction proof, are
known to Acl2 to be tautologies.
The [ld-query-control-alist] may now be used to suppress printing of
queries; see [ld-query-control-alist].
Warning messages are printed with short summary strings, for example
the string ``Use'' in the following message.
Acl2 Warning [Use] in DEFTHM: It is unusual to :USE an enabled
:REWRITE or :DEFINITION rule, so you may want to consider
disabling FOO.
At the end of the event, just before the time is printed, all such
summary strings are printed out.
The keyword command :u has been introduced as an abbreviation for
:[ubt] :[max]. Printing of query messages is suppressed by :u.
The keyword :cheat is no longer supported by any event form.
Some irrelevant formals are detected; see [irrelevant-formals].
A bug in the application of metafunctions was fixed: now if the
output of a metafunction is equal to its input, the application of
the metafunction is deemed unsuccessful and the next metafunction
is tried.
An example has been added to the documentation for [equivalence] to
suggest how to make use of [equivalence] relations in rewriting.
The following Common Lisp functions have been added to Acl2:
[alpha-char-p], [upper-case-p], [lower-case-p], [char-upcase],
[char-downcase], [string-downcase], [string-upcase], and
digit-charp-p.
A documentation section called [proof-checker] has been added for the
interactive facility, whose documentation has been slightly
improved. See in particular the documentation for [proof-checker],
[verify], and [macro-command].
A number of [events] that had been inadvertently disallowed in
[books] are now permitted in [books]. These are: [defcong], defcor,
[defequiv], [defrefinement], [defstub], and [verify-termination].")
(NOTE5
(RELEASE-NOTES)
"Acl2 Version 1.5 Notes
Acl2 now allows ``complex rationals,'' which are complex numbers
whose real parts are rationals and whose imaginary parts are
non-zero rationals. See [complex].
A new way of handling [force]d hypotheses has been implemented.
Rather than cause a case split at the time the [force] occurs, we
complete the main proof and then embark on one or more ``forcing
rounds'' in which we try to prove the [force]d hypotheses. See
[forcing-round]. To allow us to compare the new handling of [force]
with the old, Version 1.5 implements both and uses a flag in
[state] to determine which method should be used. Do (assign
old-style-forcing t) if you want [force] to be handled as it was in
Version 1.4. However, we expect to eliminate the old-style forcing
eventually because we think the new style is more effective. To see
the difference between the two approaches to forcing, try proving
the associativity of [append] under both settings of
old-style-forcing. To get the new behavior invoke:
(thm (implies (and (true-listp a) (true-listp b))
(equal (append (append a b) c)
(append a (append b c)))))
Then (assign old-style-forcing t) and invoke the thm [command] above
again.
A new :cases [hints] allows proof by cases. See [hints].
[Include-book] and [encapsulate] now restore the
[ACL2-defaults-table] when they complete. See [include-book] and
see [encapsulate].
The [guard]s on many Acl2 primitives defined in axioms.lisp have been
weakened to permit them to be used in accordance with lisp custom
and tradition.
It is possible to attach heuristic filters to :[rewrite] rules to
limit their applicability. See [syntaxp].
A tutorial has been added (but as of Version_3.6.1 it has become
obsolete).
[Events] now print the Summary paragraph listing [rune]s used, time,
etc., whether they succeed or fail. The format of the ``[failure]
banner'' has been changed but still has multiple asterisks in it.
Thm also prints a Summary, whether it succeeds or fails; but thm is
not an event.
A new event form [skip-proofs] has been added; see [skip-proofs].
A user-specific customization facility has been added in the form of
a book that is automatically included, if it exists on the current
directory. See [ACL2-customization].
A facility for conditional metalemmas has been implemented; see
[meta].
The acceptable values for [ld-skip-proofsp] have changed. In the old
version (Version 1.4), a value of t meant that proofs and [local]
[events] are to be skipped. In Version 1.5, a value of t means
proofs (but not [local] [events]) are to be skipped. A value of
'[include-book] means proofs and [local] [events] are to be
skipped. There are two other, more obscure, acceptable values. See
[ld-skip-proofsp].
In order to turn off the forcing of assumptions, one should now
[disable] the :[executable-counterpart] of [force] (rather than the
:[definition] of [force], as in the previous release); see [force].
The macros [enable-forcing] and [disable-forcing] make it convenient
to [enable] or [disable] forcing. See [enable-forcing] and see
[disable-forcing].
The new commands :[pr] and :[pr!] print the rules created by an event
or command. See [pr] and see [pr!].
The new [history] [command]s :[puff] and :[puff*] will replace a
compound [command] such as an [encapsulate] or [include-book] by
the sequence of [events] in it. That is, they ``[puff] up'' or
``lift'' the subevents of a [command] to the [command] level,
eliminating the formerly superior [command] and lengthening the
[history]. This is useful if you want to ``partially undo'' an
[encapsulate] or book or other compound [command] so you can
experiment. See [puff] and see [puff*].
Theory expressions now are allowed to use the free variable [world]
and prohibited from using the free variable [state]. See
[theories], although it is essentially the same as before except it
mentions [world] instead of [state]. See [world] for a discussion
of the Acl2 logical [world]. Allowing [in-theory] [events] to be
state-sensitive violated an important invariant about how [books]
behaved.
[Table] keys and values now are allowed to use the free variable
[world] and prohibited from using the free variable [state]. See
the note above about theory expressions for some explanation.
The macro for minus, [-], used to expand (- x 3) to (+ x -3) and now
expands it to (+ -3 x) instead. The old macro, if used in the
left-hand sides of rewrite rules, produced inapplicable rules
because the constant occurs in the second argument of the [+], but
potential target terms generally had the constant in the first
argument position because of the effect of commutativity-of-+.
A new class of rule, :linear-alias rules, allows one to implement the
nqthm package and similar hacks in which a [disable]d function is
to be known equivalent to an arithmetic function.
A new class of rule, :built-in-clause rules, allows one to extend the
set of clauses proved silently by [defun] during measure and
[guard] processing. See [built-in-clause].
The new command [pcb!] is like [pcb] but sketches the [command] and
then prints its subsidiary [events] in full. See [pcb!].
:[Rewrite] class rules may now specify the :[loop-stopper] field. See
[rule-classes] and see [loop-stopper].
The rules for how [loop-stopper]s control permutative rewrite rules
have been changed. One effect of this change is that now when the
built-in commutativity rules for [+] are used, the terms a and (-
a) are permuted into adjacency. For example, (+ a b (- a)) is now
normalized by the commutativity rules to (+ a (- a) b); in Version
1.4, b was considered syntactically smaller than (- a) and so (+ a
b (- a)) is considered to be in normal form. Now it is possible to
arrange for unary functions be be considered ``invisible'' when
they are used in certain contexts. By default, [unary--] is
considered invisible when its application appears in the argument
list of [binary-+]. See [loop-stopper] and see :DOC
set-invisible-fns-table.
Extensive documentation has been provided on the topic of Acl2's
``term ordering.'' See [term-order].
Calls of [ld] now default [ld-error-action] to :return rather than to
the current setting.
The [command] descriptor :x has been introduced and is synonymous
with :[max], the most recently executed [command]. [History]
[command]s such as :[pbt] print a :x beside the most recent
[command], simply to indicate that it is the most recent one.
The [command] descriptor :x-23 is synonymous with (:x -23). More
generally, every symbol in the keyword package whose first
character is #\\x and whose remaining [characters] parse as a
negative integer is appropriately understood. This allows :[pbt]
:x-10 where :[pbt] (:max -10) or :[pbt] (:here -10) were previously
used. The old forms are still legal.
The order of the arguments to [defcong] has been changed.
The simplifier now reports the use of unspecified built-in type
information about the primitives with the phrase ``primitive type
reasoning.'' This phrase may sometimes occur in situations where
``propositional calculus'' was formerly credited with the proof.
The function [pairlis] has been replaced in the code by a new
function [pairlis$], because Common Lisp does not adequately
specify its [pairlis] function.
Some new Common Lisp functions have been added, including [logtest],
[logcount], [integer-length], [make-list], [remove-duplicates],
[string], and [concatenate]. The source file
/slocal/src/acl2/axioms.lisp is the ultimate reference regarding
Common Lisp functions in Acl2.
The functions [defuns] and [theory-invariant] have been documented.
See [defuns] and see [theory-invariant].
A few symbols have been added to the list *acl2-exports*.
A new key has been implemented for the [ACL2-defaults-table],
:irrelevant-formals-ok. See [set-irrelevant-formals-ok].
The connected book directory, [cbd], must be nonempty and begin and
end with a slash. It is set (and displayed) automatically upon your
first entry to [lp]. You may change the setting with [set-cbd]. See
[cbd].
:[oops] will undo the last :[ubt]. See [oops].
Documentation has been written about the ordinals. See :DOC
e0-ordinalp and see :DOC e0-ord-<. [Note added later: Starting with
Version_2.8, instead see [o-p] and see [o<].
The color [events] --- (red), (pink), (blue), and (gold) --- may no
longer be enclosed inside calls of [local], for soundness reasons.
In fact, neither may any event that sets the [ACL2-defaults-table].
See [embedded-event-form].
See [ld-keyword-aliases] for an example of how to change the exit
keyword from :[q] to something else.
The attempt to install a [monitor] on :[rewrite] rules stored as
simple abbreviations now causes an error because the application of
abbreviations is not tracked.
A new message is sometimes printed by the theorem prover, indicating
that a given simplification is ``specious'' because the subgoals it
produces include the input goal. In Version 1.4 this was detected
but not reported, causing behavior some users found bizarre. See
[specious-simplification].
:[Definition] rules are no longer always required to specify the
:clique and :controller-alist fields; those fields can be defaulted
to system-determined values in many common instances. See
[definition].
A warning is printed if a macro form with keyword arguments is given
duplicate keyword values. Execute (thm t :doc nil :doc \"ignored\")
and read the warning printed.
A new restriction has been placed on [encapsulate]. Non-[local]
recursive definitions inside the [encapsulate] may not use, in
their tests and recursive calls, the constrained functions
introduced by the [encapsulate]. See [subversive-recursions]. (Note
added in Version 2.3: Subversive recursions were first recognized
by us here in Version 1.5, but our code for recognizing them was
faulty and the bug was not fixed until Version 2.3.)
The [events] [defequiv], [defcong], [defrefinement], and
[defevaluator] have been reimplemented so that they are just macros
that expand into appropriate [defthm] or [encapsulate] [events];
they are no longer primitive [events]. See the [documentation] of
each affected event.
The defcor event, which was a shorthand for a [defthm] that
established a [corollary] of a named, previously proved event, has
been eliminated because its implementation relied on a technique we
have decided to ban from our code. If you want the effect of a
defcor in Version 1.5 you must submit the corresponding [defthm]
with a :by hint naming the previously proved event.
Error reporting has been improved for inappropriate [in-theory]
[hints] and [events], and for syntax errors in rule classes, and
for non-existent filename arguments to [ld].
Technical Note: We now maintain the Third Invariant on type-alists,
as described in the Essay on the Invariants on Type-alists, and
Canonicality. This change will affect some proofs, for example, by
causing a to rewrite more quickly to c when (equiv a b) and (equiv
b c) are both known and c is the canonical representative of the
three.")
(NOTE6
(RELEASE-NOTES)
"Acl2 Version 1.6 Notes
A new key has been implemented for the [ACL2-defaults-table],
:ignore-ok. See [set-ignore-ok].
It is now legal to have color [events], such as (red), in the
[portcullis] of a book. More generally, it is legal to set the
[ACL2-defaults-table] in the [portcullis] of a book. For example,
if you execute :red and then certify a book, the event (red) will
show up in the [portcullis] of that book, and hence the definitions
in that book will all be red (except when overridden by appropriate
declarations or [events]). When that book is included, then as
always, its [portcullis] must first be ``raised,'' and that will
cause the default color to become red before the [events] in the
book are executed. As always, the value of [ACL2-defaults-table]
immediately after execution of an [include-book], [certify-book],
or [encapsulate] form will be the same as it was immediately before
execution (and hence, so will the default color). See [portcullis]
and, for more about books, see [books].
A theory [ground-zero] has been defined to contain exactly those
rules that are [enable]d when Acl2 starts up. See [ground-zero].
The function [nth] is now [enable]d, correcting an oversight from
Version 1.5.
Customization files no longer need to meet the syntactic restrictions
put on [books]; rather, they can contain arbitrary Acl2 forms. See
[ACL2-customization].
Structured directory names and structured file names are supported;
see especially the documentation for [pathname], [book-name], and
[cbd].
Acl2 now works with some Common Lisp implementations other than akcl,
including Lucid, Allegro, and MCL.
A facility has been added for displaying proof trees, especially
using emacs; see [proof-tree].
There is a considerable amount of new [documentation], in particular
for the printing functions [fmt], [fmt1], and [fms], and for the
notion of Acl2 term (see [term]).
It is possible to introduce new well-founded relations, to specify
which relation should be used by [defun], and to set a default
relation. See [well-founded-relation].
It is possible to make functions suggest new inductions. See
[induction].
It is possible to change how Acl2 expresses [type-set] information;
in particular, this affects what clauses are proved when [force]d
assumptions are generated. See [type-set-inverter].
A new restriction has been added to [defpkg], having to do with
undoing. If you undo a [defpkg] and define the same package name
again, the imports list must be identical to the previous imports
or else an explanatory error will occur. See
[package-reincarnation-import-restrictions].
[Theory-invariant] and [set-irrelevant-formals-ok] are now embedded
event forms.
The command :[good-bye] may now be used to quit entirely out of Lisp,
thus losing your work forever. This command works in akcl but may
not work in every Common Lisp.
A theory [ground-zero] has been added that contains exactly the
[enable]d rules in the [startup] theory. See [ground-zero].
Define-pc-macro and define-pc-atomic-macro now automatically define
:red functions. (It used to be necessary, in general, to change
color to :red before invoking these.)
For a proof of the well-foundedness of e0-ord-< on the e0-ordinalps,
see [proof-of-well-foundedness]. [Note added later: Starting with
Version_2.8, [o<] and [o-p] replace e0-ord-< and e0-ordinalp,
respectively.]
Free variables are now handled properly for hypotheses of
:[type-prescription] rules.
When the system is loaded or saved, [state] is now bound to
*the-live-state*.
[Certify-book] has been modified so that when it compiles a file, it
loads that object file.
[Defstub] has been modified so that it works when the color is hot
(:red or :pink).
Several basic, but not particularly commonly used, [events] have been
added or changed. The obscure axiom symbol-name-intern has been
modified. The definition of firstn has been changed. [Butlast] is
now defined. The definition of [integer-length] has been modified.
The left-hand side of the rewrite rule rational-implies2 has been
changed from (* (numerator x) (/ (denominator x))) to (* (/
(denominator x)) (numerator x)), in order to respect the fact that
[unary-/] is invisible with respect to [binary-*]. See
[loop-stopper].
The `preprocess' process in the waterfall (see [hints] for a
discussion of the :do-not hint) has been changed so that it works
to avoid case-splitting. The `simplify' process refuses to force
(see [force]) when there are [if] terms, including [and] and [or]
terms, in the goal being simplified.
The function apply is no longer introduced automatically by
translation of user input to internal form when functions are
called on inappropriate explicit values, e.g., (car 3).
The choice of which variable to use as the measured variable in a
recursive definition has been very slightly changed.")
(NOTE7
(RELEASE-NOTES)
"ACL2 Version 1.7 (released October 1994) Notes
[Include-book] now takes (optionally) an additional keyword argument,
indicating whether a compiled file is to be loaded. The default
behavior is unchanged, except that a warning is printed when a
compiled file is not loaded. See [include-book].
A markup language for [documentation] strings has been implemented,
and many of the source files have been marked up using this
language (thanks largely to the efforts of Laura Lawless). See
markup. Moreover, there are translators that we have used to
provide versions of the ACL2 [documentation] in info (for use in
emacs), html (for Mosaic), and tex (for hardcopy) formats.
A new event defdoc has been implemented. It is like [deflabel], but
allows redefinition of [doc] strings and has other advantages. See
defdoc.
We used to ignore corollaries when collecting up the axioms
introduced about constrained functions. That bug has been fixed. We
thank John Cowles for bringing this bug to our attention.
The macro [defstub] now allows a :[doc] keyword argument, so that
[documentation] may be attached to the name being introduced.
A new command [nqthm-to-ACL2] has been added to help Nqthm users to
make the transition to ACL2. See [nqthm-to-ACL2], which also
includes a complete listing of the relevant tables.
Many function names, especially of the form ``foo-lst'', have been
changed in order to support the following convention, for any
``foo'':
(foo-listp lst) represents the notion (for x in lst always foop x).
A complete list of these changes may be found at the end of this
note. All of them except symbolp-listp and list-of-symbolp-listp
have the string ``-lst'' in their names. Note also that
keyword-listp has been renamed [keyword-value-listp].
Accumulated persistence has been implemented. It is not connected to
:[brr] or rule monitoring. See [accumulated-persistence].
:Trigger-terms has been added for :[linear] rule classes, so you can
hang a [linear] rule under any addend you want. See [linear], which
has been improved and expanded.
ACL2 now accepts 256 [characters] and includes the Common Lisp
functions [code-char] and [char-code]. However, ACL2 controls the
lisp reader so that #\\c may only be used when c is a single
standard character or one of Newline, Space, Page, Rubout, Tab. If
you want to enter other [characters] use [code-char], e.g., (coerce
(list (code-char 7) (code-char 240) #a) 'string). See [characters].
Note: our current handling of [characters] makes the set of
theorems different under Macintosh Common Lisp (MCL) than under
other Common Lisps. We hope to rectify this situation before the
final release of ACL2.
A new [table], [macro-aliases-table], has been implemented, that
associates macro names with function names. So for example, since
[append] is associated with [binary-append], the form (disable
append) it is interpreted as though it were (disable
binary-append). See [macro-aliases-table], see [add-macro-alias]
and see [remove-macro-alias].
The implementation of conditional metalemmas has been modified so
that the metafunction is applied before the hypothesis metafunction
is applied. See [meta].
The Common Lisp functions [acons] and [endp] have been defined in the
ACL2 logic.
We have added the symbol [declare] to the list *acl2-exports*, and
hence to the package \"ACL2-USER\".
A new hint, :restrict, has been implemented. See [hints].
It used to be that if :[ubt] were given a number that is greater than
the largest current [command] number, it treated that number the
same as :[max]. Now, an error is caused.
The [table] :force-table has been eliminated.
A command :[disabledp] (and macro [disabledp]) has been added; see
[disabledp].
[Compilation] via :[set-compile-fns] is now suppressed during
[include-book]. In fact, whenever the [state] global variable
[ld-skip-proofsp] has value '[include-book].
Here are some less important changes, additions, and so on.
Unlike previous releases, we have not proved all the theorems in
axioms.lisp; instead we have simply assumed them. We have deferred
such proofs because we anticipate a fairly major changed in Version
1.8 in how we deal with [guard]s.
We used to (accidentally) prohibit the ``redefinition'' of a [table]
as a function. That is no longer the case.
The check for whether a [corollary] follows tautologically has been
sped up, at the cost of making the check less ``smart'' in the
following sense: no longer do we expand primitive functions such as
[implies] before checking this propositional implication.
The [command] [ubt!] has been modified so that it never causes or
reports an error. See [ubt!].
ACL2 now works in Harlequin LispWorks.
The user can now specify the :trigger-terms for :[linear] rules. See
[linear].
The name of the system is now ``ACL2''; no longer is it ``Acl2''.
The raw lisp counterpart of [theory-invariant] is now defined to be a
no-op as is consistent with the idea that it is just a call of
[table].
A bug was fixed that caused [proof-checker] [instructions] to be
executed when [ld-skip-proofsp] was t.
The function [rassoc] has been added, along with a corresponding
function used in its [guard], r-eqlable-alistp.
The [in-theory] event and hint now print a warning not only when
certain ``primitive'' :[definition] rules are [disable]d, but also
when certain ``primitive'' :[executable-counterpart] rules are
[disable]d.
The modified version of trace provided by ACL2, for use in raw Lisp,
has been modified so that the lisp special variable *trace-alist*
is consulted. This alist associates, using [eq], values with their
print representations. For example, initially *trace-alist* is a
one-element list containing the pair (cons state
'|*the-live-state*|).
The system now prints an observation when a form is skipped because
the default color is :red or :pink. (Technically: when-cool has
been modified.)
Additional protection exists when you submit a form to raw Common
Lisp that should only be submitted inside the ACL2 read-eval-print
loop.
Here is a complete list of the changes in function names described
near the top of this note, roughly of the form
foo-lst --> foo-listp
meaning: the name ``foo-lst'' has been changed to ``foo-listp.''
symbolp-listp --> symbol-listp
list-of-symbolp-listp --> symbol-list-listp
{for consistency with change to symbol-listp}
rational-lst --> rational-listp
{which in fact was already defined as well}
integer-lst --> integer-listp
character-lst --> character-listp
stringp-lst --> string-listp
32-bit-integer-lst --> 32-bit-integer-listp
typed-io-lst --> typed-io-listp
open-channel-lst --> open-channel-listp
readable-files-lst --> readable-files-listp
written-file-lst --> written-file-listp
read-file-lst --> read-file-listp
writeable-file-lst --> writable-file-listp
{note change in spelling of ``writable''}
writeable-file-lst1 --> writable-file-listp1
pseudo-termp-lst --> pseudo-term-listp
hot-termp-lst --> hot-term-listp {by analogy with pseudo-term-listp}
weak-termp-lst --> weak-term-listp
weak-termp-lst-lst --> weak-termp-list-listp
ts-builder-case-lstp -> ts-builder-case-listp
quotep-lst --> quote-listp
termp-lst --> term-listp
instr-lst --> instr-listp
spliced-instr-lst --> spliced-instr-listp
rewrite-fncallp-lst --> rewrite-fncallp-listp
every-occurrence-equiv-hittablep1-lst -->
every-occurrence-equiv-hittablep1-listp
some-occurrence-equiv-hittablep1-lst -->
some-occurrence-equiv-hittablep1-listp
{by analogy with the preceding, even though it's a
``some'' instead of ``all'' predicate]
almost-quotep1-lst --> almost-quotep1-listp
ffnnames-subsetp-lst --> ffnnames-subsetp-listp
boolean-lstp --> boolean-listp
subst-expr1-lst-okp --> subst-expr1-ok-listp")
(NOTE8
(RELEASE-NOTES)
"ACL2 Version 1.8 (May, 1995) Notes
See [note8-update] for yet more recent changes.
[Guard]s have been eliminated from the ACL2 logic. A summary is
contained in this brief note. Also see [defun-mode] and see
[set-guard-checking].
[Guard]s may be included in [defuns] as usual but are ignored from
the perspective of admission to the logic: functions must terminate
on all arguments.
As in Nqthm, primitive functions, e.g., [+] and [car], logically
default unexpected arguments to convenient values. Thus, (+ 'abc 3)
is 3 and (car 'abc) is nil. See [programming], and see the
[documentation] for the individual primitive functions.
In contrast to earlier versions of ACL2, Version 1.8 logical
functions are executed at Nqthm speeds even when [guard]s have not
been verified. In versions before 1.8, such functions were
interpreted by ACL2.
Colors have been eliminated. Two ``[defun-mode]s'' are supported,
:[program] and :[logic]. Roughly speaking, :[program] does what
:red used to do, namely, allow you to prototype functions for
execution without any proof burdens. :[Logic] mode does what :blue
used to do, namely, allow you to add a new definitional axiom to
the logic. A global [default-defun-mode] is comparable to the old
default color. The system comes up in :[logic] mode. To change the
global [defun-mode], type :[program] or :[logic] at the top-level.
To specify the [defun-mode] of a [defun] locally use
(declare (xargs :mode mode)).
The [prompt] has changed. The initial [prompt], indicating :[logic]
mode, is
ACL2 !>
If you change to :[program] mode the [prompt] becomes
ACL2 p!>
[Guard]s can be seen as having either of two roles: (a) they are a
specification device allowing you to characterize the kinds of
inputs a function ``should'' have, or (b) they are an efficiency
device allowing logically defined functions to be executed directly
in Common Lisp. If a [guard] is specified, as with [xargs]
:[guard], then it is ``verified'' at defun-time (unless you also
specify [xargs] :verify-guards nil). [Guard] verification means
what it always has: the input [guard] is shown to imply the
[guard]s on all subroutines in the body. If the [guard]s of a
function are verified, then a call of the function on inputs
satisfying the [guard] can be computed directly by Common Lisp.
Thus, verifying the [guard]s on your functions will allow them to
execute more efficiently. But it does not affect their logical
behavior and since you will automatically get Nqthm speeds on
unverified logical definitions, most users will probably use
[guard]s either as a specification device or only use them when
execution efficiency is extremely important.
Given the presence of [guard]s in the system, two issues are
unavoidable. Are [guard]s verified as part of the [defun] process?
And are [guard]s checked when terms are evaluated? We answer both
of those questions below.
Roughly speaking, in its initial [state] the system will try to
verify the [guard]s of a [defun] if a :[guard] is supplied in the
[xargs] and will not try otherwise. However, [guard] verification
in [defun] can be inhibited ``locally'' by supplying the [xargs]
:[verify-guards] nil. ``Global'' inhibition can be obtained via the
:[set-verify-guards-eagerness]. If you do not use the :[guard]
[xargs], you will not need to think about [guard] verification.
We now turn to the evaluation of expressions. Even if your functions
contain no [guard]s, the primitive functions do and hence you have
the choice: when you submit an expression for evaluation do you
mean for [guard]s to be checked at runtime or not? Put another way,
do you mean for the expression to be evaluated in Common Lisp (if
possible) or in the logic? Note: If Common Lisp delivers an answer,
it will be the same as in the logic, but it might be erroneous to
execute the form in Common Lisp. For example, should (car 'abc)
cause a [guard] violation error or return nil?
The top-level ACL2 loop has a variable which controls which sense of
execution is provided. To turn ``[guard] checking on,'' by which we
mean that [guard]s are checked at runtime, execute the top-level
form :set-guard-checking t. To turn it off, do :set-guard-checking
nil. The status of this variable is reflected in the [prompt].
ACL2 !>
means [guard] checking is on and
ACL2 >
means [guard] checking is off. The exclamation mark can be thought of
as ``barring'' certain computations. The absence of the mark
suggests the absence of error messages or unbarred access to the
logical axioms. Thus, for example
ACL2 !>(car 'abc)
will signal an error, while
ACL2 >(car 'abc)
will return nil.
Note that whether or not [guard]s are checked at runtime is
independent of whether you are operating in :[program] mode or
:[logic] mode and whether theorems are being proved or not.
(Although it must be added that functions defined in :[program]
mode cannot help but check their [guard]s because no logical
definition exists.)
Version 1.8 permits the verification of the [guard]s of theorems,
thus insuring that all instances of the theorem will evaluate
without error in Common Lisp. To verify the [guard]s of a theorem
named name execute the event
(verify-guards name).
If a theorem's [guard]s have been verified, the theorem is guaranteed
to evaluate without error to non-nil in Common Lisp (provided
resource errors do not arise).
Caveat about [verify-guards]: [implies] is a function symbol, so in
the term (implies p q), p cannot be assumed true when q is
evaluated; they are both evaluated ``outside.'' Hence, you cannot
generally verify the [guard]s on a theorem if [implies] is used to
state the hypotheses. Use [if] instead. In a future version of
ACL2, [implies] will likely be a macro.
See sum-list-example.lisp for a nice example of the use of Version
1.8. This is roughly the same as the documentation for
[guard-example].
We have removed the capability to do ``old-style-forcing'' as existed
before Version 1.5. See [note5].
NOTE: Some low level details have, of course, changed. One such
change is that there are no longer two distinct type prescriptions
stored when a function is admitted with its [guard]s verified. So
for example, the type prescription [rune] for [binary-append] is
now
(:type-prescription binary-append)
while in Versions 1.7 and earlier, there were two such [rune]s:
(:type-prescription binary-append . 1)
(:type-prescription binary-append . 2)
Nqthm-style forcing on [linear] arithmetic assumptions is no longer
executed when forcing is [disable]d.
Functional instantiation now benefits from a trick also used in
Nqthm: once a [constraint] generated by a :functional-instance
lemma instance (see [lemma-instance]) has been proved on behalf of
a successful event, it will not have to be re-proved on behalf of a
later event.
[1+] and [1-] are now macros in the logic, not functions. Hence, for
example, it is ``safe'' to use them on left-hand sides of rewrite
rules, without invoking the common warning about the presence of
nonrecursive function symbols.
A new [documentation] section [file-reading-example] illustrates how
to process forms in a file.
A new [proof-checker] command forwardchain has been added; see
[ACL2-pc::forwardchain].
It is now possible to use quantifiers. See [defun-sk] and see
[defchoose].
There is a new event [set-inhibit-warnings], which allows the user to
turn off warnings of various types. see [set-inhibit-warnings].
An unsoundness relating [encapsulate] and :functional-instance
[hints] has been remedied, with a few small effects visible at the
user level. The main observable effect is that [defaxiom] and
non-local [include-book] [events] are no longer allowed in the
scope of any [encapsulate] event that has a non-empty [signature].
When [certify-book] is called, we now require that the default
[defun-mode] (see [default-defun-mode]) be :[logic]. On a related
note, the default [defun-mode] is irrelevant to [include-book]; the
mode is always set to :[logic] initially, though it may be changed
within the book and reverts to its original value at the conclusion
of the [include-book]. A bug in [include-book] prevented it from
acting this way even though the [documentation] said otherwise.
The [documentation] has been substantially improved. A new section
``Programming'' contains [documentation] of many useful functions
provided by ACL2; see [programming]. Also, the [documentation] has
been ``marked up'' extensively. Thus in particular, users of Mosaic
will find many links in the [documentation].
The symbols [force], [mv-nth], and acl2-count have been added to the
list *acl2-exports*.
We now permit most names from the main Lisp package to be used as
names, except for names that define functions, macros, or
constants. See [name].
We have changed the list of imports from the Common Lisp package to
ACL2, i.e., the list *common-lisp-symbols-from-main-lisp-package*,
to be exactly those external symbols of the Common Lisp package as
specified by the draft Common Lisp standard. In order to
accommodate this change, we have renamed some ACL2 functions as
shown below, but these and other ramifications of this change
should be transparent to most ACL2 users.
warning --> warning$
print-object --> print-object$
Proof trees are no longer enabled by default. To start them up,
:[start-proof-tree].
We have added the capability of building smaller images. The easiest
way to do this on a Unix (trademark of AT&T) system is: make small.
Here we will put some less important changes, additions, and so on.
We have added definitions for the Common Lisp function [position]
(for the test [eql]), as well as corresponding versions
[position-equal] and [position-eq] that use tests [equal] and [eq],
respectively. See [position], see [position-equal], and see
[position-eq].
The [defthm] event rational-listp-implies-rationalp-car no longer
exists.
We fixed a bug in the hint mechanism that applied :by, :cases, and
:use [hints] to the first induction goal when the prover reverted
to proving the original goal by induction.
We fixed a bug in the handling of (set-irrelevant-formals-ok :warn).
In support of removing the old-style forcing capability, we deleted
the initialization of [state] global old-style-forcing and deleted
the definitions of recover-assumptions,
recover-assumptions-from-goal, remove-assumptions1,
remove-assumptions, and split-on-assumptions, and we renamed
split-on-assumptions1 to split-on-assumptions.
The special value 'none in the [proof-checker] commands claim and [=]
has been replaced by :none.
A bug in the handling of [hints] by subgoals has been fixed. For
example, formerly a :do-not hint could be ``erased'' by a :use hint
on a subgoal. Thanks go to Art Flatau for noticing the bug.
The functions weak-termp and weak-term-listp have been deleted, and
their calls have been replaced by corresponding calls of
[pseudo-termp] and pseudo-term-listp. The notion of [pseudo-termp]
has been slightly strenthened by requiring that terms of the form
(quote ...) have length 2.
Performance has been improved in various ways. At the prover level,
backchaining through the recognizer alist has been eliminated in
order to significantly speed up ACL2's rewriter. Among the other
prover changes (of which there are several, all technical): we no
longer clausify the input term when a proof is interrupted in favor
of inducting on the input term. At the [io] level, we have improved
performance somewhat by suitable declarations and proclamations.
These include technical modifications to the macros [mv] and
[mv-let], and introduction of a macro the-mv analogous to the macro
[the] but for forms returning multiple values.
The function spaces now takes an extra argument, the current column.
A bug in the [proof-checker] equiv command was fixed.
The function intersectp has been deleted, because it was essentially
duplicated by the function [intersectp-equal].
We now proclaim functions in AKCL and GCL before compiling [books].
This should result in somewhat increased speed.
The function repeat has been eliminated; use [make-list] instead.
The [proof-checker] command expand has been fixed so that it
eliminates [let] (lambda) expressions when one would expect it to.
A new primitive function, [mv-nth], has been introduced. [Mv-nth] is
equivalent to [nth] and is used in place of [nth] in the
translation of [mv-let] expressions. This allows the user to
control the simplification of [mv-let] expressions without
affecting how [nth] is treated. In that spirit, the rewriter has
been modified so that certain [mv-nth] expressions, namely those
produced in the translation of (mv-let (a b c)(mv x y z) p), are
given special treatment.
A minor bug in untranslate has been fixed, which for example will fix
the printing of conjunctions.
Translate now takes a logicp argument, which indicates whether it
enforces the restriction that :[program] mode functions do not
occur in the result.
The modified version of trace provided by ACL2, for use in raw Lisp,
has been modified so that the lisp special variable *trace-alist*
has a slightly different functionality. This alist associates,
using [eq], symbols with the print representations of their values.
For example, initially *trace-alist* is a one-element list
containing the pair (cons 'state '|*the-live-state*|). Thus, one
may cons the pair (cons '*foo* \"It's a FOO!\") on to *trace-alist*;
then until *foo* is defined, this change will have no effect, but
after for example
(defconst *foo* 17)
then trace will print 17 as \"It's a FOO!\".
Trace also traces the corresponding logic function.
[Proof-tree] display has been improved slightly in the case of
successful proofs and certain event failures.
The function positive-integer-log2 has been deleted.
The macro [skip-proofs] now prints a warning message when it is
encountered in the context of an [encapsulate] event or a book. See
[skip-proofs].
Some functions related to the-fn and wormhole1 now have [defun-mode]
:[program], but this change is almost certain to be inconsequential
to all users.")
(NOTE8-UPDATE
(RELEASE-NOTES)
"ACL2 Version 1.8 (Summer, 1995) Notes
ACL2 can now use Ordered Binary Decision Diagram technology. See
[bdd]. There is also a [proof-checker] bdd command.
ACL2 is now more respectful of the intention of the function [hide].
In particular, it is more careful not to dive inside any call of
[hide] during equality substitution and case splitting.
The [ld] special (see [ld]) [ld-pre-eval-print] may now be used to
turn off printing of input forms during processing of [encapsulate]
and [certify-book] forms, by setting it to the value :never, i.e.,
(set-ld-pre-eval-print :never state). See [ld-pre-eval-print].
The TUTORIAL documentation section (now obsolete) has, with much help
from Bill Young, been substantially improved to a bona fide
introduction.
The term pretty-printer has been modified to introduce (<= X Y) as an
abbreviation for (not (< Y X)).
Forward chaining and linear arithmetic now both benefit from the
evaluation of ground subterms.
A new macro [set-inhibit-output-lst] has been defined. This should be
used when setting the [state] global inhibit-output-lst; see
[set-inhibit-output-lst] and see [proof-tree].
The test for redundancy in definitions includes the [guard] and type
declarations. See [redundant-events].
See [generalized-booleans] for a discussion of a potential soundness
problem for ACL2 related to the question: Which Common Lisp
functions are known to return Boolean values?
Here we will put some less important changes, additions, and so on.
A bug has been fixed so that now, execution of :comp t (see [comp])
correctly handles non-standard characters.
A bug in [digit-char-p] has been fixed, so that the ``default'' is
nil rather than 0.
[True-listp] now tests the final [cdr] against nil using [eq] instead
of [equal], for improved efficiency. The logical meaning is,
however, unchanged.
[Put-assoc-equal] has been added to the logic (it used to have
:[defun-mode] :[program], and has been documented.")
(NOTE9
(RELEASE-NOTES)
"ACL2 Version 1.9 (Fall, 1996) Notes
By default, when the system is started it is illegal to use the
variable [state] as a formal parameter of a function definition.
The aim is to prevent novice users from stumbling into the
Byzantine syntactic restrictions on that variable symbol. Use
:set-state-ok t
or, equivalently,
(set-state-ok t)
to switch back to the old default mode. See [set-state-ok]
Set-state-ok is an event that affects the ACL2 defaults table (see
[ACL2-defaults-table]). Recall that when books are included, the
defaults table is restored to its pre-inclusion state. Thus, while
a set-state-ok form will permit the book to define a state-using
function, it will not permit the user of the book to make such a
definition. We recommend putting (set-state-ok t) in any book that
defines a state using function.
Books certified under Version 1.8 must be recertified under Version
1.9. See :DOC version.
The simplifier has been made to look out for built-in clauses,
whereas in past versions such clauses were only noticed by the
``preprocessor'' at the top of the waterfall. THIS CHANGE MAY
PREVENT OLD SCRIPTS FROM REPLAYING! The undesirable side-effect is
caused by the fact that :HINTS require you to refer to clauses by
their exact name (see [goal-spec]) and because the new simplifier
proves more clauses than before, the goals produced have different
names. Thus, if a script uses :HINTS that refer to clauses other
than \"Goal\", e.g., \"Subgoal 1.3\" then the hint may be applied to a
different subgoal than originally intended.
The use of built-in-clauses has been made more efficient. If a set of
clauses arise often in a piece of work, it might be advantageous to
build them in even if that results in a large set (hundreds?) of
built-in clauses. See [built-in-clause]
Wormholes can now be used in :logic mode functions. See [wormhole]
It is now possible to provide ``computed hints.'' For example, have
you ever wished to say ``in all goals with a name like this, :use
that'' or ``if this term is in the subgoal, then :use that''? Well,
see [computed-hints] and the extraordinarily long example in see
[using-computed-hints].
Hide terms may be rewritten with :rewrite rules about hide. See
[hide], where we also now explain why hide terms are sometimes
introduced into your proof attempts.
A bug that sometimes caused the ``non-lazy IF'' hard error message
was fixed.
A bug that sometimes caused a hard error in forward chaining was
fixed.
A bug in print-rules (:pr) was fixed.
We report the use of :executable-counterparts in the evaluation of
SYNTAXP forms.
Some documentation errors were fixed.
A bug in parent-tree tracking in add-literal-and-pt was fixed.
A bug in ok$, go$ and eval$ was fixed.
Clausify now optimizes (mv-nth 'k (list x0 ... xk ... xn)) to xk.")
(NQTHM-TO-ACL2
(ACL2-TUTORIAL)
"ACL2 analogues of Nqthm functions and commands
Example Forms:
:nqthm-to-acl2 prove-lemma ; Display ACL2 topic(s) and/or print
; information corresponding to Nqthm
; PROVE-LEMMA command.
(nqthm-to-acl2 'prove-lemma) ; Same as above.
General Form:
(nqthm-to-acl2 name)
where name is a notion documented for Nqthm: either a function in the
Nqthm logic, or a command. If there is corresponding information
available for ACL2, it will be printed in response to this command.
This information is not intended to be completely precise, but
rather, is intended to help those familiar with Nqthm to make the
transition to ACL2.
We close with two tables that contain all the information used by
this nqthm-to-acl2 command. The first shows the correspondence
between functions in the Nqthm logic and corresponding ACL2
functions (when possible); the second is similar, but for commands
rather than functions.
Nqthm functions --> ACL2
----------------------------------------
ADD1 --> 1+
ADD-TO-SET --> ADD-TO-SET-EQUAL and ADD-TO-SET-EQ
AND --> AND
APPEND --> APPEND and BINARY-APPEND
APPLY-SUBR --> No correspondent, but see the documentation for
DEFEVALUATOR and META.
APPLY$ --> No correspondent, but see the documentation for
DEFEVALUATOR and META.
ASSOC --> ASSOC-EQUAL, ASSOC and ASSOC-EQ
BODY --> No correspondent, but see the documentation for
DEFEVALUATOR and META.
CAR --> CAR
CDR --> CDR
CONS --> CONS
COUNT --> ACL2-COUNT
DIFFERENCE --> -
EQUAL --> EQUAL, EQ, EQL and =
EVAL$ --> No correspondent, but see the documentation for
DEFEVALUATOR and META.
FALSE --> Nqthm's F corresponds to the ACL2 symbol NIL.
FALSEP --> NOT and NULL
FORMALS --> No correspondent, but see the documentation for
DEFEVALUATOR and META.
GEQ --> >=
GREATERP --> >
IDENTITY --> IDENTITY
IF --> IF
IFF --> IFF
IMPLIES --> IMPLIES
LEQ --> <=
LESSP --> <
LISTP --> CONSP
LITATOM --> SYMBOLP
MAX --> MAX
MEMBER --> MEMBER-EQUAL, MEMBER and MEMBER-EQ
MINUS --> - and UNARY--
NEGATIVEP --> MINUSP
NEGATIVE-GUTS --> ABS
NLISTP --> ATOM
NOT --> NOT
NUMBERP --> ACL2-NUMBERP, INTEGERP and RATIONALP
OR --> OR
ORDINALP --> O-P
ORD-LESSP --> O<
PACK --> See intern and coerce.
PAIRLIST --> PAIRLIS$
PLUS --> + and BINARY-+
QUOTIENT --> /
REMAINDER --> REM and MOD
STRIP-CARS --> STRIP-CARS
SUB1 --> 1-
TIMES --> * and BINARY-*
TRUE --> The symbol T.
UNION --> UNION-EQUAL and UNION-EQ
UNPACK --> See symbol-name and coerce.
V&C$ --> No correspondent, but see the documentation for
DEFEVALUATOR and META.
V&C-APPLY$ --> No correspondent, but see the documentation for
DEFEVALUATOR and META.
ZERO --> The number 0.
ZEROP --> ZP
Nqthm commands --> ACL2
----------------------------------------
ACCUMULATED-PERSISTENCE
--> ACCUMULATED-PERSISTENCE
ADD-AXIOM --> DEFAXIOM
ADD-SHELL --> There is no shell principle in ACL2.
AXIOM --> DEFAXIOM
BACKQUOTE-SETTING
--> Backquote is supported in ACL2, but not
currently documented.
BOOT-STRAP --> GROUND-ZERO
BREAK-LEMMA --> MONITOR
BREAK-REWRITE --> BREAK-REWRITE
CH --> PBT
See also :DOC history.
CHRONOLOGY --> PBT
See also :DOC history.
COMMENT --> DEFLABEL
COMPILE-UNCOMPILED-DEFNS
--> COMP
CONSTRAIN --> See :DOC encapsulate and :DOC local.
DATA-BASE --> Perhaps the closest ACL2 analogue of DATA-BASE
is PROPS. But see :DOC history for a collection
of commands for querying the ACL2 database
(``world''). Note that the notions of
supporters and dependents are not supported in
ACL2.
DCL --> DEFSTUB
DEFN --> DEFUN and DEFMACRO
DEFTHEORY --> DEFTHEORY
DISABLE --> DISABLE
DISABLE-THEORY
--> See :DOC theories. The Nqthm command
(DISABLE-THEORY FOO) corresponds roughly to the
ACL2 command
(in-theory (set-difference-theories
(current-theory :here)
(theory 'foo))).
DO-EVENTS --> LD
DO-FILE --> LD
ELIM --> ELIM
ENABLE --> ENABLE
ENABLE-THEORY --> See :DOC theories. The Nqthm command
(ENABLE-THEORY FOO) corresponds roughly to the
ACL2 command
(in-theory (union-theories
(theory 'foo)
(current-theory :here))).
EVENTS-SINCE --> PBT
FUNCTIONALLY-INSTANTIATE
--> ACL2 provides a form of the :USE hint that
corresponds roughly to the
FUNCTIONALLY-INSTANTIATE event of Nqthm. See
:DOC lemma-instance.
GENERALIZE --> GENERALIZE
HINTS --> HINTS
LEMMA --> DEFTHM
MAINTAIN-REWRITE-PATH
--> BRR
MAKE-LIB --> There is no direct analogue of Nqthm's notion of
``library.'' See :DOC books for a description
of ACL2's mechanism for creating and saving
collections of events.
META --> META
NAMES --> NAME
NOTE-LIB --> INCLUDE-BOOK
PPE --> PE
PROVE --> THM
PROVEALL --> See :DOC ld and :DOC certify-book. The latter
corresponds to Nqthm's PROVE-FILE,which may be
what you're interested in,really.
PROVE-FILE --> CERTIFY-BOOK
PROVE-FILE-OUT
--> CERTIFY-BOOK
PROVE-LEMMA --> DEFTHM
See also :DOC hints.
R-LOOP --> The top-level ACL2 loop is an evaluation loop as
well, so no analogue of R-LOOP is necessary.
REWRITE --> REWRITE
RULE-CLASSES --> RULE-CLASSES
SET-STATUS --> IN-THEORY
SKIM-FILE --> LD-SKIP-PROOFSP
TOGGLE --> IN-THEORY
TOGGLE-DEFINED-FUNCTIONS
--> EXECUTABLE-COUNTERPART-THEORY
TRANSLATE --> TRANS and TRANS1
UBT --> UBT and U
UNBREAK-LEMMA --> UNMONITOR
UNDO-BACK-THROUGH
--> UBT
UNDO-NAME --> See :DOC ubt. There is no way to undo names in
ACL2 without undoing back through such names.
However, see :DOC ld-skip-proofsp for
information about how to quickly recover the
state.")
(NTH
(LISTS ACL2-BUILT-INS)
"The nth element (zero-based) of a list
(Nth n l) is the nth element of l, zero-based. If n is greater than
or equal to the length of l, then nth returns nil.
(Nth n l) has a [guard] that n is a non-negative integer and l is a
[true-listp].
Nth is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <nth>
(defun nth (n l)
(declare (xargs :guard (and (integerp n)
(>= n 0)
(true-listp l))))
(if (endp l)
nil
(if (zp n)
(car l)
(nth (- n 1) (cdr l)))))
Subtopics
[Eighth]
Eighth member of the list
[Fifth]
Fifth member of the list
[First]
First member of the list
[Fourth]
Fourth member of the list
[Ninth]
Ninth member of the list
[Nth-aliases-table]
A [table] used to associate names for nth/update-nth printing
[Rest]
Rest ([cdr]) of the list
[Second]
Second member of the list
[Seventh]
Seventh member of the list
[Sixth]
Sixth member of the list
[Tenth]
Tenth member of the list
[Third]
Third member of the list")
(NTH-ALIASES-TABLE
(STOBJ NTH UPDATE-NTH)
"A [table] used to associate names for nth/update-nth printing
Example:
(table nth-aliases-table 'st0 'st)
This example associates the symbol st0 with the symbol st. As a
result, when the theorem prover prints terms of the form (nth n
st0) or (update-nth n val st0), where st is a [stobj] whose nth
accessor function is f-n, then it will print n as *f-n*.
General Form:
(table nth-aliases-table 'alias-name 'name)
This event causes alias-name to be treated like name for purposes of
the printing of terms that are calls of nth and update-nth. (Note
however that name is not recursively looked up in this table.) Both
must be symbols other than [state]. See [term], in particular the
discussion there of untranslated terms.
For a convenient way to add entries to this [table], see
[add-nth-alias]. To remove entries from the [table] with ease, see
[remove-nth-alias].
Subtopics
[Add-nth-alias]
Associate one symbol with another for printing of [nth]/[update-nth]
terms
[Remove-nth-alias]
Remove a symbol alias for printing of [nth]/[update-nth] terms")
(NTHCDR
(LISTS ACL2-BUILT-INS)
"Final segment of a list
(Nthcdr n l) removes the first n elements from the list l.
The following is a theorem.
(implies (and (integerp n)
(<= 0 n)
(true-listp l))
(equal (length (nthcdr n l))
(if (<= n (length l))
(- (length l) n)
0)))
For related functions, see [take] and see [butlast].
The [guard] of (nthcdr n l) requires that n is a nonnegative integer
and l is a true list.
Nthcdr is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <nthcdr>
(defun nthcdr (n l)
(declare (xargs :guard (and (integerp n)
(<= 0 n)
(true-listp l))))
(if (zp n) l (nthcdr (+ n -1) (cdr l))))")
(NULL
(BASICS ACL2-BUILT-INS)
"Recognizer for the empty list
Null is the function that checks whether its argument is nil. For
recursive definitions it is often preferable to test for the end of
a list using [endp] instead of null; see [endp].
Null is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <null>
(defun null (x)
(declare (xargs :guard t))
(eq x nil))")
(NUMBER-SUBTREES
(HONS-AND-MEMOIZATION ACL2-BUILT-INS)
"(number-subtrees x) returns the number of distinct subtrees of X, in
the sense of [equal]
In the logic, number-subtrees is defined as the length of
[cons-subtrees].
Under the hood, we first [hons-copy] X to obtain a normed version,
then count the number of unique conses in X using an EQ hash table.
Function: <number-subtrees>
(defun number-subtrees (x)
(declare (xargs :guard t))
(len (cons-subtrees x 'number-subtrees)))")
(NUMBERS
(PROGRAMMING)
"Numbers in ACL2 and operations on them
See [numbers-introduction] for introductory background. See
[arithmetic] for libraries of [books] for arithmetic reasoning.
Subtopics
[*]
Multiplication macro
[+]
Addition macro
[-]
Macro for subtraction and negation
[/]
Macro for division and reciprocal
[/=]
Test inequality of two numbers
[1+]
Increment by 1
[1-]
Decrement by 1
[<]
Less-than
[<=]
Less-than-or-equal test
[=]
Test equality of two numbers
[>]
Greater-than test
[>=]
Greater-than-or-equal test
[Abs]
The absolute value of a real number
[ACL2-number-listp]
Recognizer for a true list of numbers
[ACL2-numberp]
Recognizer for numbers
[Allocate-fixnum-range]
Set aside fixnums in GCL
[Ash]
Arithmetic shift operation
[Boole$]
Perform a bit-wise logical operation on 2 two's complement integers
[Ceiling]
Division returning an integer by truncating toward positive infinity
[Char-code]
The numeric code for a given character
[Code-char]
The character corresponding to a given numeric code
[Complex]
Create an ACL2 number
[Complex-rationalp]
Recognizes complex rational numbers
[Complex/complex-rationalp]
Recognizer for complex numbers
[Conjugate]
Complex number conjugate
[Denominator]
Divisor of a ratio in lowest terms
[Evenp]
Test whether an integer is even
[Explode-nonnegative-integer]
The list of [characters] in the radix-r form of a number
[Expt]
Exponential function
[Fix]
Coerce to a number
[Floor]
Division returning an integer by truncating toward negative infinity
[Ifix]
Coerce to an integer
[Imagpart]
Imaginary part of a complex number
[Int=]
Test equality of two integers
[Integer-length]
Number of bits in two's complement integer representation
[Integer-listp]
Recognizer for a true list of integers
[Integer-range-p]
Recognizer for integers between two bounds.
[Integerp]
Recognizer for whole numbers
[Logand]
Bitwise logical `and' of zero or more integers
[Logandc1]
Bitwise logical `and' of two ints, complementing the first
[Logandc2]
Bitwise logical `and' of two ints, complementing the second
[Logbitp]
The ith bit of an integer
[Logcount]
Number of ``on'' bits in a two's complement number
[Logeqv]
Bitwise logical equivalence of zero or more integers
[Logior]
Bitwise logical inclusive or of zero or more integers
[Lognand]
Bitwise logical `nand' of two integers
[Lognor]
Bitwise logical `nor' of two integers
[Lognot]
Bitwise not of a two's complement number
[Logorc1]
Bitwise logical inclusive or of two ints, complementing the first
[Logorc2]
Bitwise logical inclusive or of two ints, complementing the second
[Logtest]
Test if two integers share a `1' bit
[Logxor]
Bitwise logical exclusive or of zero or more integers
[Max]
The larger of two numbers
[Min]
The smaller of two numbers
[Minusp]
Test whether a number is negative
[Mod]
Remainder using [floor]
[Mod-expt]
Exponential function
[Nat-listp]
Recognizer for a true list of natural numbers
[Natp]
A recognizer for the natural numbers
[Nfix]
Coerce to a natural number
[Nonnegative-integer-quotient]
Natural number division function
[Numbers-introduction]
Numbers in ACL2
[Numerator]
Dividend of a ratio in lowest terms
[Oddp]
Test whether an integer is odd
[Plusp]
Test whether a number is positive
[Posp]
A recognizer for the positive integers
[Random$]
Obtain a random value
[Rational-listp]
Recognizer for a true list of rational numbers
[Rationalp]
Recognizer for rational numbers (ratios and integers)
[Real/rationalp]
Recognizer for rational numbers (including real number in ACL2(r))
[Realfix]
Coerce to a real number
[Realpart]
Real part of a complex number
[Rem]
Remainder using [truncate]
[Rfix]
Coerce to a rational number
[Round]
Division returning an integer by rounding off
[Sharp-u-reader]
Allow underscore characters in numbers
[Signed-byte-p]
Recognizer for signed integers that fit in a specified bit width
[Signum]
Indicator for positive, negative, or zero
[Truncate]
Division returning an integer by truncating toward 0
[Unary--]
Arithmetic negation function
[Unary-/]
Reciprocal function
[Unsigned-byte-p]
Recognizer for natural numbers that fit in a specified bit width
[Zero-test-idioms]
How to test for 0
[Zerop]
Test an acl2-number against 0
[Zip]
Testing an ``integer'' against 0
[Zp]
Testing a ``natural'' against 0
[Zpf]
Testing a nonnegative fixnum against 0")
(NUMBERS-INTRODUCTION
(NUMBERS)
"Numbers in ACL2
ACL2 numbers are precisely represented and unbounded. They can be
partitioned into the following subtypes:
ACL2 Numbers
|
|- Rationals
| |
| |- Integers
| | |- Positive integers 3
| | |- Zero 0
| | |- Negative Integers -3
| |
| |- Non-Integral Rationals
| | |
| | |- Positive Non-Integral Rationals 19/3
| | |- Negative Non-Integral Rationals -22/7
|
|- Complex Rational Numbers #c(3 5/2) ; i.e., 3 + (5/2)i
Signed integer constants are usually written (as illustrated above)
as sequences of decimal digits, possibly preceded by + or -.
Decimal points are not allowed. Integers may be written in binary,
as in #b1011 (= 23) and #b-111 (= -7). Octal may also be used,
#o-777 = -511. Non-integral rationals are written as a signed
decimal integer and an unsigned decimal integer, separated by a
slash. Complex rationals are written as #c(rpart ipart) where rpart
and ipart are rationals.
Of course, 4/2 = 2/1 = 2 (i.e., not every rational written with a
slash is a non-integer). Similarly, #c(4/2 0) = #c(2 0) = 2.
The common arithmetic functions and relations are denoted by +, -, *,
/, =, <, <=, > and >=. However there are many others, e.g., floor,
ceiling, and lognot. See any Common Lisp language documentation.
The primitive predicates for recognizing numbers are illustrated
below. The following ACL2 function will classify an object, x,
according to its numeric subtype, or else return 'NaN (not a
number). We show it this way just to illustrate programming in
ACL2.
(defun classify-number (x)
(cond ((rationalp x)
(cond ((integerp x)
(cond ((< 0 x) 'positive-integer)
((= 0 x) 'zero)
(t 'negative-integer)))
((< 0 x) 'positive-non-integral-rational)
(t 'negative-non-integral-rational)))
((complex-rationalp x) 'complex-rational)
(t 'NaN)))")
(NUMBERS_IN_ACL2
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Numbers in ACL2
ACL2 numbers are precisely represented and unbounded. They can be
partitioned into the following subtypes:
ACL2 Numbers
|
|- Rationals
| |
| |- Integers
| | |- Positive integers 3
| | |- Zero 0
| | |- Negative Integers -3
| |
| |- Non-Integral Rationals
| | |
| | |- Positive Non-Integral Rationals 19/3
| | |- Negative Non-Integral Rationals -22/7
|
|- Complex Rational Numbers #c(3 5/2) ; i.e., 3 + (5/2)i
Signed integer constants are usually written (as illustrated above)
as sequences of decimal digits, possibly preceded by + or -.
Decimal points are not allowed. Integers may be written in binary,
as in #b1011 (= 23) and #b-111 (= -7). Octal may also be used,
#o-777 = -511. Non-integral rationals are written as a signed
decimal integer and an unsigned decimal integer, separated by a
slash. Complex rationals are written as #c(rpart ipart) where rpart
and ipart are rationals.
Of course, 4/2 = 2/1 = 2 (i.e., not every rational written with a
slash is a non-integer). Similarly, #c(4/2 0) = #c(2 0) = 2.
The common arithmetic functions and relations are denoted by +, -, *,
/, =, <, <=, > and >=. However there are many others, e.g., floor,
ceiling, and lognot. See any Common Lisp language documentation.
The primitive predicates for recognizing numbers are illustrated
below. The following ACL2 function will classify an object, x,
according to its numeric subtype, or else return 'NaN (not a
number). We show it this way just to illustrate programming in
ACL2.
(defun classify-number (x)
(cond ((rationalp x)
(cond ((integerp x)
(cond ((< 0 x) 'positive-integer)
((= 0 x) 'zero)
(t 'negative-integer)))
((< 0 x) 'positive-non-integral-rational)
(t 'negative-non-integral-rational)))
((complex-rationalp x) 'complex-rational)
(t 'NaN)))")
(NUMERATOR
(NUMBERS ACL2-BUILT-INS)
"Dividend of a ratio in lowest terms
Completion Axiom (completion-of-numerator):
(equal (numerator x)
(if (rationalp x)
(numerator x)
0))
[Guard] for (numerator x):
(rationalp x)")
(O-FINP
(ORDINALS ACL2-BUILT-INS)
"Recognizes if an ordinal is finite
We introduce the function o-finp which returns t for any ordinal that
is finite, else nil. This function is equivalent to the function
[atom], and is introduced so that we can [disable] its definition
when dealing with ordinals (also see [make-ord]).
Function: <o-finp>
(defun o-finp (x)
(declare (xargs :guard t))
(atom x))")
(O-FIRST-COEFF
(ORDINALS ACL2-BUILT-INS)
"Returns the first coefficient of an ordinal
An ACL2 ordinal is either a natural number or, for an infinite
ordinal, a list whose elements are exponent-coefficient pairs (see
[o-p]). In the latter case, this function returns the [cdr] of the
first pair in the list. In the case of a natural number, this
function returns the ordinal itself (since a natural number, n, can
be thought of as (w^0)n).
For the corresponding exponent, see [o-first-expt].
Function: <o-first-coeff>
(defun o-first-coeff (x)
(declare (xargs :guard (or (o-finp x) (consp (car x)))))
(if (o-finp x) x (cdar x)))")
(O-FIRST-EXPT
(ORDINALS ACL2-BUILT-INS)
"The first exponent of an ordinal
An ACL2 ordinal is either a natural number or, for an infinite
ordinal, a list whose elements are exponent-coefficient pairs (see
[o-p]). In the latter case, this function returns the [car] of the
first pair in the list. In the case of a natural number, the value
returned is 0 (since a natural number, n, can be thought of as
(w^0)n).
For the corresponding coefficient, see [o-first-coeff].
Function: <o-first-expt>
(defun o-first-expt (x)
(declare (xargs :guard (or (o-finp x) (consp (car x)))))
(if (o-finp x) 0 (caar x)))")
(O-INFP
(ORDINALS ACL2-BUILT-INS)
"Recognizes if an ordinal is infinite
O-infp is a macro. (O-infp x) opens up to (not (o-finp x)).")
(O-P
(ORDINALS ACL2-BUILT-INS)
"A recognizer for the ordinals up to epsilon-0
Using the nonnegative integers and lists we can represent the
ordinals up to epsilon-0. The ordinal representation used in ACL2
has changed as of Version_2.8 from that of Nqthm-1992, courtesy of
Pete Manolios and Daron Vroon; additional discussion may be found
in ``Ordinal Arithmetic in ACL2'', {proceedings of ACL2 Workshop
2003 | http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/}.
Previously, ACL2's notion of ordinal was very similar to the
development given in ``New Version of the Consistency Proof for
Elementary Number Theory'' in The Collected Papers of Gerhard
Gentzen, ed. M.E. Szabo, North-Holland Publishing Company,
Amsterdam, 1969, pp 132-213.
The following essay is intended to provide intuition about ordinals.
The truth, of course, lies simply in the ACL2 definitions of o-p
and [o<].
Very intuitively, think of each non-zero natural number as by being
denoted by a series of the appropriate number of strokes, i.e.,
0 0
1 |
2 ||
3 |||
4 ||||
... ...
Then ``omega,'' here written as w, is the ordinal that might be
written as
w |||||...,
i.e., an infinite number of strokes. Addition here is just
concatenation. Observe that adding one to the front of w in the
picture above produces w again, which gives rise to a standard
definition of w: w is the least ordinal such that adding another
stroke at the beginning does not change the ordinal.
We denote by w+w or w*2 the ``doubly infinite'' sequence that we
might write as follows.
w*2 |||||... |||||...
One way to think of w*2 is that it is obtained by replacing each
stroke in 2 (||) by w. Thus, one can imagine w*3, w*4, etc., which
leads ultimately to the idea of ``w*w,'' the ordinal obtained by
replacing each stroke in w by w. This is also written as ``omega
squared'' or w^2, or:
2
w |||||... |||||... |||||... |||||... |||||... ...
We can analogously construct w^3 by replacing each stroke in w by w^2
(which, it turns out, is the same as replacing each stroke in w^2
by w). That is, we can construct w^3 as w copies of w^2,
3 2 2 2 2
w w ... w ... w ... w ... ...
Then we can construct w^4 as w copies of w^3, w^5 as w copies of w^4,
etc., ultimately suggesting w^w. We can then stack omegas, i.e.,
(w^w)^w etc. Consider the ``limit'' of all of those stacks, which
we might display as follows.
.
.
.
w
w
w
w
w
That is epsilon-0.
Below we begin listing some ordinals up to epsilon-0; the reader can
fill in the gaps at his or her leisure. We show in the left column
the conventional notation, using w as ``omega,'' and in the right
column the ACL2 object representing the corresponding ordinal.
ordinal ACL2 representation
0 0
1 1
2 2
3 3
... ...
w '((1 . 1) . 0)
w+1 '((1 . 1) . 1)
w+2 '((1 . 1) . 2)
... ...
w*2 '((1 . 2) . 0)
(w*2)+1 '((1 . 2) . 1)
... ...
w*3 '((1 . 3) . 0)
(w*3)+1 '((1 . 3) . 1)
... ...
2
w '((2 . 1) . 0)
... ...
2
w +w*4+3 '((2 . 1) (1 . 4) . 3)
... ...
3
w '((3 . 1) . 0)
... ...
w
w '((((1 . 1) . 0) . 1) . 0)
... ...
w 99
w +w +w4+3 '((((1 . 1) . 0) . 1) (99 . 1) (1 . 4) . 3)
... ...
2
w
w '((((2 . 1) . 0) . 1) . 0)
... ...
w
w
w '((((((1 . 1) . 0) . 1) . 0) . 1) . 0)
... ...
Observe that the sequence of o-ps starts with the natural numbers
(which are recognized by [natp]). This is convenient because it
means that if a term, such as a measure expression for justifying a
recursive function (see [o<]) must produce an o-p, it suffices for
it to produce a natural number.
The ordinals listed above are listed in ascending order. This is the
ordering tested by [o<].
The ``epsilon-0 ordinals'' of ACL2 are recognized by the recursively
defined function o-p. The base case of the recursion tells us that
natural numbers are epsilon-0 ordinals. Otherwise, an epsilon-0
ordinal is a list of [cons] pairs whose final [cdr] is a natural
number, ((a1 . x1) (a2 . x2) ... (an . xn) . p). This corresponds
to the ordinal (w^a1)x1 + (w^a2)x2 + ... + (w^an)xn + p. Each ai is
an ordinal in the ACL2 representation that is not equal to 0. The
sequence of the ai's is strictly decreasing (as defined by [o<]).
Each xi is a positive integer (as recognized by [posp]).
Note that infinite ordinals should generally be created using the
ordinal constructor, [make-ord], rather than [cons]. The functions
[o-first-expt], [o-first-coeff], and [o-rst] are ordinals
destructors. Finally, the function [o-finp] and the macro [o-infp]
tell whether an ordinal is finite or infinite, respectively.
The function [o<] compares two epsilon-0 ordinals, x and y. If both
are integers, (o< x y) is just x<y. If one is an integer and the
other is a [cons], the integer is the smaller. Otherwise, [o<]
recursively compares the [o-first-expt]s of the ordinals to
determine which is smaller. If they are the same, the
[o-first-coeff]s of the ordinals are compared. If they are equal,
the [o-rst]s of the ordinals are recursively compared.
Fundamental to ACL2 is the fact that [o<] is well-founded on
epsilon-0 ordinals. That is, there is no ``infinitely descending
chain'' of such ordinals. See [proof-of-well-foundedness].
Function: <o-p>
(defun o-p (x)
(declare (xargs :guard t))
(if (o-finp x)
(natp x)
(and (consp (car x))
(o-p (o-first-expt x))
(not (eql 0 (o-first-expt x)))
(posp (o-first-coeff x))
(o-p (o-rst x))
(o< (o-first-expt (o-rst x))
(o-first-expt x)))))")
(O-RST
(ORDINALS ACL2-BUILT-INS)
"Returns the rest of an infinite ordinal
An ACL2 infinite ordinal is a list whose elements are
exponent-coefficient pairs (see [o-p] and see [o-infp]). The first
exponent and first coefficient of an ordinal can be obtained by
using [o-first-expt] and [o-first-coeff] respectively. To obtain
the rest of the ordinal (for recursive analysis), use the o-rst
function. It returns the rest of the ordinal after the first
exponent and coefficient are removed.
Function: <o-rst>
(defun o-rst (x)
(declare (xargs :guard (consp x)))
(cdr x))")
(O<
(ORDINALS ACL2-BUILT-INS)
"The well-founded less-than relation on ordinals up to epsilon-0
If x and y are both o-ps (see [o-p]) then (o< x y) is true iff x is
strictly less than y. o< is well-founded on the [o-p]s. When x and
y are both nonnegative integers, o< is just the familiar ``less
than'' relation ([<]).
o< plays a key role in the formal underpinnings of the ACL2 logic. In
order for a recursive definition to be admissible it must be proved
to ``terminate.'' By terminate we mean that the arguments to the
function ``get smaller'' as the function recurses and this sense of
size comparison must be such that there is no ``infinitely
descending'' sequence of ever smaller arguments. That is, the
relation used to compare successive arguments must be well-founded
on the domain being measured.
The most basic way ACL2 provides to prove termination requires the
user to supply (perhaps implicitly) a mapping of the argument
tuples into the ordinals with some ``measure'' expression in such a
way that the measures of the successive argument tuples produced by
recursion decrease according to the relation o<. The validity of
this method rests on the well-foundedness of o< on the [o-p]s.
Without loss of generality, suppose the definition in question
introduces the function f, with one formal parameter x (which might
be a list of objects). Then we require that there exist a measure
expression, (m x), that always produces an [o-p]. Furthermore,
consider any recursive call, (f (d x)), in the body of the
definition. Let hyps be the conjunction of terms, each of which is
either the test of an [if] in the body or else the negation of such
a test, describing the path through the body to the recursive call
in question. Then it must be a theorem that
(IMPLIES hyps (O< (m (d x)) (m x))).
When we say o< is ``well-founded'' on the [o-p]s we mean that there
is no infinite sequence of [o-p]s such that each is smaller than
its predecessor in the sequence. Thus, the theorems that must be
proved about f when it is introduced establish that it cannot recur
forever because each time a recursive call is taken (m x) gets
smaller. From this, and the syntactic restrictions on definitions,
it can be shown (as on page 44 in ``A Computational Logic'', Boyer
and Moore, Academic Press, 1979) that there exists a function
satisfying the definition; intuitively, the value assigned to any
given x by the alleged function is that computed by a sufficiently
large machine. Hence, the logic is consistent if the axiom defining
f is added.
See [o-p] for a discussion of the ordinals and how to compare two
ordinals.
The definitional principle permits the use of relations other than o<
but they must first be proved to be well-founded on some domain.
See [well-founded-relation]. Roughly put, alternative relations are
shown well-founded by providing an order-preserving mapping from
their domain into the ordinals. See [defun] for details on how to
specify which well-founded relation is to be used.
Function: <o<>
(defun o< (x y)
(declare (xargs :guard (and (o<g x) (o<g y))))
(cond ((o-finp x) (or (o-infp y) (< x y)))
((o-finp y) nil)
((not (equal (o-first-expt x)
(o-first-expt y)))
(o< (o-first-expt x) (o-first-expt y)))
((not (= (o-first-coeff x) (o-first-coeff y)))
(< (o-first-coeff x) (o-first-coeff y)))
(t (o< (o-rst x) (o-rst y)))))")
(O<=
(ORDINALS ACL2-BUILT-INS)
"The less-than-or-equal relation for the ordinals
o<= is a macro and (o<= x y) expands to (not (o< y x)). See [o<].")
(O>
(ORDINALS ACL2-BUILT-INS)
"The greater-than relation for the ordinals
O> is a macro and (o> x y) expands to (o< y x). See [o<].")
(O>=
(ORDINALS ACL2-BUILT-INS)
"The greater-than-or-equal relation for the ordinals
O>= is a macro and (o>= x y) expands to (not (o< x y)). See [o<].")
(OBDD
(BDD)
"Ordered binary decision diagrams with rewriting
See [bdd] for information on this topic.")
(OBSERVATION
(IO ACL2-BUILT-INS)
"Print an observation
Here is a typical application of observation.
ACL2 !>(let ((ctx 'top-level)
(name 'foo))
(observation ctx
\"Skipping processing of name ~x0.\"
name))
ACL2 Observation in TOP-LEVEL: Skipping processing of name FOO.
<state>
ACL2 !>
Observation prints an initial ``ACL2 Observation...: '', and then
prints the indicated message using formatted printing (see [fmt]).
Notice in the example above that evaluation of a call of
observation returns [state]. Indeed, observation is actually a
macro whose expansion takes and returns the ACL2 [state]. A similar
utility, observation-cw, is available that does not take or return
state; rather, it returns nil as the suffix ``cw'' suggests that a
``comment window'' is the target of this printing, rather than the
state. For example:
ACL2 !>(let ((ctx 'top-level)
(name 'foo))
(observation-cw ctx
\"Skipping processing of name ~x0.\"
name))
ACL2 Observation in TOP-LEVEL: Skipping processing of name FOO.
NIL
ACL2 !>
Observation-cw takes exactly the same arguments as observation, but
observation-cw does its printing in a so-called ``wormhole''; see
[wormhole].
General Forms:
(observation ctx fmt-string fmt-arg1 fmt-arg2 ... fmt-argk)
(observation-cw ctx fmt-string fmt-arg1 fmt-arg2 ... fmt-argk)
where ctx generally evaluates to a symbol (but see below), and
fmt-string together with the fmt-argi are suitable for passing to
[fmt]. Output begins and ends with a newline.
Recall from the example above that the output from a call of
observation (or observation-cw) begins with ``ACL2 Observation''
and additional characters ending in ``: '', for example `` in
TOP-LEVEL: '', followed by formatted output produced from
fmt-string with the given fmt-argi. The characters printed
immediately following the string ``ACL2 Observation'' depend on the
value of ctx. If ctx is nil, nothing is printed. If ctx is a
non-nil symbol, it is printed using [fmt] directive ~x. If ctx is a
[cons] pair whose [car] is a symbol, formatted printing is applied
to the string \"(~x0 ~x1 ...)\", where #\\0 and #\\1 are bound
respectively to that car and cdr. Otherwise, ctx is printed using
[fmt] directive ~@.
We next discuss situations in which printing is inhibited for
observation and observation-cw. No printing is done when
observation is among the inhibited output types; see
[set-inhibit-output-lst]. Moreover, no printing is done by
observation during [include-book]. If you want to avoid printing
from observation-cw during [include-book], then you need to manage
that yourself.")
(OBSERVATION-CW (POINTERS)
"See [observation].")
(ODDP
(NUMBERS ACL2-BUILT-INS)
"Test whether an integer is odd
(oddp x) is true if and only if x is odd, i.e., not even in the sense
of [evenp].
The [guard] for oddp requires its argument to be an integer.
Oddp is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <oddp>
(defun oddp (x)
(declare (xargs :guard (integerp x)))
(not (evenp x)))")
(OK-IF
(BREAK-REWRITE)
"Conditional exit from break-rewrite
Example Form:
:ok-if (null (brr@ :wonp))
General Form:
:ok-if expr
where expr is a term involving no free variables other than state and
returning one non-state result which is treated as Boolean. This
form is intended to be executed from within break-rewrite (see
[break-rewrite]).
Consider first the simple situation that the (ok-if term) is a
command read by break-rewrite. Then, if the term is non-nil,
break-rewrite exits and otherwise it does not.
More generally, ok-if returns an ACL2 error triple (mv erp val
state). (See [ld] or see [programming-with-state] for more on error
triples.) If any form being evaluated as a command by break-rewrite
returns the triple returned by (ok-if term) then the effect of that
form is to exit [break-rewrite] if term is non-nil. Thus, one might
define a function or macro that returns the value of ok-if
expressions on all outputs and thus create a convenient new way to
exit break-rewrite.
The exit test, term, generally uses brr@ to access context sensitive
information about the attempted rule application. See [brr@]. Ok-if
is useful inside of command sequences produced by break conditions.
See [monitor]. :ok-if is most useful after an :eval command has
caused break-rewrite to try to apply the rule because in the
resulting break environment expr can access such things as whether
the rule succeeded, if so, what term it produced, and if not, why.
There is no need to use :ok-if before :evaling the rule since the
same effects could be achieved with the break condition on the rule
itself. Perhaps we should replace this concept with
:eval-and-break-if? Time will tell.")
(ON_THE_NAMING_OF_SUBGOALS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"On the Naming of Subgoals
Subgoal *1/2 is the induction step from the scheme, obtained by
instantiating the scheme with our conjecture.
We number the cases ``backward'', so this is case ``2'' of the proof
of ``*1''. We number them backward so you can look at a subgoal
number and get an estimate for how close you are to the end.")
(OOPS
(HISTORY)
"Undo a :u or :[ubt]
The keyword [command] :oops will undo the most recent :[ubt] (or :u,
which we here consider just another :[ubt]). A second :oops will
undo the next most recent :[ubt], a third will undo the :[ubt]
before that one, and a fourth :oops will return the logical [world]
to its configuration before the first :oops.
Consider the logical world (see [world]) that represents the current
extension of the logic and ACL2's rules for dealing with it. The
:[ubt] and :u [command]s ``roll back'' to some previous [world]
(see [ubt]). Sometimes these [command]s are used to inadvertently
undo useful work and user's wish they could ``undo the last undo.''
That is the function provided by :oops.
:Oops is best described in terms of an implementation. Imagine a ring
of four [world]s and a marker (*) indicating the current ACL2
[world]:
*
w0
/ \\
w3 w1
\\ /
w2
This is called the ``kill ring'' and it is maintained as follows.
When you execute an event the current [world] is extended and the
kill ring is not otherwise affected. When you execute :[ubt] or :u,
the current [world] marker is moved one step counterclockwise and
that [world] in the ring is replaced by the result, say w0', of the
:[ubt] or :u.
w0
/ \\
*w0' w1
\\ /
w2
If you were to execute [events] at this point, w0' would be extended
and no other changes would occur in the kill ring.
When you execute :oops, the marker is moved one step clockwise. Thus
the kill ring becomes
*
w0
/ \\
w0' w1
\\ /
w2
and the current ACL2 [world] is w0 once again. That is, :oops
``undoes'' the :[ubt] that produced w0' from w0. Similarly, a
second :oops will move the marker to w1, undoing the undo that
produced w0 from w1. A third :oops makes w2 the current [world].
Note however that a fourth :oops restores us to the configuration
previously displayed above in which w0' has the marker.
In general, the kill ring contains the current [world] and the three
most recent [world]s in which a :[ubt] or :u were done.
While :[ubt] may appear to discard the information in the [events]
undone, we can see that the [world] in which the :[ubt] occurred is
still available. No information has been lost about that [world].
But :[ubt] does discard information! :[Ubt] discards the
information necessary to recover from the third most recent [ubt]!
An :oops, on the other hand, discards no information, it just
selects the next available [world] on the kill ring and doing
enough :oopses will return you to your starting point.
We can put this another way. You can freely type :oops and inspect
the [world] that you thus obtain with :[pe], :[pc], and other
[history] [command]s. You can repeat this as often as you wish
without risking the permanent loss of any information. But you must
be more careful typing :[ubt] or :u. While :oops makes :[ubt] seem
``safe'' because the most recent :[ubt] can always be undone,
information is lost when you execute :[ubt].
We note that :ubt and :u may remove compiled definitions (but note
that in some Lisps, including CCL (OpenMCL) and SBCL, functions are
always compiled). When the original world is restored using :oops,
restored functions will not generally be compiled (except for Lisps
as above), though the user can remedy this situation; see [comp].
Finally, we note that our implementation of oops can use a
significant amount of memory, because of the saving of old logical
[world]s. Most users are unlikely to experience a memory problem,
but if you do, then you may want to disable oops by evaluting
(reset-kill-ring 0 state); see [reset-kill-ring].")
(OPEN-INPUT-CHANNEL (POINTERS)
"See [io].")
(OPEN-INPUT-CHANNEL-P (POINTERS)
"See [io].")
(OPEN-OUTPUT-CHANNEL (POINTERS)
"See [io].")
(OPEN-OUTPUT-CHANNEL!
(IO ACL2-BUILT-INS)
"When trust tags are needed to open output channels
Use this function in place of open-output-channel if you want to open
a channel for output at times this would otherwise be prohibited,
for example during [make-event] expansion and [clause-processor]
[hints]. If this functionality doesn't quite seem like what you
need, take a look at the definition of open-output-channel! in
axioms.lisp, specifically the binding of [state] global variable
writes-okp. The following example, taken from (no longer available)
community book books/hons-archive/hons-archive.lisp, illustrates
the latter approach.
(defmacro har-zip! (x filename &key sortp)
\"See :doc hons-archive\"
`(mv-let (erp val state)
(progn!
:state-global-bindings
((temp-touchable-vars t set-temp-touchable-vars))
(state-global-let*
((writes-okp t))
(let ((state (har-zip-fn ,x ,filename ,sortp state)))
(mv nil nil state))))
(declare (ignore erp val))
state))
The book below illustrates the soundness loophole plugged in ACL2
Version_3.2 related to file writes during book certification.
; The following example is adapted (with only very slight changes)
; from one written by Peter Dillinger. It illustrates the prohibition
; against writing files enforced by with-output-channel during book
; certification (more specifically, during make-event expansion).
; This book certifies in ACL2 Version_3.1 before the fix discussed in the
; paragraph about it being ``possible to write files during book
; certification'' in :DOC NOTE-3-2. The fix was actually made to ACL2
; function open-output-channel.
; After the fix, in order for certification to succeed one needs to do
; two things. First, in raw lisp:
; (push :after-writes-okp-fix *features*)
; Second, certify with this command:
; (certify-book \"writes-okp\" 0 nil :ttags (:writes-okp))
(in-package \"ACL2\")
(local
(defun write-objects-to-channel (obj-lst chan state)
(declare (xargs :mode :program
:stobjs state
:guard (true-listp obj-lst)))
(if (consp obj-lst)
(pprogn (print-object$ (car obj-lst) chan state)
(write-objects-to-channel (cdr obj-lst) chan state)
state)
state)))
#+after-writes-okp-fix
(defttag :writes-okp)
(local
(defun write-objects-to-file (obj-lst filename state)
(declare (xargs :mode :program
:stobjs state
:guard (and (stringp filename)
(true-listp obj-lst))))
(mv-let (chan state)
#-after-writes-okp-fix
(open-output-channel filename :object state)
#+after-writes-okp-fix
(open-output-channel! filename :object state)
(if chan
(pprogn (write-objects-to-channel obj-lst chan state)
(close-output-channel chan state)
(value :done))
(er soft 'write-object-to-file
\"Could not open for writing: ~x0\"
filename)))))
(local
(defconst *nil.lisp*
'((in-package \"ACL2\")
(defthm bad nil :rule-classes nil))))
(local
(defconst *nil.cert*
'((IN-PACKAGE \"ACL2\")
\"ACL2 Version 3.1\"
:BEGIN-PORTCULLIS-CMDS
:END-PORTCULLIS-CMDS
NIL
((\"/home/peterd/test/nil.lisp\" \"nil\" \"nil\"
((:SKIPPED-PROOFSP) (:AXIOMSP) (:TTAGS)) . 134094174))
62589544
)))
(local
(make-event (er-progn
(write-objects-to-file *nil.lisp* \"nil.lisp\" state)
(write-objects-to-file *nil.cert* \"nil.cert\" state)
(value '(value-triple :invisible)))))
(local (include-book
\"nil\" :load-compiled-file nil))
(defthm bad nil :rule-classes nil)")
(OPEN-OUTPUT-CHANNEL-P (POINTERS)
"See [io].")
(OPEN-TRACE-FILE
(TRACE)
"Redirect trace output to a file
Example:
(open-trace-file \"foo\") ; trace output will go to file foo
General Form:
(open-trace-file filename) ; trace output will go to file filename
Output from [trace$] normally goes to the screen, i.e.,
[standard-co]. But it can be redirected to a file as shown above.
See [close-trace-file] for how to send trace output back to the
screen.")
(OPTIMIZE (POINTERS) "See [declare].")
(OR
(BASICS ACL2-BUILT-INS)
"Disjunction
Or is the macro for disjunctions. Or takes any number of arguments
and returns the first that is non-nil, or nil if there is no
non-nil element.
In the ACL2 logic, the macroexpansion of (or x y) is an IF term that
appears to cause x to be evaluated twice:
ACL2 !>:trans (or x y)
(IF X X Y)
=> *
ACL2 !>
If x were replaced by an expression whose evaluation takes a long
time, then such an expansion would be ineffecient. However, don't
be fooled: you can expect Common Lisp implementations to avoid this
problem, say by generating a new variable, for example:
ACL2 !>:q ; Exit the ACL2 loop and go into raw Common Lisp
Exiting the ACL2 read-eval-print loop. To re-enter, execute (LP).
ACL2>(macroexpand '(or x y))
(LET ((#:G5374 X)) (IF #:G5374 #:G5374 Y))
T
ACL2>
Or is a Common Lisp macro. See any Common Lisp documentation for more
information.
Macro: <or>
(defmacro or (&rest args)
(or-macro args))
Function: <or-macro>
(defun or-macro (lst)
(declare (xargs :guard t))
(if (consp lst)
(if (consp (cdr lst))
(list 'if
(car lst)
(car lst)
(or-macro (cdr lst)))
(car lst))
nil))")
(ORACLE-APPLY
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Call a function argument on the given list of arguments
Oracle-apply evaluates its first argument to produce an ACL2 function
symbol, FN, and then applies FN to the value of the second
argument, which should be a true list whose length is the number of
inputs for FN. The return value is of the form (mv call-result
state).
Examples:
(oracle-apply 'cons '(3 4) state) = (mv '(3 . 4) <state>)
(oracle-apply (car '(floor foo)) (list (+ 6 7) 5) state) = (mv 2 <state>)
Also see [oracle-funcall] for a related utility.
Note that calls of oracle-funcall and oracle-apply return two values:
the result of the function application, and a modified [state].
Oracle-apply is defined in :[logic] mode, and in fact is
[guard]-verified. However, you will not be able to prove much about
this function, because it is defined in the logic using the
acl2-oracle field of the ACL2 [state]; see [read-ACL2-oracle]. The
behavior described above --- i.e., making a function call --- takes
place when the third argument is the ACL2 [state], so during proofs
(when that can never happen), a term (oracle-apply 'fn '...) will
not simplify using a call of fn.
The guard for (oracle-apply fn args state) is the term
(oracle-apply-guard fn args state), which we describe below.
Function: <oracle-apply-guard>
(defun oracle-apply-guard (fn args state)
(declare (xargs :stobjs state))
(and (f-boundp-global 'temp-touchable-fns
state)
(ev-fncall-w-guard fn args (w state)
(f-get-global 'temp-touchable-fns
state))))
where:
Function: <ev-fncall-w-guard>
(defun
ev-fncall-w-guard
(fn args wrld temp-touchable-fns)
(declare (xargs :guard t))
(and
(plist-worldp wrld)
(symbolp fn)
(not (eq fn 'if))
(not (assoc-eq fn *ttag-fns-and-macros*))
(true-listp args)
(let* ((formals (getpropc fn 'formals t wrld))
(stobjs-in (stobjs-in fn wrld))
(untouchable-fns (global-val 'untouchable-fns wrld)))
(and (not (eq formals t))
(eql (len formals) (len args))
(true-listp untouchable-fns)
(or (not (member-eq fn untouchable-fns))
(and temp-touchable-fns
(or (eq t temp-touchable-fns)
(and (true-listp temp-touchable-fns)
(member-eq fn temp-touchable-fns)))))
(not (and (null formals)
(getpropc fn 'stobj-function nil wrld)))
(true-listp stobjs-in)
(all-nils stobjs-in)))))
These definitions say that fn is a function symbol other than if; it
is not among the keys of the alist, *ttag-fns-and-macros*; and it
does not take or create a [stobj] (see [defstobj]). Moreover, the
second argument, args, must be a true list whose length is the
number of formal parameters of fn. These requirements may be a bit
onerous for guard verification of functions that call oracle-apply,
but this is easily overcome by using [ec-call], for example as
follows.
(defun f (x state)
(declare (xargs :stobjs state))
(ec-call (oracle-apply 'car (list x) state)))
This use of [ec-call] will, however, cause the [guard] of
oracle-apply to be checked at runtime.
If the [guard] for oracle-apply fails to hold but there is no guard
violation because guard-checking is suppressed (see
[set-guard-checking]), then the value returned is computed using
its logical definition --- which, as mentioned above, uses the ACL2
oracle --- and hence the value computed is unpredictable (indeed,
the function argument will not actually be called).
The value returned by oracle-apply is always a single value obtained
by calling the executable counterpart of its function argument, as
we now explain. Consider a form (oracle-apply fn args state) that
evaluates to (mv VAL state'), where fn evaluates to the function
symbol F. If F returns multiple values, then VAL is the first value
computed by the call of F on the value of args. More precisely,
oracle-apply actually invokes the executable counterpart of F;
thus, if args is the expression (list x1 ... xk), then VAL is the
same as (first) value returned by evaluating (ec-call (F x1 x2 ...
xk)). See [ec-call].
(Remark. If you identify a need for a version of oracle-apply to
return multiple values, we can perhaps provide such a utility; feel
free to contact the ACL2 implementors to request it.)
A subtlety is that the evaluation takes place in so-called ``safe
mode'', which avoids raw Lisp errors due to calls of :[program]
mode functions. The use of safe mode is unlikely to be noticed if
the value of the first argument of oracle-apply is a :[logic] mode
function symbol. However, for :program mode functions with side
effects due to special raw Lisp code, as may be the case for
built-in functions or for custom functions defined with active
trust tags (see [defttag]), use of the function [oracle-apply-raw]
may be preferable. It is a much less restrictive version of
oracle-apply, which avoids safe mode and (for example) can apply a
function that has a definition in the host Lisp but not in the ACL2
[world].
Function: <oracle-apply>
(defun oracle-apply (fn args state)
(declare (xargs :stobjs state
:guard (oracle-apply-guard fn args state)))
(mv-let (erp val state)
(read-acl2-oracle state)
(declare (ignore erp))
(mv (and (true-listp val)
(eq (car val) fn)
(equal (cadr val) args)
(caddr val))
state)))")
(ORACLE-APPLY-RAW
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Call a function argument on the given list of arguments, no
restrictions
See [oracle-apply], as we assume familiarity with that function.
Oracle-apply-raw is a variant of oracle-apply that is untouchable,
and hence requires a trust tag to remove the untouchability (see
[defttag] and see [remove-untouchable]). Unlike oracle-apply,
oracle-apply-raw simply calls the raw Lisp function funcall to
compute the result, without restriction: the specified :[guard] is
t, the function itself is applied (not its executable counterpart),
there is no restriction for untouchable functions or [return-last],
and safe mode is not used. Thus, in general, oracle-apply-raw can
be dangerous to use: any manner of error can occur!
As is the case for [oracle-apply], the function symbol
[oracle-apply-raw] is defined in :[logic] mode and is
[guard]-verified. Oracle-apply-raw is logically defined to be
[oracle-apply]; more precisely:
(oracle-apply-raw fn args state)
= {logical definition}
(ec-call (oracle-apply fn args state))
Function: <oracle-apply-raw>
(defun oracle-apply-raw (fn args state)
(declare (xargs :stobjs state :guard t))
(ec-call (oracle-apply fn args state)))")
(ORACLE-FUNCALL
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Call a function argument on the remaining arguments
Oracle-funcall evaluates its first argument to produce an ACL2
function symbol, and then applies that function symbol to the
values of the rest of the arguments. The return value is of the
form (mv call-result state).
Examples:
(oracle-funcall 'cons 3 4) ==> (mv '(3 . 4) <state>)
(oracle-funcall (car '(floor foo bar)) (+ 6 7) 5) ==> (mv 2 <state>)
Oracle-funcall is a macro; each of its calls macroexpands to a call
of the related utility oracle-apply that takes the ACL2 [state] as
an argument, as follows:
(oracle-funcall fn x1 x2 .. xk)
macroexpands to
(oracle-apply fn (list x1 x2 .. xk) state)
Note that calls of oracle-funcall and oracle-apply return two values:
the result of the function application, and a modified [state].
See [oracle-apply] for details, including information about [guard]s.
Macro: <oracle-funcall>
(defmacro oracle-funcall (fn &rest args)
(cons 'oracle-apply
(cons fn
(cons (cons 'list args)
(cons 'state 'nil)))))")
(ORDINALS
(MISCELLANEOUS)
"Ordinals in ACL2
Ordinals are used in ACL2 for proving termination in the admission of
recursive function definitions. For a proof that the ACL2 ordinals
are well-founded, see [proof-of-well-foundedness].
The representation of ordinals changed in ACL2 Version_2.8, and is
due to Pete Manolios and Daron Vroon. They have also defined
algorithms for ordinal arithmetic, created a library of theorems to
reason about ordinal arithmetic, and written the rest of this
documentation in order to explain this change. We thank them for
their efforts. Although they have provided the implementation and
even modified the community books as needed, we have looked over
their work and are maintaining it (and this documentation); if
there are any bugs, they should be considered ours (Matt Kaufmann
and J Moore).
A book is included for compatibility with the representation before
Version_2.8. For books that contain events relying on the previous
ordinal implementation, insert the following lines before the first
such event:
(include-book \"ordinals/e0-ordinal\" :dir :system)
(set-well-founded-relation e0-ord-<)
The new ordinal representation is based on a slightly different
version of Cantor Normal Form than that used by the old ordinals.
An advantage of the new representation is that it is exponentially
more succinct than the old representation.
While pre-Version_2.8 ACL2 versions provided built-in functions for
checking if an object is an ordinal and for comparing two ordinals,
they did not provide support for reasoning about and constructing
ordinals. The community books directory books/ordinals provides
such support. First, it provides efficient algorithms for ordinal
arithmetic (including addition, subtraction, multiplication, and
exponentiation). The algorithms and their complexity are described
in the following paper.
Manolios, Panagiotis & Vroon, Daron.
Algorithms for ordinal arithmetic.
Baader, Franz (ed),
19th International Conference on Automated Deduction--CADE-19.
Pages 243-257 of LNAI, vol. 2741. Springer-Verlag.
Second, the algorithms are mechanically verified and libraries of
theorems which can be used to automate reasoning involving the
ordinals are provided. For details, see the following paper.
Manolios, Panagiotis & Vroon, Daron.
Ordinal arithmetic in ACL2.
Kaufmann, Matt, & Moore, J Strother (eds).
Fourth International Workshop on the ACL2 Theorem
Prover and Its Applications (ACL2-2003),
July, 2003.
See {http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/ | http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/}.
We now describe aspects of the above mentioned books in more detail.
The new ordering function is [o<] and the new ordinal recognizer is
[o-p]. See also [natp], [posp], [o<=], [o>], [o>=], [o-first-expt],
[o-first-coeff], [o-rst], [make-ord], [o-finp], and [o-infp].
The old ordinals were based on the following formulation of Cantor
Normal Form:
For any ordinal, a < epsilon-0, there exist natural numbers p and n,
and ordinals a1 >= a2 >= ... >= an > 0 such that a > a1 and a =
w^(a1) + w^(a2) + ... + w^(an) + p.
Thus, a predicate recognizing ACL2's old ordinals is given by the
following definition.
(defun e0-ordinalp (x)
(if (consp x)
(and (e0-ordinalp (car x))
(not (equal (car x) 0))
(e0-ordinalp (cdr x))
(or (atom (cdr x))
(not (e0-ord-< (car x) (cadr x)))))
(and (integerp x)
(>= x 0))))
The new representation is based on a corollary to the above theorem,
which we get by the left distributive property of ordinal
multiplication over ordinal addition. Thus, w^a + w^a = (w^a)2, w^a
+ w^a + w^a = (w^a)3 and so forth. The corollary is as follows:
For any ordinal, a < epsilon-0, there exist natural numbers p and n,
positive integers x1, x2, ..., xn and ordinals a1 > a2 > ... > an >
0 such that a > a1 and a = w^(a1)x1 + w^(a2)x2 + ... + w^(an)xn +
p.
Instead of representing an ordinal as a list of non-increasing
ordinals, we represent it as a list of exponent-coefficient pairs,
such that the exponents are strictly decreasing (see [o-p]). Note
that this representation is exponentially more efficient than the
old representation.
The ordinal arithmetic functions: o+, o-, o*, and o^ are defined in
the ordinals library (in the community books directory
books/ordinals). To use them, include the book
ordinals-without-arithmetic or ordinals, depending on whether you
want the arithmetic books included or not (ordinals includes
community book books/arithmetic/top-with-meta). To use the old
ordinals, include the book e0-ordinal and run the command
(set-well-founded-relation e0-ord-<)
The community book [arithmetic/natp-posp] is a book for reasoning
about posp and natp. We recommend using this book if you have to
reason about posp and natp. It is included in community book
books/arithmetic/top, which is included in community book
books/arithmetic/top-with-meta, which is included in community book
books/ordinals/ordinals.
If you have a good reason to use the old definitions of the ordinals
(e.g., because of legacy code and theorems), then we provide a
convenient way to do this. The book ordinal-isomorphism proves that
the new ordinals are order-isomorphic to the old ordinals and thus
theorems proved in one context can be directly transferred to the
other. For an example of how to do this, look at the book defmul in
the community books directory books/workshops/2000/ruiz/multiset.
The ordinals books have been used to prove non-trivial theorems. For
a good example, see the books in the community books directory
books/workshops/2003/sustik/support, where Matyas Sustik proves
Dickson's lemma.
Finally, many termination proofs can be carried out with weaker
orderings than the ordinals up to epsilon-0. For example, many
inductive theorem provers only know that the lexicographic ordering
on natural numbers is well-founded. The book lexicographic-ordering
contains a definition of such an ordering l< whose arguments are
either a list of natural numbers, or a natural number. In the book
we prove that l< is well-founded (that is, we prove a
:well-founded-relation [defthm] and provide a macro llist to
simplify the generation of measure functions. We also show how to
use l< to prove that the famous Ackermann function terminates.
Finally, since l< does something reasonable with natural numbers,
it gets along with [ACL2-count], the default measure chosen by
ACL2.
Subtopics
[Make-ord]
A constructor for ordinals.
[O-finp]
Recognizes if an ordinal is finite
[O-first-coeff]
Returns the first coefficient of an ordinal
[O-first-expt]
The first exponent of an ordinal
[O-infp]
Recognizes if an ordinal is infinite
[O-p]
A recognizer for the ordinals up to epsilon-0
[O-rst]
Returns the rest of an infinite ordinal
[O<]
The well-founded less-than relation on ordinals up to epsilon-0
[O<=]
The less-than-or-equal relation for the ordinals
[O>]
The greater-than relation for the ordinals
[O>=]
The greater-than-or-equal relation for the ordinals
[Proof-of-well-foundedness]
A proof that [o<] is well-founded on [o-p]s")
(OTF-FLG
(DEFTHM THM XARGS)
"Allow more than one initial subgoal to be pushed for induction
The value of this flag is normally nil. If you want to prevent the
theorem prover from abandoning its initial work upon pushing the
second subgoal, set :otf-flg to t.
Suppose you submit a conjecture to the theorem prover and the system
splits it up into many subgoals. Any subgoal not proved by other
methods is eventually set aside for an attempted induction proof.
But upon setting aside the second such subgoal, the system chickens
out and decides that rather than prove n>1 subgoals inductively, it
will abandon its initial work and attempt induction on the
originally submitted conjecture. The :otf-flg (Onward Thru the Fog)
allows you to override this chickening out. When :otf-flg is t, the
system will push all the initial subgoals and proceed to try to
prove each, independently, by induction.
Even when you don't expect induction to be used or to succeed,
setting the :otf-flg is a good way to force the system to generate
and display all the initial subgoals.
For [defthm] and [thm], :otf-flg is a keyword argument that is a peer
to :[rule-classes] and :[hints]. It may be supplied as in the
following examples; also see [defthm].
(thm (my-predicate x y) :rule-classes nil :otf-flg t)
(defthm append-assoc
(equal (append (append x y) z)
(append x (append y z)))
:hints ((\"Goal\" :induct t))
:otf-flg t)
The :otf-flg may be supplied to [defun] via the [xargs] declare
option. When you supply an :otf-flg hint to defun, the flag is
effective for the termination proofs and the guard proofs, if any.")
(OTHER_REQUIREMENTS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Other Requirements
[{IMAGE}]
ACL2 is distributed on the Web without fee.
There is a license agreement based on the 3-clause BSD license. See
the file LICENSE in the ACL2 distribution.
ACL2 currently runs on Unix, Linux, Windows, and Macintosh OS X
operating systems.
It can be built in any of the following Common Lisps:
* Allegro Common Lisp,
* CCL (formerly OpenMCL)
* CLISP,
* CMU Common Lisp,
* GCL (Gnu Common Lisp),
* LispWorks, and
* SBCL (Steel Bank Common Lisp)
[{IMAGE}]")
(OUTPUT-TO-FILE
(IO)
"Redirecting output to a file
For a general discussion of ACL2 input/output and of the ACL2
read-eval-print loop, see [io] and see [ld] (respectively). Here we
use an example to illustrate how to use some of the options
provided by ld to redirect ACL2 output to a file, other than the
printing of the prompt (which continues to go to the terminal).
There are two ld specials that control output from the ld command:
[proofs-co] for proof output and [standard-co] for other output.
The following example shows how to use these to redirect output to
a file \"tmp.out\". The following command opens a character output
channel to to the file \"tmp.out\" and redirects proof output to that
channel, i.e., to file \"tmp.out\".
(mv-let (chan state)
(open-output-channel \"tmp.out\" :character state)
(set-proofs-co chan state))
Next, we redirect standard output to that same channel.
(set-standard-co (proofs-co state) state)
Now we can load an input file, in this case file \"tmp.lisp\", and
output will be redirected to file \"tmp.out\". (The use of
:ld-pre-eval-print t is optional; see [ld].)
(ld \"tmp.lisp\" :ld-pre-eval-print t)
Having completed our load operation, we restore both proof output and
standard output to the terminal, as follows.
(set-standard-co *standard-co* state)
(close-output-channel (proofs-co state) state)
(set-proofs-co *standard-co* state)
The following variant of the above example shows how to redirect
output as above except without changing the global settings of the
two [ld] specials, [proofs-co] and [standard-co]. This approach
uses a notion of ``global variables'' stored in the ACL2 [state];
see [assign] and see [@].
(mv-let (chan state)
(open-output-channel \"tmp.out\" :character state)
(assign tmp-channel chan))
(ld \"tmp.lisp\" :ld-pre-eval-print t
:proofs-co (@ tmp-channel)
:standard-co (@ tmp-channel))
(close-output-channel (@ tmp-channel) state)")
(OVERRIDE-HINTS
(HINTS)
"A list of hints given priority in every proof attempt
This is an advanced feature, originally implemented to help system
designers to create ``modes'' that control the way hints are
supplied to the theorem prover. Please see [default-hints] for the
much more usual way to install hints that may be applied by
default.
Examples:
ACL2 !>(override-hints (w state))
((computed-hint-1 clause keyword-alist processor)
(computed-hint-2 clause keyword-alist stable-under-simplificationp))
Override-hints returns a list of computed hints (see
[computed-hints]) which, unlike other computed hints, may mention
the variable KEYWORD-ALIST.
Before reading further, please see [hints-and-the-waterfall] to
review the basics of how [hints] are applied during a proof. In
particular, we assume familiarity with the notion of selecting a
hint to be applied to the current goal. If there are
override-hints, that hint selection is tentative, because if it
reduced to nil after the application of override-hints, then that
hint will be skipped and the attempt will continue for selecting an
applicable hint. (Craft your override-hints so that :no-op t is
returned in such cases instead of nil, if you don't want the hint
to be skipped.) But we must explain what is meant by ``the
application of override-hints'', and we do that now.
Suppose that there are override-hints when a hint is selected for the
current goal. That selected hint is a keyword-alist, which is an
alternating list of hint keywords and their values, whose source is
either an explicit hint (goal-name :key1 val1 ... :keyn valn) where
the :keyi are allowed to be custom hint keywords (which are
expanded away; see [custom-keyword-hints]), or else is the non-nil
keyword-alist produced by evaluating a computed hint. Then the
override-hints are applied to that keyword-alist as follows, one at
a time, in order of their occurrence in the list of override-hints
(as determined by the use of [set-override-hints] and
[add-override-hints]). The first override-hint is evaluated, in the
usual manner of evaluating computed hints but with the variable
KEYWORD-ALIST bound to the above keyword-alist. That evaluation
produces a result that should also be a keyword-alist, or else an
error occurs. Any custom keyword hints are then eliminated from
that keyword-alist. The resulting keyword-alist must not contain
the :ERROR hint keyword and must not start with the
:COMPUTED-HINT-REPLACEMENT keyword; otherwise an error occurs. With
KEYWORD-ALIST bound to this result, the second override-hint is
similarly evaluated. This process continues, and the keyword-alist
returned by the final override-hint is the one used when processing
the goal at hand. Except: If that keyword-alist is nil, then the
next hint among the pending hints is tentatively selected and the
process repeats, applying each override hint to that new tentative
selection. Of course we might obtain nil again, in which case we
tentatively select the next pending hint; and so on.
If finally no hint is selected for the current goal, then
KEYWORD-ALIST is bound to nil and the override-hints are applied as
described above. But note that this final step is skipped if hint
selection is being performed because stable-under-simplificationp
has just become true, rather than at the top of the waterfall.
(Otherwise the override-hints could easily keep firing uselessly
yet putting us back at the top of the waterfall, with no change to
the given goal, resulting in an infinite loop.)
As mentioned above, the :COMPUTED-HINT-REPLACEMENT keyword is illegal
for the value of an override-hint. But a selected hint may be a
computed hint that evaluates to a keyword-alist beginning with
prefix :COMPUTED-HINT-REPLACEMENT val. What value does ACL2 return
for such a computed hint in the presence of override-hints? First,
this prefix is stripped off before passing the resulting
keyword-alist to the override-hints as described above. If the
result of applying override-hints to that keyword-alist is not nil,
then the prefix is put back on the front of that resulting
keyword-alist after doing internal processing of the hint,
including expansion of any custom keyword hints. Otherwise, the
application of override-hints to the computed hint is nil, so this
hint is not selected after all.
WARNING: Unlike ordinary computed hints, a value of nil for an
override-hint is not ignored. That is: When an ordinary computed
hint evaluates to nil, it is deemed not to apply, and the next
available hint is consulted. But when an override-hint is
evaluated, the result is always supplied for the next binding of
the variable KEYWORD-ALIST, even if that result is nil. If you want
an override-hint to be a no-op, return as the expression the
variable KEYWORD-ALIST rather than an expression that evaluates to
nil.
This feature can be used in order to implement a form of additive
hints. Suppose for example that you want a hint that turns off
generalization. A simple but inadequate solution is:
(add-default-hints '((quote (:do-not '(generalize)))))
The problem is that if there is any explicit hint supplied for a
given goal, then it will be the one selected, and the above will be
ignored. But suppose that the explicit hint supplied is of the form
(\"Subgoal x.y\" :do-not '(fertilize)). What we would really want in
this case is to generate the hint for the indicated subgoal that
binds :do-not to a list indicating that both fertilization _and_
generalization are disabled for that goal. A solution is to merge,
for example as follows. (The use of [prog2$] and [cw] is of course
optional, included here to provide debug printing.)
(add-override-hints
'((let* ((tmp (assoc-keyword :do-not KEYWORD-ALIST))
(new-keyword-alist
(cond (tmp (list* :do-not
`(cons 'generalize ,(cadr tmp))
(remove-keyword :do-not KEYWORD-ALIST)))
(t (list* :do-not ''(generalize) KEYWORD-ALIST)))))
(prog2$ (cw \"New: ~x0~|\" new-keyword-alist)
new-keyword-alist))))
REMARKS
(1) The utilities [add-override-hints], [add-override-hints!],
[set-override-hints], [set-override-hints!],
[remove-override-hints], and [remove-override-hints!] are also
available, in complete analogy to their default-hints versions.
(2) The community book hints/basic-tests.lisp illustrates the use of
override-hints and illuminates a number of corner cases; search in
that file for ``Test override-hints.''
(3) The community book hints/merge-hint.lisp provides support for
merging hints that might be useful for writers of override-hint
expressions (see the examples at the end of that file).
(4) Override-hints are used in the processing of :BACKTRACK hints
(see [hints]).
Subtopics
[Add-override-hints]
Add to the [override-hints]
[Add-override-hints!]
Add non-[local]ly to the [override-hints]
[Remove-override-hints]
Delete from the list of [override-hints]
[Remove-override-hints!]
Delete non-[local]ly from the list of [override-hints]
[Set-override-hints]
Set the [override-hints]
[Set-override-hints!]
Set the [override-hints] non-[local]ly")
(OVERVIEW_OF_THE_EXPANSION_OF_ENDP_IN_THE_BASE_CASE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Overview of the Expansion of ENDP in the Base Case
Subgoal *1/1 is the Base Case of our induction. It simplifies to
Subgoal *1/1' by expanding the ENDP term in the hypothesis, just as
we saw in the earlier proof of Subgoal *1/2.")
(OVERVIEW_OF_THE_EXPANSION_OF_ENDP_IN_THE_INDUCTION_STEP
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Overview of the Expansion of ENDP in the Induction Step
In this message the system is saying that Subgoal *1/2 has been
rewritten to the Subgoal *1/2', by expanding the definition of
endp. This is an example of simplification, one of the main proof
techniques used by the theorem prover.
Click [here] if you would like to step through the simplification of
Subgoal *1/2.")
(OVERVIEW_OF_THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Overview of the Final Simplification in the Base Case
The But is our signal that the goal is proved.
Click [here] to step through the proof. It is very simple.")
(OVERVIEW_OF_THE_PROOF_OF_A_TRIVIAL_CONSEQUENCE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Overview of the Proof of a Trivial Consequence
[{IMAGE}]
{IMAGE}
ACL2 !>(defthm trivial-consequence
(equal (app (app (app (app x1 x2) (app x3 x4)) (app x5 x6)) x7)
(app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7))))))
[ACL2 Warning] [Subsume] in ( DEFTHM TRIVIAL-CONSEQUENCE ...): The previously
added rule ASSOCIATIVITY-OF-APP subsumes the newly proposed :REWRITE
rule TRIVIAL-CONSEQUENCE, in the sense that the old rule rewrites a
more general target. Because the new rule will be tried first, it
may nonetheless find application.
By the simple :rewrite rule [ASSOCIATIVITY-OF-APP] we reduce the conjecture
to
Goal'
(EQUAL (APP X1
(APP X2
(APP X3 (APP X4 (APP X5 (APP X6 X7))))))
(APP X1
(APP X2
(APP X3 (APP X4 (APP X5 (APP X6 X7))))))).
But we reduce the conjecture to T, by primitive type reasoning.
Q.E.D.
Summary
Form: ( DEFTHM TRIVIAL-CONSEQUENCE ...)
Rules: ((:REWRITE ASSOCIATIVITY-OF-APP)
(:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: [Subsume]
Time: 0.20 seconds (prove: 0.02, print: 0.00, other: 0.18)
TRIVIAL-CONSEQUENCE
{IMAGE}
You might explore the links before moving on.
[{IMAGE}]")
(OVERVIEW_OF_THE_SIMPLIFICATION_OF_THE_BASE_CASE_TO_T
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Overview of the Simplification of the Base Case to T
[{IMAGE}]
[Subgoal *1/1]
(IMPLIES (ENDP A)
(EQUAL (APP (APP A B) C)
(APP A (APP B C)))).
By the simple :definition ENDP we reduce the conjecture to
Subgoal *1/1'
(IMPLIES (NOT (CONSP A))
(EQUAL (APP (APP A B) C)
(APP A (APP B C)))).
[But] simplification reduces this to T, using the :definition APP and
primitive type reasoning.
[{IMAGE}]")
(OVERVIEW_OF_THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Overview of the Simplification of the Induction Conclusion
In this message the system is saying that Subgoal *1/2' has been
rewritten to T using the rules noted. The word ``But'' at the
beginning of the sentence is a signal that the goal has been
proved.
Click [here] to step through the proof of Subgoal *1/2'.")
(OVERVIEW_OF_THE_SIMPLIFICATION_OF_THE_INDUCTION_STEP_TO_T
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Overview of the Simplification of the Induction Step to T
[{IMAGE}]
[Subgoal *1/2]
(IMPLIES (AND (NOT (ENDP A))
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (APP (APP A B) C)
(APP A (APP B C)))).
By the simple :definition [ENDP] we reduce the conjecture to
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (APP (APP A B) C)
(APP A (APP B C)))).
[But] simplification reduces this to T, using the :definition APP, the
:rewrite rules CDR-CONS and CAR-CONS and primitive type reasoning.
[{IMAGE}]")
(P!
(LD)
"To pop up (at least) one level of ACL2's command loop
Logically speaking, (p!) = nil. If you are already at the top level
of the ACL2 command loop, rather than being in a subsidiary call of
[ld], then the keyword then a call of (p!) returns nil and has no
other effect.
Otherwise, (p!) is evaluated inside a call of [ld] that was made
inside ACL2's command loop. In that case, the current computation
is aborted and treating as causing an error, and control returns to
the superior call of ld.
Here is a more detailed description of the effect of (p!) when not at
the top level of the ACL2 command loop. The current call of LD is
treated as though ld-error-action is :RETURN! (the default; here we
ignore the case (:exit N)) and hence immediately returns control to
the superior call of [ld]. If all calls of [ld] were made with the
default ld-error-action of :RETURN!, then all superior calls of ld
will then complete until you are back at top level of the ACL2
loop. For more information, see [ld-error-action].
If you are at an ACL2 prompt (as opposed to a raw Lisp break), then
you may type :p! in place of (p!); see [keyword-commands].")
(PACKAGE (POINTERS) "See [packages].")
(PACKAGE-REINCARNATION-IMPORT-RESTRICTIONS
(PACKAGES)
"Re-defining undone [defpkg]s
Suppose (defpkg \"pkg\" imports) is the most recently executed
successful definition of \"pkg\" in this ACL2 session and that it has
since been undone, as by :[ubt]. Any future attempt in this session
to define \"pkg\" as a package must specify an identical imports
list.
The restriction stems from the need to implement the reinstallation
of saved logical [world]s as in error recovery and the :[oops]
[command]. Suppose that the new [defpkg] attempts to import some
symbol, a::sym, not imported by the previous definition of \"pkg\".
Because it was not imported in the original package, the symbol
pkg::sym, different from a::sym, may well have been created and may
well be used in some saved [world]s. Those saved [world]s are
Common Lisp objects being held for you ``behind the scenes.'' In
order to import a::sym into \"pkg\" now we would have to unintern
pkg::sym, rendering those saved [world]s ill-formed. It is because
of saved [world]s that we do not actually clear out a package when
it is undone.
At one point we thought it was sound to allow the new [defpkg] to
import a subset of the old. But that is incorrect. Suppose the old
definition of \"pkg\" imported a::sym but the new one does not.
Suppose we allowed that and implemented it simply by setting the
imports of \"pkg\" to the new subset. Then consider the conjecture
(eq a::sym pkg::sym). This ought not be a theorem because we did
not import a::sym into \"pkg\". But in fact in AKCL it is a theorem
because pkg::sym is read as a::sym because of the old imports.")
(PACKAGES
(PROGRAMMING)
"Collections of symbols that act as namespaces.
Packages are collections of symbols. They can be used to avoid name
conflicts when working on large ACL2 projects. See
[working-with-packages] for the best practices in setting up and
using packages.
Subtopics
[*ACL2-exports*]
Symbols that are often imported into new [packages] to provide easy
access to ACL2 functionality.
[*common-lisp-symbols-from-main-lisp-package*]
Symbols that are often imported into new packages to provide easy
access to Common Lisp functionality.
[ACL2-user]
A package the ACL2 user may prefer
[Defpkg]
Define a new symbol package
[Hidden-death-package]
Handling [defpkg] [events] that are [local]
[Hidden-defpkg]
Handling defpkg events that are local
[In-package]
Select current package
[Intern]
Create a new symbol in a given package
[Intern$]
Create a new symbol in a given package
[Intern-in-package-of-symbol]
Create a symbol with a given name
[Managing-ACL2-packages]
User-contributed documentation on packages
[Package-reincarnation-import-restrictions]
Re-defining undone [defpkg]s
[Pkg-imports]
List of symbols imported into a given package
[Pkg-witness]
Return a specific symbol in the indicated package
[Sharp-bang-reader]
Package prefix that is not restricted to symbols
[Symbol-package-name]
The name of the package of a symbol (a string)")
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS
(ACL2-TUTORIAL)
"Pages Written Especially for the Tours
The ACL2 Home Page is generated from ACL2's online documentation
strings. (How else could we achieve the total integration of ACL2's
online documentation with the home page?) This page is just an
artifact of the structure of our documentation strings: each string
must belong to a ``major section'' of the documentation database.
This page is not structured to be used by a person browsing via the
Web. It contains, in an arbitrary order, the pages written
specificially for the Web user.
Furthermore, browsing the pages below as text, in particular using
the ACL2 :DOC command, is often unsatisfying because because of the
lack of support for displaying gif files or for going ``back'' to a
node just visited. If you wish to look at the pages below, we
strongly recommend that you do so via a HTML-based Web browser.
Indeed, you should simply visit ACL2's Home Page and take one of
the Tours.
Generally, the topics listed above will not be of use to the ACL2
user.
Subtopics
[A_Flying_Tour_of_ACL2]
A Flying Tour of ACL2
[A_Sketch_of_How_the_Rewriter_Works]
A Sketch of How the Rewriter Works
[A_Tiny_Warning_Sign]
A Tiny Warning Sign
[A_Trivial_Proof]
A Trivial Proof
[A_Typical_State]
A Typical State
[A_Walking_Tour_of_ACL2]
A Walking Tour of ACL2
[ACL2_Characters]
ACL2 Characters
[ACL2_Conses_or_Ordered_Pairs]
ACL2 Conses or Ordered Pairs
[ACL2_Strings]
ACL2 Strings
[ACL2_Symbols]
ACL2 Symbols
[ACL2_System_Architecture]
ACL2 System Architecture
[ACL2_as_an_Interactive_Theorem_Prover]
ACL2 as an Interactive Theorem Prover
[ACL2_as_an_Interactive_Theorem_Prover_{cont}]
ACL2 as an Interactive Theorem Prover (cont)
[ACL2_is_an_Untyped_Language]
ACL2 is an Untyped Language
[About_Models]
About Models
[About_Types]
About Types
[About_the_ACL2_Home_Page]
About the ACL2 Home Page
[About_the_Admission_of_Recursive_Definitions]
About the Admission of Recursive Definitions
[About_the_Prompt]
About the Prompt
[An_Example_Common_Lisp_Function_Definition]
An Example Common Lisp Function Definition
[An_Example_of_ACL2_in_Use]
An Example of ACL2 in Use
[Analyzing_Common_Lisp_Models]
Analyzing Common Lisp Models
[Common_Lisp]
Common Lisp
[Common_Lisp_as_a_Modeling_Language]
Common Lisp as a Modeling Language
[Conversion]
Conversion to Uppercase
[Corroborating_Models]
Corroborating Models
[Evaluating_App_on_Sample_Input]
Evaluating App on Sample Input
[Flawed_Induction_Candidates_in_App_Example]
Flawed Induction Candidates in App Example
[Free_Variables_in_Top-Level_Input]
Free Variables in Top-Level Input
[Functions_for_Manipulating_these_Objects]
Functions for Manipulating these Objects
[Guards_in_ACL2]
Guards
[Guessing_the_Type_of_a_Newly_Admitted_Function]
Guessing the Type of a Newly Admitted Function
[Guiding_the_ACL2_Theorem_Prover]
Guiding the ACL2 Theorem Prover
[Hey_Wait!__Is_ACL2_Typed_or_Untyped{Q}]
Hey Wait! Is ACL2 Typed or Untyped?
[How_Long_Does_It_Take_to_Become_an_Effective_User{Q}]
How Long Does It Take to Become an Effective User?
[How_To_Find_Out_about_ACL2_Functions]
How To Find Out about ACL2 Functions
[How_To_Find_Out_about_ACL2_Functions_{cont}]
How To Find Out about ACL2 Functions (cont)
[Modeling_in_ACL2]
Modeling in ACL2
[Models_in_Engineering]
Models in Engineering
[Models_of_Computer_Hardware_and_Software]
Models of Computer Hardware and Software
[Name_the_Formula_Above]
Name the Formula Above
[Nontautological_Subgoals]
Prover output omits some details
[Numbers_in_ACL2]
Numbers in ACL2
[On_the_Naming_of_Subgoals]
On the Naming of Subgoals
[Other_Requirements]
Other Requirements
[Overview_of_the_Expansion_of_ENDP_in_the_Base_Case]
Overview of the Expansion of ENDP in the Base Case
[Overview_of_the_Expansion_of_ENDP_in_the_Induction_Step]
Overview of the Expansion of ENDP in the Induction Step
[Overview_of_the_Final_Simplification_in_the_Base_Case]
Overview of the Final Simplification in the Base Case
[Overview_of_the_Proof_of_a_Trivial_Consequence]
Overview of the Proof of a Trivial Consequence
[Overview_of_the_Simplification_of_the_Base_Case_to_T]
Overview of the Simplification of the Base Case to T
[Overview_of_the_Simplification_of_the_Induction_Conclusion]
Overview of the Simplification of the Induction Conclusion
[Overview_of_the_Simplification_of_the_Induction_Step_to_T]
Overview of the Simplification of the Induction Step to T
[Perhaps]
Perhaps
[Popping_out_of_an_Inductive_Proof]
Popping out of an Inductive Proof
[Proving_Theorems_about_Models]
Proving Theorems about Models
[Revisiting_the_Admission_of_App]
Revisiting the Admission of App
[Rewrite_Rules_are_Generated_from_DEFTHM_Events]
Rewrite Rules are Generated from DEFTHM Events
[Running_Models]
Running Models
[Subsumption_of_Induction_Candidates_in_App_Example]
Subsumption of Induction Candidates in App Example
[Suggested_Inductions_in_the_Associativity_of_App_Example]
Suggested Inductions in the Associativity of App Example
[Symbolic_Execution_of_Models]
Symbolic Execution of Models
[The_Admission_of_App]
The Admission of App
[The_Associativity_of_App]
The Associativity of App
[The_Base_Case_in_the_App_Example]
The Base Case in the App Example
[The_End_of_the_Flying_Tour]
The End of the Flying Tour
[The_End_of_the_Proof_of_the_Associativity_of_App]
The End of the Proof of the Associativity of App
[The_End_of_the_Walking_Tour]
The End of the Walking Tour
[The_Event_Summary]
The Event Summary
[The_Expansion_of_ENDP_in_the_Induction_Step_{Step_0}]
The Expansion of ENDP in the Induction Step (Step 0)
[The_Expansion_of_ENDP_in_the_Induction_Step_{Step_1}]
The Expansion of ENDP in the Induction Step (Step 1)
[The_Expansion_of_ENDP_in_the_Induction_Step_{Step_2}]
The Expansion of ENDP in the Induction Step (Step 2)
[The_Falling_Body_Model]
The Falling Body Model
[The_Final_Simplification_in_the_Base_Case_{Step_0}]
The Final Simplification in the Base Case (Step 0)
[The_Final_Simplification_in_the_Base_Case_{Step_1}]
The Final Simplification in the Base Case (Step 1)
[The_Final_Simplification_in_the_Base_Case_{Step_2}]
The Final Simplification in the Base Case (Step 2)
[The_Final_Simplification_in_the_Base_Case_{Step_3}]
The Final Simplification in the Base Case (Step 3)
[The_First_Application_of_the_Associativity_Rule]
The First Application of the Associativity Rule
[The_Induction_Scheme_Selected_for_the_App_Example]
The Induction Scheme Selected for the App Example
[The_Induction_Step_in_the_App_Example]
The Induction Step in the App Example
[The_Instantiation_of_the_Induction_Scheme]
The Instantiation of the Induction Scheme
[The_Justification_of_the_Induction_Scheme]
The Justification of the Induction Scheme
[The_Proof_of_the_Associativity_of_App]
The Proof of the Associativity of App
[The_Q.E.D._Message]
The Q.E.D. Message
[The_Rules_used_in_the_Associativity_of_App_Proof]
The Rules used in the Associativity of App Proof
[The_Simplification_of_the_Induction_Conclusion_{Step_0}]
The Simplification of the Induction Conclusion (Step 0)
[The_Simplification_of_the_Induction_Conclusion_{Step_1}]
The Simplification of the Induction Conclusion (Step 1)
[The_Simplification_of_the_Induction_Conclusion_{Step_10}]
The Simplification of the Induction Conclusion (Step 10)
[The_Simplification_of_the_Induction_Conclusion_{Step_11}]
The Simplification of the Induction Conclusion (Step 11)
[The_Simplification_of_the_Induction_Conclusion_{Step_12}]
The Simplification of the Induction Conclusion (Step 12)
[The_Simplification_of_the_Induction_Conclusion_{Step_2}]
The Simplification of the Induction Conclusion (Step 2)
[The_Simplification_of_the_Induction_Conclusion_{Step_3}]
The Simplification of the Induction Conclusion (Step 3)
[The_Simplification_of_the_Induction_Conclusion_{Step_4}]
The Simplification of the Induction Conclusion (Step 4)
[The_Simplification_of_the_Induction_Conclusion_{Step_5}]
The Simplification of the Induction Conclusion (Step 5)
[The_Simplification_of_the_Induction_Conclusion_{Step_6}]
The Simplification of the Induction Conclusion (Step 6)
[The_Simplification_of_the_Induction_Conclusion_{Step_7}]
The Simplification of the Induction Conclusion (Step 7)
[The_Simplification_of_the_Induction_Conclusion_{Step_8}]
The Simplification of the Induction Conclusion (Step 8)
[The_Simplification_of_the_Induction_Conclusion_{Step_9}]
The Simplification of the Induction Conclusion (Step 9)
[The_Summary_of_the_Proof_of_the_Trivial_Consequence]
The Summary of the Proof of the Trivial Consequence
[The_Theorem_that_App_is_Associative]
The Theorem that App is Associative
[The_Time_Taken_to_do_the_Associativity_of_App_Proof]
The Time Taken to do the Associativity of App Proof
[The_Tours]
The Tours
[The_WARNING_about_the_Trivial_Consequence]
The WARNING about the Trivial Consequence
[Undocumented_Topic]
Undocumented Topic
[Using_the_Associativity_of_App_to_Prove_a_Trivial_Consequence]
Using the Associativity of App to Prove a Trivial Consequence
[What_Is_ACL2{Q}]
What Is ACL2?
[What_is_Required_of_the_User{Q}]
What is Required of the User?
[What_is_a_Mathematical_Logic{Q}]
What is a Mathematical Logic?
[What_is_a_Mechanical_Theorem_Prover{Q}]
What is a Mechanical Theorem Prover?
[What_is_a_Mechanical_Theorem_Prover{Q}_{cont}]
What is a Mechanical Theorem Prover? (cont)
[You_Must_Think_about_the_Use_of_a_Formula_as_a_Rule]
You Must Think about the Use of a Formula as a Rule")
(PAIRLIS
(LISTS ALISTS)
"See [pairlis$]
The Common Lisp language allows its pairlis function to construct an
alist in any order! So we have to define our own version: See
[pairlis$].")
(PAIRLIS$
(LISTS ALISTS ACL2-BUILT-INS)
"Zipper together two lists
The Common Lisp language allows its [pairlis] function to construct
an alist in any order! So we have to define our own version,
pairlis$. It returns the list of pairs obtained by [cons]ing
together successive respective members of the given lists until the
first list runs out. (Hence in particular, if the second argument
is nil then each element of the first argument is paired with nil.)
The [guard] for pairlis$ requires that its arguments are true lists.
Function: <pairlis$>
(defun pairlis$ (x y)
(declare (xargs :guard (and (true-listp x) (true-listp y))))
(mbe :logic (cond ((endp x) nil)
(t (cons (cons (car x) (car y))
(pairlis$ (cdr x) (cdr y)))))
:exec (pairlis$-tailrec x y nil)))")
(PAND
(PARALLEL-PROGRAMMING ACL2-BUILT-INS)
"Parallel, Boolean version of [and]
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism],
and see [parallel-programming], which has a disclaimer.
Example Forms:
(pand (subsetp-equal x y)
(subsetp-equal y x))
(pand (declare
(granularity
(and (> (length x) 500)
(> (length y) 500))))
(subsetp-equal x y)
(subsetp-equal y x))
General Form:
(pand (declare (granularity expr)) ; optional granularity declaration
arg1 ... argN)
where N >= 0 and each argi and expr are arbitrary terms.
Pand evaluates its arguments in parallel. It returns a Boolean
result: nil if any argument evaluates to nil, else t. Note that
pand always returns a Boolean result, even though and can return a
non-nil value other than t, namely the value of its last argument.
(A moment's reflection will make it clear that in order for [por]
to parallelize efficiently, it needs to return a Boolean value; so
pand returns a Boolean value for consistency with [por].)
Another difference between pand and [and] is that for a call of pand,
even if an argument evaluates to nil, a subsequent argument may be
evaluated. Consider the following example (where cw prints a
string; see [cw]).
(defun bar ()
(pand (equal (make-list 100000) nil) ; evaluates to nil
(cw \"hello world~%\")))
When (bar) is evaluated, the above arguments of pand can execute in
parallel, causing ``hello world'' to be printed to the terminal. If
we had used and rather than pand, then since (equal (make-list
100000) nil) evaluates to nil, the above call of [cw] would be
avoided and no such printing would take place. Even with pand, such
printing might not take place, depending on resources, timing of
thread creation, and whether or not parallel execution is enabled
(see [set-parallel-execution]).
Note that unlike the case for [and], the definition of pand does not
provide (consp x) as a [guard] to (car x) in the call of pand
below:
(defun h (x)
(declare (xargs :guard t))
(pand (consp x) (equal (car x) 'foo)))
As a result, [guard] verification will fail for the above definition.
If pand were replaced by and, then [guard] verification would
succeed.
See [parallelism-tutorial] for another example. Also see
[parallelism-at-the-top-level] for restrictions on evaluating
parallelism primitives from within the ACL2 top-level loop. Finally
see [early-termination] to read how pand can offer more efficiency
than [and] by avoiding evaluation of some of its arguments.")
(PARALLEL (PARALLELISM)
"Evaluating forms in parallel
See [parallelism].")
(PARALLEL-EXECUTION
(PARALLEL-PROGRAMMING)
"For ACL2(p): configure parallel execution
See [set-parallel-execution] for how to configure parallel execution
for calls of [plet], [pargs], [pand], [por] (but not
[spec-mv-let]).")
(PARALLEL-PROGRAMMING
(PARALLELISM)
"Parallel programming in ACL2(p)
Here we document support for parallel programming in ACL2(p), an
experimental extension of ACL2; also see [parallelism].
One of ACL2's strengths lies in its ability to execute industrial
models efficiently. The ACL2 source code provides an experimental
parallel execution capability that can increase the speed of
explicit evaluation, including simulator runs using such models,
and it can also decrease the time required for proofs that make
heavy use of the evaluation of ground terms.
The parallelism primitives are [plet], [pargs], [pand], [por], and
[spec-mv-let]. [Pand] and [por] terminate early when an argument is
found to evaluate to nil or non-nil, respectively, thus potentially
improving on the efficiency of lazy evaluation. [Spec-mv-let] is a
modification of [mv-let] that supports speculative and parallel
execution.
Of the above five parallelism primitives, all but [spec-mv-let] allow
for limiting parallel execution (spawning of so-called ``threads'')
depending on resource availability. Specifically, the primitives
allow specification of a size condition to control the
[granularity] under which threads are allowed to spawn. You can use
such [granularity] declarations in recursively-defined functions to
implement data-dependent parallelism in their execution.
We recommend that in order to learn to use the parallelism
primitives, you begin by reading examples: see
[parallelism-tutorial]. That section will direct you to further
documentation topics.
In addition to providing parallel programming primitives, ACL2(p)
also provides the ability to execute the main ACL2 proof process in
parallel. See [set-waterfall-parallelism] for further details.
Disclaimer. The parallelism primitives have been designed for
executing purely functional code, but some ACL2 functions do
interesting things ``under the hood'' in order to achieve their
effects. For example, [hons] primitives such as [hons-wash] may not
have the intended effect when executed under the parallelism
primitives.
Subtopics
[Deflock]
Define a wrapper macro that provides mutual exclusion in ACL2(p)
[Early-termination]
Early termination for [pand] and [por].
[Error-triples-and-parallelism]
How to avoid error triples in ACL2(p)
[Granularity]
Limit the amount of parallelism
[Pand]
Parallel, Boolean version of [and]
[Parallel-execution]
For ACL2(p): configure parallel execution
[Parallelism-at-the-top-level]
Parallel execution in the ACL2 top-level loop
[Parallelism-performance]
Performance issues for parallel execution
[Parallelism-tutorial]
A tutorial on how to use the parallelism library.
[Pargs]
Parallel evaluation of arguments in a function call
[Plet]
Parallel version of [let]
[Por]
Parallel, Boolean version of [or]
[Spec-mv-let]
Modification of [mv-let] supporting speculative and parallel
execution
[With-output-lock]
Provides a mutual-exclusion mechanism for performing output in
parallel")
(PARALLEL-PROOF
(PARALLELISM)
"Parallel proof in ACL2(p)
Here we document support for parallel proof in ACL2(p), an
experimental extension of ACL2; also see [parallelism], and for
parallel programming in particular, see [parallel-programming].
Subtopics
[ACL2p-key-checkpoints]
Key checkpoints in ACL2(p)
[Default-total-parallelism-work-limit]
For ACL2(p): returns the default value for global
total-parallelism-work-limit
[Parallel-pushing-of-subgoals-for-induction]
Consequences of how parallelized proofs of subgoals are pushed for
induction
[Unsupported-waterfall-parallelism-features]
Proof features not supported with waterfall-parallelism enabled
[Waterfall-parallelism]
For ACL2(p): configuring the parallel execution of the waterfall
[Waterfall-printing]
For ACL2(p): configuring the printing within the parallelized
waterfall")
(PARALLEL-PUSHING-OF-SUBGOALS-FOR-INDUCTION
(PARALLEL-PROOF)
"Consequences of how parallelized proofs of subgoals are pushed for
induction
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
The following discussion, concerning the naming of subgoals pushed
for proof by induction and the timeliness of aborting when two or
more goals are pushed for proof by induction, only applies when
waterfall parallelism is enabled (see [set-waterfall-parallelism]).
When two sibling subgoals (e.g. 4.5 and 4.6) both push goals to be
proved by induction (e.g., 4.6 pushes *1 and 4.5 pushes *2), a name
is assigned to the second pushed subgoal (e.g., *2) as if the first
push hasn't happened (e.g., *2 is mistakenly called *1). In such a
case, we say what the name _could_ be. The following non-theorem
illustrates how this works.
(set-waterfall-parallelism :full)
(thm (equal (append (car (cons x x)) y z) (append x x y)))
There is another consequence of the way the parallelized waterfall
pushes subgoals for proof by induction. Without waterfall
parallelism enabled, ACL2 sometimes decides to abort instead of
pushing a goal for later proof by induction, preferring instead to
induct on the original conjecture. But with waterfall parallelism
enabled, the prover no longer necessarily immediately aborts to
prove the original conjecture. Suppose for example that sibling
subgoals, Subgoal 4.6 and Subgoal 4.5, each push a subgoal for
induction. If the waterfall is performing the proof of each of
these subgoals in parallel, the proof will no longer abort
immediately after the second push occurs, that is at Subgoal 4.5.
As a result, the prover will continue through Subgoal 4.4, Subgoal
4.3, and beyond. It is not until the results of combining the proof
results of Subgoal 4.6 with the results from the remaining sibling
subgoals (4.5, 4.4, and so on), that the proof attempt will abort
and revert to prove the original conjecture by induction. This
example illustrates behavior that is rather like the case that
:[otf-flg] is t, in the sense that the abort does not happen
immediately, but also rather like the case that :[otf-flg] is nil,
in the sense that the abort does occur before getting to Subgoal 3.")
(PARALLELISM
(ACL2)
"Experimental extension for parallel execution and proofs
This documentation topic relates to an experimental extension of
ACL2, ACL2(p), created initially by David L. Rager. See
[compiling-ACL2p] for how to build an executable image that
supports parallel execution. Also see community books directory
books/parallel/ for examples. For a completely different sort of
parallelism, at the system level, see [provisional-certification].
IMPORTANT NOTE. We hope and expect that every evaluation result is
correctly computed by ACL2(p), and that every formula proved using
ACL2(p) is a theorem of the ACL2 logic (and in fact is provable
using ACL2). However, we do not guarantee these properties. Since
ACL2(p) is intended to be an aid in efficient evaluation and proof
development, we focus less on ironclad soundness and more on
providing an efficient and working implementation. Nevertheless, if
you encounter a case where ACL2(p) computes an incorrect result, or
produces a proof where ACL2 fails to do so (and this failure is not
discussed in [unsupported-waterfall-parallelism-features]), please
notify the implementors.
The ACL2 source code provides experimental parallel execution and
proof capabilities. For example, one of ACL2's strengths lies in
its ability to simulate industrial models efficiently, and it can
also decrease the time required for proofs about such models both
by making use of parallel evaluation and by dispatching proof
subgoals in parallel.
While we aim to support Clozure Common Lisp (CCL), Steel Bank Common
Lisp (SBCL), and Lispworks, SBCL and Lispworks both currently
sometimes experience problems when evaluating the ACL2 proof
process (the ``waterfall'') in parallel. Therefore, CCL is the
recommend Lisp for anyone that wants to use parallelism and isn't
working on fixing those problems.
Subtopics
[Compiling-ACL2p]
Compiling ACL2(p)
[Cpu-core-count]
The number of cpu cores
[Parallel]
Evaluating forms in parallel
[Parallel-programming]
Parallel programming in ACL2(p)
[Parallel-proof]
Parallel proof in ACL2(p)
[Parallelism-build]
Building an ACL2 executable with parallel execution enabled
[Set-parallel-execution]
For ACL2(p): enabling parallel execution for four parallelism
primitives
[Set-total-parallelism-work-limit]
For ACL2(p): set thread limit for parallelism primitives
[Set-total-parallelism-work-limit-error]
For ACL2(p): control the action taken when the thread limit is
exceeded
[Set-waterfall-parallelism]
For ACL2(p): configuring the parallel execution of the waterfall
[Set-waterfall-parallelism-hacks-enabled]
For ACL2(p): enable waterfall-parallelism hacks
[Set-waterfall-parallelism-hacks-enabled!]
For ACL2(p): enabling waterfall parallelism hacks
[Set-waterfall-printing]
For ACL2(p): configuring the printing that occurs within the
parallelized waterfall
[Unsupported-parallelism-features]
ACL2 features not supported in ACL2(p)
[Waterfall-parallelism-for-book-certification]
For ACL2(p): using waterfall parallelism during book certification")
(PARALLELISM-AT-THE-TOP-LEVEL
(PARALLEL-PROGRAMMING)
"Parallel execution in the ACL2 top-level loop
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
Calls of parallelism primitives made explicitly in the ACL2 top-level
loop, as opposed to inside function bodies, will never cause
parallel execution. Such calls will either execute with serial
execution or will cause an error; see [set-parallel-execution]. For
a way around this restriction, see [top-level].
Consider for example the following call of [pargs] in the ACL2
top-level loop. Instead of executing pargs, ACL2 macroexpands away
this call, leaving us with serial execution of the arguments to the
[cons] call, or else causes an error (see
[set-parallel-execution]). If there is no error, then
(pargs (cons (expensive-fn-1 4) (expensive-fn-2 5)))
expands into:
(cons (expensive-fn-1 4) (expensive-fn-2 5))
One trivial way to enable parallel execution of a form is to surround
it with a call to macro [top-level]. Consider the following
example.
(top-level (pargs (cons (expensive-fn-1 4) (expensive-fn-2 5))))
Then in an executable image that supports parallel execution --- see
[compiling-ACL2p] for instructions on how to build such an
executable --- (expensive-fn-1 4) and (expensive-fn-2 5) can
evaluate in parallel.
A second way to enable parallel execution of a form is to place it
inside a function body. For example, consider the following
definition.
(defun foo (x y)
(pargs (cons (expensive-fn-1 x) (expensive-fn-2 y))))
Then in an executable image that supports parallel execution,
submission of the form (foo 4 5) can cause parallel execution of
(expensive-fn-1 4) and (expensive-fn-2 5).
Note that [guard]s need not be verified in order to obtain [parallel]
execution. The only restrictions on parallel execution are to use
an ACL2 executable supporting it, to avoid calling parallelism
primitives directly in the top-level loop, to have sufficient
resources (especially, threads) available, and to avoid explicitly
disabling parallel execution (see [set-parallel-execution]).")
(PARALLELISM-BUILD
(PARALLELISM)
"Building an ACL2 executable with parallel execution enabled
See [compiling-ACL2p].")
(PARALLELISM-PERFORMANCE
(PARALLEL-PROGRAMMING)
"Performance issues for parallel execution
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
See [granularity] for an important construct that limits the spawning
of parallel computations, which can be important when a computation
is too short-lived to warrant a separate thread.
There are times in which parallelism provides no speedup because of
garbage collection in the underlying Lisp implementation. The
following example illustrates this phenomenon. If you change the
[granularity] declaration so that the depth bound is 3, 4, or
larger instead of 2, you may still find no speedup. In all cases
you may find that parallelism results in a significantly greater
time spent in garbage collection.
(include-book \"finite-set-theory/osets/sets\" :dir :system)
(defun set::pmergesort-exec (x depth)
(declare (xargs :mode :program))
(cond ((endp x) nil)
((endp (cdr x)) (set::insert (car x) nil))
(t (mv-let (part1 part2)
(set::split-list x nil nil)
(pargs
(declare (granularity (< depth 2)))
(set::union (set::pmergesort-exec part1
(1+ depth))
(set::pmergesort-exec part2
(1+ depth))))))))
(defconst *x* (reverse (fromto 1 400000)))
(time$ (length (set::pmergesort-exec *x* 0)))
(set-parallel-execution nil)
(time$ (length (set::pmergesort-exec *x* 0)))")
(PARALLELISM-TUTORIAL
(PARALLEL-PROGRAMMING)
"A tutorial on how to use the parallelism library.
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
In this topic we introduce the ACL2 parallelism primitives using the
example of a doubly-recursive Fibonacci function, whose basic
definition is as follows. See [parallelism] for a very high-level
summary of the parallelism capability described here, and see
[compiling-ACL2p] for how to build an executable image that
supports parallel execution. Here, we assume that such an
executable is being used.
Serial Fibonacci
(defun fib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
(t (+ (fib (- x 1)) (fib (- x 2))))))
Introducing [Pargs]
A simple way to introduce parallelism into this function definition
is to wrap the addition expression with a call of [pargs], and the
arguments to the addition will be computed in parallel whenever
resources are available. As a result, we end up with a very similar
and thus intuitive function definition. Note that we replaced [+]
by [binary-+], since [pargs] expects a function call, not a macro
call.
(defun pfib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
(t (pargs (binary-+ (pfib (- x 1))
(pfib (- x 2)))))))
Introducing the Granularity Problem
After you submit the above two versions of the Fibonacci function,
test them with the following forms.
(time$ (fib 10))
(time$ (pfib 10))
Now increase the argument by increments of 5 to 10 until you find
your curiosity satisfied or your patience wearing thin. You can
interrupt evaluation if necessary and return to the ACL2 loop. You
will immediately notice that you have not increased execution
speed, at least not by much, by introducing parallelism.
First, consider the computation of (pfib 4). Assuming resources are
available, (pfib 4) will create a thread for computing (pfib 3) and
another thread for (pfib 2). It is easy to imagine that setting up
each thread takes much longer than the entire computation of (fib
4).
Second, we must realize that if we have two threads available for
computing (fib 10), then the evaluation of (fib 8) will probably
complete before the evaluation of (fib 9). Once (fib 8) finishes,
parallelism resources will become available for the next recursive
call made on behalf of (fib 9). If for example that call is (fib
3), we will waste a lot of cycles just handing work to the thread
that does this relatively small computation. We need a way to
ensure that parallelism resources are only used on problems of a
\"large\" size. Ensuring that only \"large\" problems are spawned is
called the ``granularity problem.''
In summary: We want to tell ACL2 that it can evaluate the arguments
of [pargs] in parallel only when the parameter of pfib is greater
than some threshold. Our tests using CCL have suggested that 27 is
a reasonable threshold.
Explicit Programming for the Granularity Problem
One way to avoid the granularity problem is to duplicate code as
follows.
(defun pfib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
(t (if (> x 27) ; the granularity test
(pargs (binary-+ (pfib (- x 1))
(pfib (- x 2))))
(binary-+ (pfib (- x 1))
(pfib (- x 2)))))))
Duplicating code is fundamentally a bad design principle, because it
can double the work for future maintenance. A ``granularity form''
is an expression
(declare (granularity <form>))
that can allow threads to be spawned (without duplicating code)
whenever the evaluation of <form> results in a non-nil value. It
may be placed inside any call of a parallelism primitive, in a
position documentated separately for each primitive. Here is a
definition of pfib using this feature for a call of the parallelism
primitive [pargs].
(defun pfib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
(t (pargs
(declare (granularity (> x 27)))
(binary-+ (pfib (- x 1))
(pfib (- x 2)))))))
Test each version as follows (or substitute your own natural number
for 33).
(time$ (fib 33))
(time$ (pfib 33))
Another Granularity Issue Related to Thread Limitations
Our implementation of parallelism primitives has the property that
once a thread is assigned a computation, that assignment stays in
effect until the computation is complete. In particular, if a
thread encounters a parallelism primitive that spawns child
threads, the parent thread stays assigned, waiting until the child
computations complete before it can continue its own computation.
In the meantime, the parent thread reduces the number of additional
threads that Lisp can provide by 1, rather than being reassigned to
do other work.
How can this lack of reassignment affect the user? Consider, for
example, the application of a recursive function to a long list.
Imagine that this function is written so that the body contains a
recursive call, for example as (pargs (process (car x)) (recur (cdr
x))). Each such [pargs] call that spawns child work must wait for
its children, one of which is the work of evaluating (recur (cdr
x)), to complete. There is an ACL2 limit on how much pending work
can be in the system, limiting the number of [pargs] calls that can
result in parallel execution. For example, if the ACL2 limit is k
and each call of [pargs] actually spawns threads for evaluating its
arguments, then after k cdrs there will be no further parallel
execution.
Possible solutions may include reworking of algorithms (for example
to be tree-based rather than list-based) or using appropriate
granularity forms. We hope that future implementations will allow
thread ``re-deployment'' in order to mitigate this problem. This
problem applies to [plet], [pargs], [pand], [por], and
[spec-mv-let].
Introducing [Plet]
We can use a [let] binding to compute the recursive calls of fib and
then add the bound variables together, as follows.
(defun fib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
(t (let ((a (fib (- x 1)))
(b (fib (- x 2))))
(+ a b)))))
By using the parallelism primitive [plet], we can introduce
parallelism much as we did using [pargs], with an optional
granularity form, as follows.
(defun pfib (x)
(declare (xargs :guard (natp x)))
(cond ((or (zp x) (<= x 0)) 0)
((= x 1) 1)
(t (plet
(declare (granularity (> x 27)))
((a (pfib (- x 1)))
(b (pfib (- x 2))))
(+ a b)))))
Notice that this time, we were able to use + rather than being forced
to use binary-+. Unlike [pargs], which expects a function call (not
a macro call), [plet] allows macros at the top level of its body.
Introducing [Pand] (By Way of a Tree Validation Example)
Consider ``genetic trees'' that contains leaves of DNA elements, in
the sense that each tip is one of the symbols A, G, C, or T. First
we define the function valid-tip which recognizes whether a tip
contains one of these symbols.
(defun valid-tip (tip)
(declare (xargs :guard t))
(or (eq tip 'A)
(eq tip 'G)
(eq tip 'C)
(eq tip 'T)))
Now we define a function that traverses the tree, checking that every
tip is valid.
(defun valid-tree-serial (tree)
(declare (xargs :guard t))
(if (atom tree)
(valid-tip tree)
(and (valid-tree-serial (car tree))
(valid-tree-serial (cdr tree)))))
We also define a parallel version.
(defun valid-tree-parallel (tree)
(declare (xargs :guard t))
(if (atom tree)
(valid-tip tree)
(pand (valid-tree-parallel (car tree))
(valid-tree-parallel (cdr tree)))))
Before we can time the functions, we need to create test trees. We
have found that test trees need to be approximately 1 gigabyte
before we clearly see speedup, and we make them asymmetric to
demonstrate the ability of our implementation to adapt to
asymmetric data. We can create the trees with the execution of the
following forms.
(defun make-valid-binary-tree (x)
(declare (xargs :mode :program))
(if (< x 0)
(cons (cons 'C 'G) (cons 'A 'T))
(cons (make-valid-binary-tree (- x 2)) ; 2 to make asymmetric
(make-valid-binary-tree (- x 1)))))
(defconst *valid-tree* (make-valid-binary-tree 30)) ; takes awhile
(defconst *invalid-tree* (cons *valid-tree* nil)) ; nil is invalid tip
We can time our functions with the forms:
(time$ (valid-tree-serial *valid-tree*))
(time$ (valid-tree-parallel *valid-tree*))
Unfortunately, the serial version runs faster than the parallelism
version; however, there is more to this story.
Demonstrating Early Termination with an Invalid Tree
Now observe this magic:
(time$ (valid-tree-serial *invalid-tree*))
(time$ (valid-tree-parallel *invalid-tree*))
The serial version took awhile, while the parallel version finished
almost immediately. The test for validation was split into testing
the [car] and the [cdr] of the *invalid-tree* root, and since the
cdr was equal to nil, its test returned immediately. This immediate
return quickly interrupted the computation associated with the car,
and returned the result.
Granularity with [Pand]
We can also define a parallel version with a granularity form:
(defun valid-tree-parallel (tree depth)
(declare (xargs :guard (natp depth)))
(if (atom tree)
(valid-tip tree)
(pand
(declare (granularity (< depth 5)))
(valid-tree-parallel (car tree) (1+ depth))
(valid-tree-parallel (cdr tree) (1+ depth)))))
We can test this form by executing our previous forms. You will
probably find some speedup on a machine with several cores
available, but more speedup can likely be obtained with an
expensive test on the leaves in place of valid-tip.
(time$ (valid-tree-serial *valid-tree*))
(time$ (valid-tree-parallel *valid-tree* 0))
Introducing [Por]
[Por] can be used in the same way as [pand], but with early
termination occurring when an argument evaluates to a non-nil
value, in which case the value returned is t. Finally, [por] also
supports the use of a [granularity] form.")
(PARGS
(PARALLEL-PROGRAMMING ACL2-BUILT-INS)
"Parallel evaluation of arguments in a function call
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism],
and see [parallel-programming], which has a disclaimer.
Example Forms:
(pargs (binary-+ (fibonacci (- x 1)) (fibonacci (- x 2))))
(pargs (declare (granularity (> x 35)))
(binary-+ (fibonacci (- x 1)) (fibonacci (- x 2))))
General Form:
(pargs (declare (granularity expr)) ; optional granularity declaration
(f arg1 ... argN))
where N >= 0 and each argi and expr are arbitrary terms. Logically,
pargs is just the identity macro, in the sense that the above forms
can logically be replaced by (f arg1 ... argN). However, this pargs
form may parallelize the evaluation of arguments arg1 through argN
before applying function f to those results. If the above
[granularity] declaration is present, then its expression (expr
above) is first evaluated, and if the result is nil, then such
parallelism is avoided. Even if parallelism is not thus avoided,
parallelism may be limited by available resources.
Since macros can change expressions in unexpected ways, it is illegal
to call pargs on a form that is a macro call. To parallelize
computation of arguments to a macro, see [plet].
See [parallelism-at-the-top-level] for restrictions on evaluating
parallelism primitives from within the ACL2 top-level loop.")
(PATHNAME
(BOOKS-REFERENCE)
"Introduction to filename conventions in ACL2
The notion of pathname objects from Common Lisp is not supported in
ACL2, nor is the function pathname. However, ACL2 supports file
operations, using conventions for naming files based on those of
the Unix (trademark of AT&T) operating system, so that the
character / is used to terminate directory names. Some file names
are ``absolute'' (complete) descriptions of a file or directory;
others are ``relative'' to the current working directory or to the
connected book directory (see [cbd]). We emphasize that even for
users of Windows-based systems or Macintosh computers, ACL2 file
names are in the Unix style. We will call these ACL2 pathnames,
often omitting the ``ACL2.''
Pathnames starting with the directory separator (/) or the tilde
character (~) are absolute pathnames. All other pathnames are
relative pathnames. An exception is in the Microsoft Windows
operating system, where it is illegal for the pathname to start
with a tilde character but the drive may be included, e.g.,
\"c:/home/smith/acl2/book-1.lisp\". In fact, the drive must be
included in the portcullis of a book; see [portcullis]. Note also
that some host Common Lisps will not support pathnames starting
with \"~\", for example ~smith, though ACL2 will generally support
those starting with \"~/\" regardless of the host Common Lisp.
Consider the following examples. The filename string
\"/home/smith/acl2/book-1.lisp\"
is an absolute pathname, with top-level directory \"home\", under that
the directory \"smith\" and then the directory \"acl2\", and finally,
within that directory the file \"book-1.lisp\". If the connected book
directory is \"/home/smith/\" (see [cbd]), then the filename string
above also corresponds to the relative filename string
\"acl2/book1.lisp\".
Finally, we note that (on non-Windows systems) the pathname \"~\" and
pathnames starting with \"~/\" are illegal in books being certified.
Otherwise, a subsidiary [include-book] form would have a different
meaning at certification time than at a later time when the
certified book is included by a different user.")
(PATTERNED-CONGRUENCE
(RULE-CLASSES)
"Removing restrictions on classic [congruence] rules
This topic assumes familiarity with the basics of congruence rules;
see [congruence].
We begin our discussion by showing some patterned congruence rules
and using them to illustrate some terminology.
Example forms:
; ``Shallow'' patterned congruence rule:
(implies (e1 y1 y2)
(e2 (f1 3 y1 (cons x x))
(f1 3 y2 (cons x x))))
; ``Deep'' patterned congruence rule:
(implies (e1 y1 y2)
(e2 (mv-nth 1 (foo x y1 z))
(mv-nth 1 (foo x y2 z))))
; ``Deep'' patterned congruence rule:
(implies (e1 y1 y2)
(e2 (mv-nth 1 (foo x (g y1) z))
(mv-nth 1 (foo x (g y2) z))))
In the example forms above, e1 and e2 are known equivalence
relations, which (as for classic congruence rules) we call the
``inner'' and ``outer'' equivalences. The examples above are not
classic, because the ``function symbol'' of the rule --- f1 in the
first example, mv-nth in the second and third examples --- is not
being applied to distinct variables. The first example is called
``shallow'' because the ``variable'' of the rule, y1, is a
top-level argument of the ``lhs'' of the rule, which is the first
call of f1; the others do not have this property, as y1 is buried
under further function calls.
We invite you to browse the community book
demos/patterned-congruences.lisp, which provides several examples
of patterned congruence rules and their use, as well as several
examples of formulas that are illegal as patterned congruence rules
for various reasons.
We now define the class of patterned congruence rules. The general
form of a patterned congruence rule is
(implies (equiv1 x y)
(equiv2 lhs rhs)),
where the rule is not classic (see [congruence]) and the following
conditions hold. Equiv1 and equiv2 are known equivalence relations,
which (as in the classic case) we call the ``inner'' and ``outer''
equivalences, respectively. The terms lhs and rhs are function
calls, and we call these the lhs and rhs of the rule, respectively.
The variable x occurs in lhs and the variable y occurs in rhs.
These must be the only occurrences of x and y in either lhs or rhs,
and rhs must be the result of substituting y for x in lhs. None of
the following may occur as a function symbol of lhs (or,
equivalently, rhs): if, implies, equal, or a [lambda].
Patterned congruence rules are used, much like classic congruence
rules, by the ACL2 rewriter to determine which equivalence
relations to maintain as it dives into a term. Recall (see
[congruence]) that if it suffices for the rewriter to maintain e2
when rewriting a term, then it suffices to maintain e1 when
rewriting an argument of that term provided there is an applicable
congruence rule with outer equivalence e2 and inner equivalence e1.
An analogous principle holds for patterned congruence rules, which
by the way consider refinements of the outer equivalence just as is
done by classic congruence rules. But there is a new wrinkle
because the lhs of a patterned congruence rule is a function call
that can have non-variable arguments. Consider the following
events.
(defun e1 (x y)
(equal x y))
(defequiv e1)
(defun f10 (x)
(list 3 x x))
(defun f11 (x y)
(declare (ignore y))
x)
(defthm e1-implies-iff-f11-cong-2
(implies (e1 y1 y2)
(iff (f11 (f10 x) y1)
(f11 (f10 x) y2)))
:rule-classes (:congruence))
(in-theory (disable f11 (:t f11) e1))
The following proof fails, because the indicated call of f10 expands
before the rewriter is applied to b2 --- otherwise b2 would rewrite
to b1 because (e1 b1 b2) is known in that context and by the rule
above, it suffices to maintain e1 when rewriting b2.
(thm (implies (e1 b1 b2)
(iff (f11 (f10 a)
b1)
(f11 (f10 a) ; expands before b2 is rewritten
b2))))
On the other hand, the following succeeds because the rewrite
discussed above does indeed take place when the indicated call of
f10 does not expand.
(thm
(implies (e1 b1 b2)
(iff (f11 (f10 a)
b1)
(f11 (f10 a) ; does not expand
b2)))
:hints ((\"Goal\" :in-theory (disable f10))))
This inherent sequentiality of matching is important for soundness,
as is illustrated by examples using the function some-consp in the
aforementioned community book, demos/patterned-congruences.lisp.
The example above illustrates the following point: as the rewriter
dives into a term, then when matching is attempted using a
patterned congruence rule, rewriting has already taken place to the
left of the current subterm. By contrast, note that this pass
through the rewriter will not yet have completed rewriting of terms
to the right of the current subterm when matching a patterned
congruence rule.
Patterned congruence rules are used primarily during the process of
rewriting. In particular, unlike classic congruence rules, they are
not used to do equality substitution at the goal level. The
simplest way to understand this point may be with the following
trivial example.
(defstub foo (x y z) t)
(thm (implies (equal u (* a b))
(foo u u b)))
The theorem fails, of course, but what is interesting is that ACL2
simplifies it by replacing the variable u by the term (* a b)
throughout the goal and then dropping the equality, to produce the
following goal.
(FOO (* A B) (* A B) B)
This sort of substitution can also be made when equal is replaced by
a known equivalence relation, if a classic congruence rule for foo
justifies the substitution. But that is not the case for our
implementation of patterned congruence rules.
The discussion above is intended to suffice for effective use of
patterned congruence rules. If you are interested in their
implementation, we invite you to read the long comment entitled
``Essay on Patterned Congruences and Equivalences'' in ACL2 source
file rewrite.lisp.")
(PBT
(HISTORY)
"Print the [command]s back through a [command] descriptor
Examples:
:pbt :max ; print back through the most recent command
:pbt :x ; print back through the most recent command
:pbt fn ; print back through the introduction of fn
:pbt 5 ; print back through the fifth command executed
:pbt (:x -4) ; print back through the most recent five commands
See [command-descriptor].
Pbt takes one argument, a [command] descriptor, and prints the
[command]s from :max (aka :x) through the one described. See
[command-descriptor] for a description of what a [command]
descriptor is. See [pc] for a description of the format used to
display [command]s. Pbt will print the [command]s that [ubt] will
undo.")
(PC
(HISTORY)
"Print the [command] described by a [command] descriptor
Examples:
:pc 3 ; print the third command executed
:pc :max ; print the most recent command
:pc :x ; print the most recent command
:pc fn ; print the command that introduced fn
See [command-descriptor].
Pc takes one argument, a [command] descriptor, and prints the
[command] identified by that descriptor, doing so in full unless
the [ld-evisc-tuple] is non-nil, in which case it abbreviates using
that evisc-tuple; see [evisc-tuple]. See [command-descriptor]. For
example:
ACL2 !>:pc foo
LVd 52 (DEFUN FOO (X) X)
Pc always prints a space first, followed by four (possibly blank)
[characters] (``LVd'' above) explained below. Then pc prints the
[command] number, a number uniquely identifying the [command]'s
position in the sequence of [command]s since the beginning of the
user's session. Finally, the [command] itself is printed.
While pc always prints a space first, some [history] [command]s, for
example :[pcs] and :[pe], use the first column of output to delimit
a region of [command]s or to point to a particular event (perhaps
as modified using [extend-pe-table]) within a [command].
For example, :pcs 52 54 will print something like
/LVd 52 (DEFUN FOO (X) X)
LV 53 (DEFUN BAR (X) (CONS X X))
\\ 54 (DEFTHM FOO-BAR (EQUAL (CAR (BAR X)) (FOO X)))
: ...
127 (DEFUN LATEST (X) X)
Here, the two slash [characters] in the first column are intended to
suggest a bracket delimiting [command]s 52 through 54. The last
[command] printed by [pcs] is always the most recent [command],
i.e., the [command] at :here, and is separated from the rest of the
display by an elipsis if some [command]s are omitted.
Similarly, the :[pe] [command] will print a particular event (perhaps
as modified using [extend-pe-table]) within a [command] block and
will indicate that event by printing a ``[>]'' in the first column.
The symbol is intended to be an arrow pointing at the event in
question.
For example, :[pe] true-listp-app might print:
1 (INCLUDE-BOOK \"list-book\")
\\
> (DEFTHM TRUE-LISTP-APP
(EQUAL (TRUE-LISTP (APP A B)) (TRUE-LISTP B)))
using the arrow to indicate the event itself. The slash printed to
connect the [command], [include-book], with the event, [defthm], is
intended to suggest a tree branch indicating that the event is
inferior to (and part of) the [command].
The mysterious [characters] sometimes preceding a [command] have the
following interpretations. The first two have to do with the
function symbols introduced by the [command] and are blank if no
symbols were introduced.
At any time we can classify our function symbols into disjoint sets,
which we will here name with [characters]. The ``P'' functions are
those in :[program] mode. The ``L'' functions are those in :[logic]
mode whose [guard]s have not been verified. The ``V'' functions are
those in :[logic] mode whose [guard]s have been verified. You may
also see the use of (lower-case) ``v'' to indicate functions
introduced by [encapsulate]. Note that [verify-termination] and
[verify-guards] cause function symbols to be reclassified. If a
[command] introduces function symbols then the first mysterious
character indicates the class of the symbols at the time of
introduction and the second character indicates the current class
of the symbols (if the current class is different from the
introductory class).
Thus, the display
PLd 52 (DEFUN FOO (X) X)
tells us that [command] 52 introduced a :[program] function but that
some [command] after 52 changed its mode to :[logic] and that the
[guard]s of foo have not been verified. That is, foo's termination
has been verified even though it was not verified as part of the
[command] that introduced foo. Had a subsequent [command] verified
the [guard]s of foo, the display would contain a V where the L is.
The display
P d 52 (DEFUN FOO (X) X)
indicates that foo was introduced in :[program] mode and still is in
that mode.
The third character indicates the [enable]d/[disable]d status of the
[rune]s introduced by the [command]. If the status character is
blank then all the [rune]s (if any) introduced are [enable]d. If
the status character is ``D'' then some [rune]s were introduced and
they are all [disable]d. If the status character is ``d'' then at
least one, but not all, of the [rune]s introduced is [disable]d.
Thus, in the display
L d 52 (DEFUN FOO (X) X)
we see that some [rune] introduced by [command] 52 is [disable]d. As
noted in the documentation for [rune], a [defun] [command]
introduces many [rune]s, e.g., the axiomatic definition rule,
(:definition fn), the executable counterpart rule,
(:executable-counterpart fn), and [type-prescription]s,
(:type-prescription fn). The display above does not say which of
the [rune]s based on foo is [disable]d, but it does tell us one of
them is; see [disabledp] for how to obtain the disabled runes for a
given function symbol.
Remark for users of the [break-rewrite] utility. Inside the :[brr]
loop, the status character shows whether rules are disabled at the
current point of the proof that is currently underway, rather than
whether rules are disabled globally. For example, if you break
while the prover is working on Subgoal 3, and the [hints] supplied
for the proof specify (\"Subgoal 3\" :in-theory (disable foo)), then
regardless of whether or not rules associated with foo are enabled
globally, the status character indicates whether they are enabled
while processing Subgoal 3.
Finally, a fourth character is printed, indicating whether functions
are [memoize]d. A symbol may be memoized if it is a function symbol
that is not constrained (i.e., introduced by [defchoose] or in the
[signature] of an [encapsulate] event). If the command introduces
no symbol that may be memoized, then a space is printed. Otherwise,
if every memoizable symbol is memoized, an ``M'' is printed.
Otherwise, an ``m'' is printed.")
(PCB
(HISTORY)
"Print the [command] block described by a [command] descriptor
Examples:
:pcb :max ; print the most recent command block
:pcb :x ; print the most recent command block
:pcb fn ; print the command block that introduced fn
:pcb 5 ; print the fifth command block
See [command-descriptor].
Pcb takes one argument, a [command] descriptor, and prints in an
abbreviated format the [command] block of the [command] described.
See [command-descriptor] for details of [command] descriptors. See
[pc] for description of the format in which [command]s are
displayed. The [command] block of a [command] consists of the
[command] itself and all of the [events] it created. If the
[command] created a single event and that event is in fact the
[command] (i.e., if the [command] typed was just an event such as a
[defun] or [defthm] rather than a macro that expanded to some event
forms), then pcb just prints the [command] (unless the event is
replaced using [extend-pe-table]). Pcb sketches [command] and all
of the [events] it created, rather than printing them fully. If you
wish to see just the [command], in its entirety, use [pc]. If you
wish to see one of the [events] within the block, in its entirety,
use [pe]. If you wish to see the [command] sketched and all of the
[events] it created, in their entirety, use [pcb!].")
(PCB!
(HISTORY)
"Print in full the [command] block described by a [command] descriptor
Examples:
:pcb! :max ; print the most recent command block
:pcb! :x ; print the most recent command block
:pcb! fn ; print the command block that introduced fn
:pcb! 5 ; print the fifth command block
See [command-descriptor].
Pcb! takes one argument, a [command] descriptor, and prints the
[command] block of the [command] described. Unlike [pcb], pcb!
prints the event forms in full (see [pcb] for details) --- unless
the [ld-evisc-tuple] is non-nil, in which case it abbreviates using
that evisc-tuple; see [evisc-tuple].")
(PCS
(HISTORY)
"Print the sequence of [command]s between two [command] descriptors
Examples:
:pcs 1 5 ; print commands 1 through 5
:pcs 5 1 ; same as above
:pcs :x (:x -3) ; print the 3 most recently executed commands
:pcs fn assoc-of-fn ; print the commands between the one that introduced
; fn and the one that introduced assoc-of-fn
Pcs takes two arguments, both of which are [command] descriptors, and
prints the [command]s between them with [pc]. The order of the two
descriptors is irrelevant. See [command-descriptor] for a
description of [command] descriptors. See [pc] for a description of
the format in which [command]s are displayed.
For a related utility that simply returns a sequence of commands, see
[get-command-sequence].")
(PE
(HISTORY)
"Print the events named by a logical name
Example:
:pe fn ; sketches the command that introduced fn and
; prints in full the event within it that created fn.
See [logical-name].
Pe takes one argument, a logical name, and prints the event
corresponding to the name, doing so in full unless the
[ld-evisc-tuple] is non-nil, in which case it abbreviates using
that evisc-tuple; see [evisc-tuple]. Pe also sketches the [command]
responsible for that event if the [command] is different from the
event itself. See [pc] for a description of the format used to
display a [command]. To remind you that the event is inferior to
the [command], i.e., you can only undo the entire [command], not
just the event, the event is indented slightly from the [command]
and a slash (meant to suggest a tree branch) connects them.
If the given logical name corresponds to more than one event, then
:pe will print the above information for every such event. Here is
an example of such behavior.
ACL2 !>:pe nth
-4270 (ENCAPSULATE NIL ...)
\\
>V (VERIFY-TERMINATION NTH)
Additional events for the logical name NTH:
PV -4949 (DEFUN NTH (N L)
\"Documentation available via :doc\"
(DECLARE (XARGS :GUARD (AND (INTEGERP N)
(>= N 0)
(TRUE-LISTP L))))
(IF (ENDP L)
NIL
(IF (ZP N)
(CAR L)
(NTH (- N 1) (CDR L)))))
ACL2 !>
If you prefer to see only the formula for the given name, for example
if it is part of a large [mutual-recursion], see [pf].
See [extend-pe-table] for a way to specify a form to be printed in
place of the actual event. To avoid such replacement, see [pe!].")
(PE!
(HISTORY)
"Print events as with [pe] but ignoring the [pe-table]
This alternative to [pe] temporarily clears the [pe-table] so that
original [events] are displayed.")
(PE-TABLE (POINTERS)
"See [extend-pe-table].")
(PEEK-CHAR$ (POINTERS) "See [io].")
(PERHAPS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Perhaps
The theorem prover's proof is printed in real time. At the time it
prints ``Perhaps'' it does not know the proof will succeed.")
(PF
(HISTORY)
"Print the formula corresponding to the given name
Examples:
:pf (:definition fn) ; prints the definition of fn as an equality
:pf fn ; same as above
:pf (:rewrite foo) ; prints the statement of the rewrite rule foo
:pf foo ; same as above
pf takes one argument, an event name or a [rune], and prints the
formula associated with name. If the argument is the name of a
macro associated with a function name by [macro-aliases-table],
then the function name is used as the argument.")
(PKG-IMPORTS
(PACKAGES)
"List of symbols imported into a given package
Completion Axiom (completion-of-pkg-imports):
(equal (pkg-imports x)
(if (stringp x)
(pkg-imports x)
nil))
[Guard] for (pkg-imports x):
(stringp x)
(Pkg-imports pkg) returns a duplicate-free list of all symbols
imported into pkg, which should be the name of a package known to
ACL2. For example, suppose \"MY-PKG\" was created by
(defpkg \"MY-PKG\" '(ACL2::ABC LISP::CAR)).
Then (pkg-imports \"MY-PKG\") equals the list (ACL2::ABC LISP::CAR).
If pkg is not a string, then (pkg-imports pkg) is nil. If pkg is a
string but not the name of a package known to ACL2, then the value
of the form (pkg-imports pkg) is unspecified, and it evaluation
will fail to yield a value. By ``the symbols imported into pkg'' we
mean the symbols imported into pkg by the [defpkg] event that
introduced pkg. There are no imports for built-in packages except
for the \"ACL2\" package, which imports the symbols in the list value
of the constant *common-lisp-symbols-from-main-lisp-package*. In
particular, this is the case for the \"COMMON-LISP\" package. Users
familiar with Common Lisp may find this surprising, since in actual
Common Lisp implementations it is often the case that many symbols
in that package are imported from other packages. However, ACL2
treats all symbols in the constant
*common-lisp-symbols-from-main-lisp-package* as having a
[symbol-package-name] of \"COMMON-LISP\", as though they were not
imported. ACL2 admits a symbol imported into in the \"COMMON-LISP\"
package only if it belongs to that list: any attempt to read any
other symbol imported into the \"COMMON-LISP\" package, or to produce
such a symbol with [intern$] or [intern-in-package-of-symbol], will
cause an error.
The following axioms formalize properties of pkg-imports discussed
above (use :[pe] to view them).
symbol-package-name-intern-in-package-of-symbol
intern-in-package-of-symbol-is-identity
symbol-listp-pkg-imports
no-duplicatesp-pkg-imports
completion-of-pkg-imports")
(PKG-WITNESS
(PACKAGES ACL2-BUILT-INS)
"Return a specific symbol in the indicated package
For any string pkg that names a package currently known to ACL2,
(pkg-witness pkg) is a symbol in that package whose [symbol-name]
is the value of constant *pkg-witness-name*. Logically, this is the
case even if the package is not currently known to ACL2. However,
if pkg-witness is called on a string that is not the name of a
package known to ACL2, a hard Lisp error will result.
(Pkg-witness pkg) has a guard of (and (stringp pkg) (not (equal pkg
\"\"))). If pkg is not a string, then (pkg-witness pkg) is equal to
(pkg-witness \"ACL2\")")
(PL
(HISTORY)
"Print the rules for the given name or term
Examples:
:pl foo ; prints rules that rewrite some call of foo
:pl (+ x y) ; prints rules that rewrite (+ x y)
Also see [pl2], which restricts output to rules that you specify for
a given term.
Pl takes one argument, which should be a symbol or a term.
First suppose that the argument is a symbol. Then it should be either
a function symbol or else a macro alias for a function symbol (see
[macro-aliases-table]), which is treated as the corresponding
function symbol. In this case :pl displays rules that apply to
terms whose top function symbol is the one specified, specifically,
rules of class :[rewrite], :[definition], :[meta], :[linear],
:[type-prescription], :[forward-chaining], :[elim], and
:[induction].
Otherwise the argument should be a term (in user syntax, so that for
example macros are permitted). In this case, :pl displays the
:[rewrite], :[definition], and :meta rules that rewrite the
specified term, followed by the applicable :[type-prescription]
rules. Each rule is displayed with additional information, such as
the hypotheses that remain after applying some simple techniques to
discharge them that are likely to apply in any context. Note that
for :[meta] rules, only those are displayed that meet two
conditions: the application of the metafunction returns a term
different from the input term, and if there is a hypothesis
metafunction then it also returns a term. (A subtlety: In the case
of extended metafunctions (see [extended-metafunctions]), a trivial
metafunction context is used for the application of the
metafunction.)
Note that some rule classes are not handled by :pl. In particular, if
you want to see all :[clause-processor] rules, issue the command
:print-clause-processor-rules, and for trusted clause-processors,
(table trusted-clause-processor-table); see [clause-processor] and
see [define-trusted-clause-processor].")
(PL2
(HISTORY)
"Print rule(s) for the given form
Examples:
:pl2 (+ x y) nil ; prints rules that apply to (+ x y)
:pl2 (+ x y) foo ; prints rules named foo that apply to (+ x y)
:pl2 (+ x y) (:rewrite foo) ; if the rule with rune (:rewrite foo) applies
; to (+ x y), then print it
:pl2 (+ x y) (:type-prescription foo)
; as above, but for the indicated
; type-prescription rule
Pl2 takes two arguments. The first is a term. The second is either
nil or a ``rule-id'' that is either a symbol or a [rune]. The
result is to print rules of class :[rewrite], :[definition], :meta,
:[linear], and :[type-prescription] that apply to the given term.
Indeed, :pl2 prints exactly what is printed by applying :[pl] to
the first argument --- see [pl] --- except that if the second
argument is not nil then it is used to filter the rules printed, as
follows.
If the rule-id is a symbol, then only rules whose name is that symbol
will be printed.
If the rule-id is a [rune], then at most one rule will be printed:
the rule named by that rune (if the rule would be printed by
:[pl]).")
(PLET
(PARALLEL-PROGRAMMING ACL2-BUILT-INS)
"Parallel version of [let]
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism],
and see [parallel-programming], which has a disclaimer.
Example Forms:
(plet ((a (fibonacci (- x 1)))
(b (fibonacci (- x 2))))
(+ a b))
(plet (declare (granularity (> x 35)))
((a (fibonacci (- x 1)))
(b (fibonacci (- x 2))))
(+ a b))
General Form:
(plet (declare (granularity expr)) ; optional granularity declaration
((var1 val1)
...
(varN valN))
(declare ...) ... (declare ...) ; optional declarations
body)
The syntax of plet is identical to the syntax of [let], except that
plet permits an optional granularity declaration in the first
argument position; see [granularity]. In the logic a call of plet
macroexpands to the corresponding call of [let], where the
granularity declaration (if any) is dropped.
Plet cause the evaluation of each vali above to be done in parallel
before processing the body. If the above [granularity] declaration
is present, then its expression (expr above) is first evaluated,
and if the result is nil, then such parallelism is avoided. Even if
parallelism is not thus avoided, parallelism may be limited by
available resources.
See [parallelism-at-the-top-level] for restrictions on evaluating
parallelism primitives from within the ACL2 top-level loop.")
(PLUSP
(NUMBERS ACL2-BUILT-INS)
"Test whether a number is positive
(Plusp x) is true if and only if x > 0.
The [guard] of plusp requires its argument to be a rational ([real],
in ACL2(r)) number.
Plusp is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <plusp>
(defun plusp (x)
(declare (xargs :guard (real/rationalp x)))
(> x 0))")
(POINTERS
(DOCUMENTATION)
"Links pointing to relevant documentation topics
Subtopics
[&allow-other-keys]
See [macro-args].
[&body]
See [macro-args].
[&key]
See [macro-args].
[&optional]
See [macro-args].
[&rest]
See [macro-args].
[&whole]
See [macro-args].
[Accumulated-persistence-oops]
See [accumulated-persistence].
[ACL2s]
See [ACL2-sedan].
[Add-ld-keyword-alias]
See [ld-keyword-aliases].
[Add-ld-keyword-alias!]
See [ld-keyword-aliases].
[Add-to-set-eq]
See [add-to-set].
[Add-to-set-eql]
See [add-to-set].
[Add-to-set-equal]
See [add-to-set].
[Apropos]
See [finding-documentation].
[Assoc-eq]
See [assoc].
[Assoc-equal]
See [assoc].
[Backchain-limit-rw]
See [hints] for keyword :backchain-limit-rw.
[Backtrack]
See [hints] for keyword :backtrack.
[Book-makefiles]
See [books-certification].
[By]
See [hints] for keyword :by.
[Cases]
See [hints] for keyword :cases.
[Certifying-books]
See [books-certification].
[Check-invariant-risk]
See [set-check-invariant-risk].
[Close-input-channel]
See [io].
[Close-output-channel]
See [io].
[Default-verify-guards-eagerness]
See [set-verify-guards-eagerness].
[Delete-assoc-eq]
See [delete-assoc].
[Delete-assoc-equal]
See [delete-assoc].
[Do-not-induct]
See [hints] for keyword :do-not-induct.
[Dynamically-monitor-rewrites]
See [dmr].
[Expand]
See [hints] for keyword :expand.
[External-format]
See [character-encoding].
[Fake-rune]
See [rune].
[Fast-alist]
See [fast-alists].
[Fms!-to-string]
See [printing-to-strings].
[Fms-to-string]
See [printing-to-strings].
[Fmt!-to-string]
See [printing-to-strings].
[Fmt-to-string]
See [printing-to-strings].
[Fmt1!-to-string]
See [printing-to-strings].
[Fmt1-to-string]
See [printing-to-strings].
[Fncall-term]
See [meta-extract].
[Forced]
See [force].
[Gcs]
See [get-command-sequence].
[Get-check-invariant-risk]
See [set-check-invariant-risk].
[Get-output-stream-string$]
See [io].
[Getting-started]
See [ACL2-tutorial].
[Guard-hints]
See [xargs] for keyword :guard-hints.
[Guard-msg-table]
See [set-guard-msg].
[Guards]
See [guard].
[Hands-off]
See [hints] for keyword :hands-off.
[If-intro]
See [splitter].
[Ignorable]
See [declare].
[Ignore]
See [declare].
[Immed-forced]
See [splitter].
[Induct]
See [hints] for keyword :induct.
[Inline]
See [defun-inline].
[Intersection-eq]
See [intersection$].
[Intersection-equal]
See [intersection$].
[Intersectp-eq]
See [intersectp].
[Intersectp-equal]
See [intersectp].
[Iprint]
See [set-iprint].
[Iprinting]
See [set-iprint].
[Keyword]
See [keywordp].
[Lambda]
See [term].
[Measure]
See [xargs] for keyword :measure.
[Measure-theorem]
See [termination-theorem].
[Member-eq]
See [member].
[Member-equal]
See [member].
[Memoization]
See [memoize].
[Meta-extract-contextual-fact]
See [meta-extract].
[Meta-extract-formula]
See [meta-extract].
[Meta-extract-global-fact]
See [meta-extract].
[Meta-extract-global-fact+]
See [meta-extract].
[Meta-extract-rw+-term]
See [meta-extract].
[Mode]
See [xargs] for keyword :mode.
[No-duplicatesp-eq]
See [no-duplicatesp].
[No-duplicatesp-equal]
See [no-duplicatesp].
[No-thanks]
See [hints] for keyword :no-thanks.
[Non-executable]
See [xargs] for keyword :non-executable.
[Nonlinearp]
See [hints] for keyword :nonlinearp.
[Normalize]
See [xargs] for keyword :normalize.
[Observation-cw]
See [observation].
[Open-input-channel]
See [io].
[Open-input-channel-p]
See [io].
[Open-output-channel]
See [io].
[Open-output-channel-p]
See [io].
[Optimize]
See [declare].
[Package]
See [packages].
[Pe-table]
See [extend-pe-table].
[Peek-char$]
See [io].
[Position-eq]
See [position].
[Position-equal]
See [position].
[Print-object$]
See [io].
[Print-summary-user]
See [finalize-event-user].
[Proof-supporters-alist]
See [dead-events].
[Put-assoc-eq]
See [put-assoc].
[Put-assoc-eql]
See [put-assoc].
[Put-assoc-equal]
See [put-assoc].
[Rassoc-eq]
See [rassoc].
[Rassoc-equal]
See [rassoc].
[Read-byte$]
See [io].
[Read-char$]
See [io].
[Read-object]
See [io].
[Regression]
See [books-certification].
[Remove-duplicates-eq]
See [remove-duplicates].
[Remove-duplicates-equal]
See [remove-duplicates].
[Remove-eq]
See [remove].
[Remove-equal]
See [remove].
[Remove1-eq]
See [remove1].
[Remove1-equal]
See [remove1].
[Reorder]
See [hints] for keyword :reorder.
[Reset-print-control]
See [print-control].
[Restrict]
See [hints] for keyword :restrict.
[Rw-cache]
See [set-rw-cache-state].
[Saving-and-restoring]
See [save-exec].
[Set-accumulated-persistence]
See [accumulated-persistence].
[Set-difference-eq]
See [set-difference$].
[Set-difference-equal]
See [set-difference$].
[Set-ld-keyword-aliases]
See [ld-keyword-aliases].
[Set-ld-keyword-aliases!]
See [ld-keyword-aliases].
[Set-ld-redefinition-action]
See [ld-redefinition-action].
[Set-ld-skip-proofs]
See [ld-skip-proofsp].
[Set-ld-skip-proofsp]
See [ld-skip-proofsp].
[Set-let*-abstraction]
See [set-let*-abstractionp].
[Set-non-linear]
See [set-non-linearp].
[Set-print-circle]
See [print-control].
[Set-print-escape]
See [print-control].
[Set-print-length]
See [print-control].
[Set-print-level]
See [print-control].
[Set-print-lines]
See [print-control].
[Set-print-readably]
See [print-control].
[Set-print-right-margin]
See [print-control].
[Set-ruler-extenders]
See [ruler-extenders].
[Set-serialize-character]
See [with-serialize-character].
[Show-accumulated-persistence]
See [accumulated-persistence].
[Single-threaded-objects]
See [stobj].
[Split-types]
See [xargs] for keyword :split-types.
[Stable-under-simplificationp]
See [computed-hints].
[Stobj-let]
See [nested-stobjs].
[Stobjs]
See [xargs] for keyword :stobjs.
[Subsetp-eq]
See [subsetp].
[Subsetp-equal]
See [subsetp].
[Trust-tag]
See [defttag].
[Ttag]
See [defttag].
[Type]
Disambiguation page for type-related concepts.
[Typespec-check]
See [meta-extract].
[Union-eq]
See [union$].
[Union-equal]
See [union$].
[Untranslate]
See [user-defined-functions-table].
[Untranslate-preprocess]
See [user-defined-functions-table].
[Use]
See [hints] for keyword :use.
[Verify-guards-eagerness]
See [set-verify-guards-eagerness].
[Waterfall]
See [hints-and-the-waterfall].
[Write-byte$]
See [io].")
(POPPING_OUT_OF_AN_INDUCTIVE_PROOF
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Popping out of an Inductive Proof
Recall that our induction scheme (click [here] to revisit it) had two
cases, the induction step (Subgoal *1/2) and the base case (Subgoal
*1/1). Both have been proved!")
(POR
(PARALLEL-PROGRAMMING ACL2-BUILT-INS)
"Parallel, Boolean version of [or]
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism],
and see [parallel-programming], which has a disclaimer.
Example Forms:
(por (subsetp-equal x y)
(subsetp-equal y x))
(por (declare
(granularity
(and (> (length x) 500)
(> (length y) 500))))
(subsetp-equal x y)
(subsetp-equal y x))
General Form:
(por (declare (granularity expr)) ; optional granularity declaration
arg1 ... argN)
where N >= 0 and each argi and expr are arbitrary terms.
Por evaluates its arguments in parallel. It returns a Boolean result:
t if any argument evaluates to non-nil, else nil. Note that while
[or] returns the first non-nil value from evaluating its arguments
left-to-right (if any such value is not nil) [por] always returns a
Boolean result, in support of efficiency (see [early-termination])
in light of the nondeterministic order in which argument values are
returned.
Another difference between por and [or] is that for a call of por,
even if the an argument's value is not nil, a subsequent argument
may be evaluated. See [pand] for a discussion of the analogous
property of pand. In particular, [guard]s generated from calls of
por may not assume for an argument that the preceding arguments
evaluated to nil.
See [parallelism-tutorial] for another example. Also see
[parallelism-at-the-top-level] for restrictions on evaluating
parallelism primitives from within the ACL2 top-level loop. Finally
see [early-termination] to read how por can offer more efficiency
than [or] by avoiding evaluation of some of its arguments.")
(PORTCULLIS
(BOOKS-TOUR)
"The gate guarding the entrance to a certified book
The certificate (see [certificate] for general information) of a
certified file is divided into two parts, a portcullis and a
[keep]. These names come from castle lore. The portcullis of a
castle is an iron grate that slides up through the ceiling of the
tunnel-like entrance. The portcullis of a book ensures that
[include-book] does not start to read the book until the
appropriate context has been created.
Technically, the portcullis consists of the [version] number of the
certifying ACL2, a list of [command]s used to create the
``certification [world]'' and an alist specifying the check sums of
all the [books] included in that [world]. The portcullis is
constructed automatically by [certify-book] from the [world] in
which [certify-book] is called, but that [world] must have certain
properties described below. After listing the properties we discuss
the issues in a more leisurely manner.
Each [command] in the portcullis must be either a [defpkg] form or an
embedded event form (see [embedded-event-form]).
Consider a book to be certified. The book is a file containing event
forms. Suppose the file contains references to such symbols as
my-pkg::fn and acl2-arith::cancel, but that the book itself does
not create the packages. Then a hard Lisp error would be caused
merely by the attempt to read the expressions in the book. The
corresponding [defpkg]s cannot be written into the book itself
because the book must be compilable and Common Lisp compilers
differ on the rules concerning the inline definition of new
packages. The only safe course is to make all [defpkg]s occur
outside of compiled files.
More generally, when a book is certified it is certified within some
logical [world]. That ``certification [world]'' contains not only
the necessary [defpkg]s but also, perhaps, function and constant
definitions and maybe even references to other [books]. When
[certify-book] creates the [certificate] for a file it recovers
from the certification [world] the [command]s used to create that
[world] from the initial ACL2 [world]. Those [command]s become part
of the portcullis for the certified book. In addition,
[certify-book] records in the portcullis the check sums (see
[check-sum]) of all the [books] included in the certification
[world].
[Include-book] presumes that it is impossible even to read the
contents of a certified book unless the portcullis can be
``raised.'' To raise the portcullis we must be able to execute
(possibly redundantly, but certainly without error), all of the
[command]s in the portcullis and then verify that the [books] thus
included were identical to those used to build the certification
[world] (up to check sum). This raising of the portcullis must be
done delicately since [defpkg]s are present: we cannot even read a
[command] in the portcullis until we have successfully executed the
previous ones, since packages are being defined.
Clearly, a book is most useful if it is certified in the most
elementary extension possible of the initial logic. If, for
example, your certification [world] happens to contain a [defpkg]
for \"MY-PKG\" and the function foo, then those definitions become
part of the portcullis for the book. Every time the book is
included, those names will be defined and will have to be either
new or redundant (see [redundant-events]). But if those names were
not necessary to the certification of the book, their presence
would unnecessarily restrict the utility of the book.
See [keep] to continue the guided tour of [books].")
(POSITION
(LISTS STRINGS ACL2-BUILT-INS)
"Position of an item in a string or a list
General Forms:
(position x seq)
(position x seq :test 'eql) ; same as above (eql as equality test)
(position x seq :test 'eq) ; same, but eq is equality test
(position x seq :test 'equal) ; same, but equal is equality test
(Position x seq) is the least index (zero-based) of the element x in
the string or list seq, if x is an element of seq. Otherwise
(position x seq) is nil. The optional keyword, :TEST, has no effect
logically, but provides the test (default [eql]) used for comparing
x with items of seq.
The [guard] for a call of position depends on the test. In all cases,
the second argument must satisfy [stringp] or [true-listp]. If the
test is [eql], then either the first argument must be suitable for
[eql] (see [eqlablep]) or the second argument must satisfy
[eqlable-listp]. If the test is [eq], then either the first
argument must be a symbol or the second argument must satisfy
[symbol-listp].
See [equality-variants] for a discussion of the relation between
position and its variants:
(position-eq x seq) is equivalent to (position x seq :test 'eq);
(position-equal x seq) is equivalent to (position x seq :test
'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function position-equal.
Position is defined by Common Lisp. See any Common Lisp documentation
for more information.
Function: <position-equal>
(defun position-equal (item lst)
(declare (xargs :guard (or (stringp lst) (true-listp lst))))
(if (stringp lst)
(position-ac item (coerce lst 'list) 0)
(position-equal-ac item lst 0)))
Function: <position-equal-ac>
(defun position-equal-ac (item lst acc)
(declare (xargs :guard (and (true-listp lst)
(acl2-numberp acc))))
(cond ((endp lst) nil)
((equal item (car lst)) acc)
(t (position-equal-ac item (cdr lst)
(1+ acc)))))")
(POSITION-EQ (POINTERS)
"See [position].")
(POSITION-EQUAL (POINTERS)
"See [position].")
(POSP
(NUMBERS ACL2-BUILT-INS)
"A recognizer for the positive integers
(posp x) is logically equivalent to (not (zp x)) (see [zp]) and also
to (and (natp x) (not (equal x 0))).
The community book [arithmetic/natp-posp] has some lightweight rules
for reasoning about posp and natp, and is included in the
[arithmetic-1] library. For a somewhat heavier and more
comprehensive alternative, you may wish to instead see the
[arith-equivs] book.
Function: <posp>
(defun posp (x)
(declare (xargs :guard t))
(and (integerp x) (< 0 x)))")
(POST-INDUCTION-KEY-CHECKPOINTS
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Reading post-induction key checkpoints
Each post-induction key checkpoint is a theorem if and only if the
original conjecture was a theorem. The reason is that each subgoal
produced by induction concludes with the original formula and
simplification preserves equivalence.
So if you see a post-induction key checkpoint that is not a theorem,
stop looking at the checkpoints! Your original conjecture is not a
theorem! Fix it.
If you're convinced all the post-induction conjectures are theorems,
ask whether each has the hypotheses you'd need to prove it. If the
case analysis feels inappropriate or induction hypotheses seem to
be missing, then ACL2 might have done the wrong induction. Find the
induction scheme it did by reading the first induction message
printed after the conjecture was submitted. If it is wrong, then
extend ACL2's induction analysis or tell ACL2 what induction to do,
as explained shortly.
But before you decide the induction hypothesis is missing, look
closely for contradictions among the hypotheses of the checkpoint
formula. For example, perhaps one of the hypotheses is (MEMBER e x)
and another is (NOT (MEMBER e' x')) where e, x, e', and x' are
possibly complicated expressions.
Is it possible that e and e' are equal and x and x' are equal? If so,
then the two hypotheses are contradictory and the checkpoint would
be proved if you could find rules that would simplify those
expressions to their common forms. So look for theorems about those
subexpressions.
Or maybe you can get e and e' to reduce to some common d but but find
that x and x' are really different. Then ask whether
(implies (member d x) (member d x'))
If you could prove that, the key checkpoint would be proved. Of
course, you may need other hypotheses from the checkpoint to state
your theorems.
If you have been working your way through the tutorial introduction
to the theorem prover, use your browser's Back Button now to
[introduction-to-key-checkpoints].")
(PPROGN
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Evaluate a sequence of forms that return [state]
Example Form:
(pprogn
(cond ((or (equal (car l) #\\) (equal (car l) slash-char))
(princ$ #\\ channel state))
(t state))
(princ$ (car l) channel state)
(mv (cdr l) state))
The convention for pprogn usage is to give it a non-empty sequence of
forms, each of which (except possibly for the last) returns state
(see [state]) as its only value. The [state] returned by each but
the last is passed on to the next. The value or values of the last
form are returned as the value of the pprogn.
If you are using single-threaded objects you may wish to define an
analogue of this function for your own [stobj].
General Form:
(PPROGN form1
form2
...
formk
result-form)
This general form is equivalent, via macro expansion, to:
(LET ((STATE form1))
(LET ((STATE form2))
...
(LET ((STATE formk))
result-form)))")
(PR
(HISTORY)
"Print the rules stored by the event with the given name
Examples:
:pr fn ; prints the rules from the definition of fn (including any
; :type-prescription rule and :definition rule)
:pr assoc-append ; if assoc-append is a rewrite rule, prints that rule
Also see [pr!], which is similar but works at the command level
instead of at the event level, and see [pl], which displays all
rewrite rules for calls of fn, not just those introduced at
definition time.
Pr takes one argument, a logical name, and prints the rules
associated with it. In each case it prints the rune, the current
enabled/disabled status, and other appropriate fields from the
rule. It may be helpful to read the documentation for various kinds
of rules in order to understand the information printed by this
command. For example, the information printed for a linear rule
might be:
Rune: (:LINEAR ABC)
Enabled: T
Hyps: ((CONSP X))
Concl: (< (ACL2-COUNT (CAR X)) (ACL2-COUNT X))
Max-term: (ACL2-COUNT (CAR X))
Backchain-limit-lst: (3)
The hyps and concl fields for this rule are fairly self-explanatory,
but it is useful to see [linear] to learn about maximal terms
(which, as one might guess, are stored under ``Max-term'').
Currently, this function does not print congruence rules or
equivalence rules.
The expert user might also wish to use [find-rules-of-rune]. See
[find-rules-of-rune].")
(PR!
(HISTORY)
"Print rules stored by the command with a given command descriptor
Examples:
:pr! fn ; prints the rules from the definition of fn (including any
; :type-prescription rule and :definition rule), as well as all other
; rules created by the command that created by fn (which could be
; many rules if, for example, fn was defined by an include-book
; command).
:pr! :max ; prints all the rules stored by the most recent command
Also see [pr], which is similar but works at the event level instead
of at the command level.
[Pr] takes one argument, a command descriptor, and prints the rules
created by the corresponding event. In each case it prints the
rune, the current enabled/disabled status, and other appropriate
fields from the rule. See [pr] for further details.")
(PRACTICE-FORMULATING-STRONG-RULES
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"A few simple checkpoints suggesting strong rules
Consider these definitions:
(defun rev (x)
(if (endp x)
nil
(append (rev (cdr x)) (list (car x)))))
(defun nats-below (j)
(if (zp j)
'(0)
(cons j (nats-below (- j 1)))))
We assume you are familiar with such ACL2 built-ins as append,
member, subsetp and true-listp. When we use throw-away names like
FOO, BAR, and MUM below we mean to suggest some arbitrary function
you shouldn't think about! We're just trying to train your eye to
ignore irrelevant things.
Below are some terms that should suggest rewrite rules to you.
Imagine that each of these terms occurs in some Key Checkpoint.
What rules come to mind? Try to think of the strongest rules you
can.
Term 1:
(TRUE-LISTP (APPEND (FOO A) (BAR B)))
Answers: See [practice-formulating-strong-rules-1]
Term 2:
(TRUE-LISTP (REV (FOO A)))
Answers: See [practice-formulating-strong-rules-2]
Term 3:
(MEMBER (FOO A) (APPEND (BAR B) (MUM C)))
Answers: See [practice-formulating-strong-rules-3]
Term 4:
(SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))
Answers: See [practice-formulating-strong-rules-4]
Term 5:
(SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))
Answers: See [practice-formulating-strong-rules-5]
Term 6:
(MEMBER (FOO A) (NATS-BELOW (BAR B)))
Answers: See [practice-formulating-strong-rules-6]
We recommend doing all of these little exercises. When you're
finished, use your browser's Back Button to return to
[strong-rewrite-rules].")
(PRACTICE-FORMULATING-STRONG-RULES-1
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Rules suggested by (TRUE-LISTP (APPEND (FOO A) (BAR B)))
What rules come to mind when looking at the following subterm of a
Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).
(TRUE-LISTP (APPEND (FOO A) (BAR B)))
Obviously, you must think about the conditions under which (APPEND x
y) returns a true-list. Recall that APPEND concatentates x and y,
with y being the terminal sublist. Its definition is equivalent to
(defun append (x y)
(if (endp x)
y
(cons (car x)
(append (cdr x) y))))
Technical Note: Append is really a macro that permits you to write
calls of append with more than two arguments.
In a sense, append ``expects'' its arguments to be lists ending in
nil, so-called true-listps. (Such expectations are formalized in
ACL2 by the notion of the ``[guard]'' [{ICON}] of the function, but
we strongly recommend not investigating guards until you're good at
using the system.)
New users frequently start every new theorem by listing all their
expectations on the arguments of functions in the problem. For
example, if the new user wants to make some statement about when
(append x y) is a true-listp, it is not uncommon for him or her
first to write:
(implies (and (true-listp x)
(true-listp y))
...)
to get ``comfortable.'' Then, thinking about when (append x y) is a
true-listp is easy: it always returns a true-listp. It's always a
true-listp.'' This thinking produces the theorem:
(defthm true-listp-append-really-weak
(implies (and (true-listp x)
(true-listp y))
(true-listp (append x y))))
You'll note we gave it a name suggesting it is ``really weak.''
One sense in which it is weak is that it has an unnecessary
hypothesis. If y is a true-listp, then (append x y) is too, whether
x is a true-listp or not. In ACL2, all functions are total.
Logically speaking, it doesn't matter whether endp expects its
argument to be a true-listp or not, it behaves. (Append x y) either
returns y or a cons whose second argument is generated by append.
Thus, if y is a true-listp, the answer is too. So here is an
improved version of the rule:
(defthm true-listp-append-weak
(implies (true-listp y)
(true-listp (append x y))))
We still think of it as ``weak'' because it has a hypothesis that
limits its applicability.
The strong version of the rule is
(defthm true-listp-append-strong
(equal (true-listp (append x y))
(true-listp y))).
That is, append returns a true-listp precisely when its second
argument is a true-listp. We recommend that the strong version be
made a :[rewrite] [{ICON}] rule.
The weak version of the rule allows us to reduce (TRUE-LISTP (APPEND
x y)) to true if we can show that (TRUE-LISTP y) is true. But
suppose (TRUE-LISTP y) is actually false. Then (TRUE-LISTP (APPEND
x y)) would not simplify under the weak version of the rule. But
under the strong version it would simplify to NIL.
Technical Note: The weak version of the rule is a useful
:[type-prescription] [{ICON}] rule. The type mechanism cannot
currently exploit the strong version of the rule.
The strategy of ``getting comfortable'' by adding a bunch of
hypotheses before you know you need them is not conducive to
creating strong rules. We tend to state the main relationship that
we intuit about some function and then add the hypotheses we need
to make it true. In this case, there were no necessary hypotheses.
But if there are, we first identify them and then we ask ``what can
I say about the function if these hypotheses aren't true?'' and try
to strengthen the statement still further.
Use your browser's Back Button now to return to
[practice-formulating-strong-rules].")
(PRACTICE-FORMULATING-STRONG-RULES-2
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Rules suggested by (TRUE-LISTP (REV (FOO A)))
What rules come to mind when looking at the following subterm of a
Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).
(TRUE-LISTP (REV (FOO A)))
The definition of rev in this problem is
(defun rev (x)
(if (endp x)
nil
(append (rev (cdr x)) (list (car x)))))
Since the definition terminates with an endp test and otherwise cdrs
the argument, the author of rev was clearly expecting x to be a
true-listp. (Indeed, the ``[guard]'' [{ICON}] for rev must include
(true-listp x) since that is endp's guard.) So you're naturally
justified in limiting your thoughts about (rev x) to x that are
true-lists. This gives rise to the theorem:
(defthm true-listp-rev-weak
(implies (true-listp x)
(true-listp (rev x))))
This is the kind of thinking illustrated in the earlier append
example (see [practice-formulating-strong-rules-1]), and, to
paraphrase Z in Men in Black, it exemplifies ``everything we've
come to expect from years of training with typed languages.''
But logically speaking, the definition of rev does not require x to
be a true-listp. It can be any object at all: ACL2 functions are
total. Rev either returns nil or the result of appending a
singleton list onto the right end of its recursive result. That
call of append always returns a true-listp since the singleton list
is a true list. (See [practice-formulating-strong-rules-1].)
So this is a theorem and a very useful :[rewrite] [{ICON}] rule:
(defthm true-listp-rev-strong
(true-listp (rev x))).
Use your browser's Back Button now to return to
[practice-formulating-strong-rules].")
(PRACTICE-FORMULATING-STRONG-RULES-3
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Rules suggested by (MEMBER (FOO A) (APPEND (BAR B) (MUM C)))
What rules come to mind when looking at the following subterm of a
Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).
(MEMBER (FOO A) (APPEND (BAR B) (MUM C)))
Since (append x y) contains all the members of x and all the members
of y, e is a member of (append x y) precisely when e is a member of
x or of y. So a strong statement of this is:
(defthm member-append-strong-false
(equal (member e (append x y))
(or (member e x)
(member e y))))
However, this is not a theorem because member is not Boolean. (Member
e x), for example, returns the first tail of x that starts with e,
or else nil. To see an example of this formula that evaluates to
nil, let
e = 3
x = '(1 2 3)
y = '(4 5 6).
Then the left-hand side, (member e (append x y)) evaluates to (3 4 5
6) while the right-hand side evaluates to (3).
However, the two sides are propositionally equivalent (both either
nil or non-nil together). So this is a useful :[rewrite] [{ICON}]
rule:
(defthm member-append-strong
(iff (member e (append x y))
(or (member e x)
(member e y)))).
It tells the system that whenever it encounters an instance of
(MEMBER e (APPEND x y)) in a propositional occurrence (where only
its truthvalue is relevant), it should be replaced by this
disjunction of (MEMBER e x) and (MEMBER e y).
The following two formulas are true but provide much weaker rules and
we would not add them:
(implies (member e x) (member e (append x y)))
(implies (member e y) (member e (append x y)))
because they each cause the system to backchain upon seeing (MEMBER e
(APPEND x y)) expressions and will not apply unless one of the two
side-conditions can be established.
There is a rewrite rule that is even stronger than
member-append-strong. It is suggested by the counterexample, above,
for the EQUAL version of the rule.
(defthm member-append-really-strong
(equal (member e (append x y))
(if (member e x)
(append (member e x) y)
(member e y))))
While member-append-strong only rewrites member-append expressions
occurring propositionally, the -really-strong version rewrites
every occurrence.
However, this rule will be more useful than member-append-strong only
if you have occurrences of member in non-propositional places. For
example, suppose you encountered a term like:
(CONS (MEMBER e (APPEND x y)) z).
Then the -strong rule does not apply but the -really-strong rule
does.
Furthermore, the -really-strong rule, by itself, is not quite as good
as the -strong rule in propositional settings! For example, if you
have proved the -really-strong rule, you'll notice that the system
still has to use induction to prove
(IMPLIES (MEMBER E A)
(MEMBER E (APPEND B A))).
The -really-strong rule would rewrite it to
(IMPLIES (MEMBER E A)
(IF (MEMBER E A)
(APPEND (MEMBER E A) B)
(MEMBER E B)))
which would further simplify to
(IMPLIES (MEMBER E A)
(APPEND (MEMBER E A) B))
What lemma does this suggest? The answer is the rather odd:
(implies x (append x y))
which rewrites propositional occurrences of (APPEND x y) to T if x is
non-nil. This is an inductive fact about append.
A problem with the -really-strong rule is that it transforms even
propositional occurrences of member into mixed propositional and
non-propositional occurrences.
(defthm member-append-really-strong
(equal (member e (append x y)) ; <-- even if this is a propositional occurrence
(if (member e x)
(append (member e x) y) ; <-- the member in here is not!
(member e y))))
So if you are using the -really-strong lemma in a situation in which
all your member expressions are used propositionally, you'll
suddenly find yourself confronted with non-propositional uses of
member.
Our advice is not to use the -really-strong version unless your
application is inherently using member in a non-propositional way.
Use your browser's Back Button now to return to
[practice-formulating-strong-rules].")
(PRACTICE-FORMULATING-STRONG-RULES-4
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Rules suggested by (SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))
What rules come to mind when looking at the following subterm of a
Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).
(SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))
When is (append x y) a subset of z? When everything in x is in z and
everything in y is in z. We would make it a rewrite rule:
(defthm subsetp-append-1-strong
(equal (subsetp (append x y) z)
(and (subsetp x z)
(subsetp y z))))
We put the ``-1-'' in the name because there is a comparable theorem
for when the append is in the second argument of the subsetp; see
[practice-formulating-strong-rules-5].
This strong rule is better than the conditional rule;
(defthm subsetp-append-1-weak
(implies (and (subsetp x z)
(subsetp y z))
(subsetp (append x y) z)))
for all the usual reasons.
Use your browser's Back Button now to return to
[practice-formulating-strong-rules].")
(PRACTICE-FORMULATING-STRONG-RULES-5
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Rules suggested by (SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))
What rules come to mind when looking at the following subterm of a
Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).
(SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))
When is x a subset of (append y z)? Clearly it is if x is a subset of
y or x is a subset of z. We could write that:
(defthm subsetp-append-2-weak
(implies (or (subsetp x y)
(subsetp x z))
(subsetp x (append y z))))
The rule generated from this is: ``if you ever encounter (an instance
of) (SUBSETP x (APPEND y z)), backchain to the or above and try to
establish it. If you can establish it, replace the target by T.''
This does not fully characterize the situation though. For example,
'(1 2 3 4) is a subset of (append '(1 3) '(2 4)) without being a
subset of either argument of the append.
However, no obvious equivalence comes to mind -- indeed, to express
any of the ideas floating around here requires defining and
introducing more functions, which is not recommended unless those
functions are already in the problem.
For example, if you defined the concept of ``set-minus'' so that
(set-minus x y) consists of those elements of x not in y, then you
could prove:
(defthm subset-append-2-strong-but-messy
(equal (subsetp x (append y z))
(and (subsetp (set-minus x z) y)
(subsetp (set-minus x y) z))))
But this rewrite rule would ``trade'' append away and introduce
set-minus. That might be a good strategy if set-minus were already
in the problem. But if it were not, it might not be. We wouldn't
recommend this rule unless it were helpful in normalizing the
expressions in the problem.
We recommend sticking with the weak version of the rule,
(defthm subsetp-append-2-weak
(implies (or (subsetp x y)
(subsetp x z))
(subsetp x (append y z)))).
This illustrates the fact that sometimes there is no strong version
of a rule!
Use your browser's Back Button now to return to
[practice-formulating-strong-rules].")
(PRACTICE-FORMULATING-STRONG-RULES-6
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Rules suggested by (MEMBER (FOO A) (NATS-BELOW (BAR B)))
What rules come to mind when looking at the following subterm of a
Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).
(MEMBER (FOO A) (NATS-BELOW (BAR B)))
The definition of NATS-BELOW is
(defun nats-below (j)
(if (zp j)
'(0)
(cons j (nats-below (- j 1)))))
Thus, (nats-below 7) is (7 6 5 4 3 2 1 0). So when is k a member of
(nats-below j)?
The weakest version is
(defthm member-nats-below-weak
(implies (and (natp k)
(natp j)
(<= k j))
(member k (nats-below j))))
But clearly we could improve this to:
(defthm member-nats-below-weak-better
(implies (and (natp k)
(natp j))
(iff (member k (nats-below j))
(<= k j))))
or even
(defthm member-nats-below-weak-better
(implies (natp j)
(iff (member k (nats-below j))
(and (natp k)
(<= k j)))))
Clearly though, we'd like to get rid of the (natp j) hypothesis and
the neatest plausible version is:
(defthm member-nats-below-weak-neatest
(iff (member k (nats-below j))
(and (natp j)
(natp k)
(<= k j))))
But it is not a theorem! For example, if j is -1 and k is 0, then the
left-hand side above returns t, because (nats-below j) is (0), but
the right-hand side is nil.
But this suggests a strategy for dealing with necessary hypotheses,
like (natp j). We can move them into an IF on the right-hand side!
Something like this might be a useful rewrite rule:
(iff (member k (nats-below j))
(if (natp j)
(and (natp k)
(<= k j))
...)).
We know, from member-nats-below-weak-better, that if (natp j) is
true, the member is equivalent to (and (natp k) (<= k j)). So now
consider what we know if (natp j) is false. If we can think of some
term it's equivalent to and that term is simpler than the member
expression, we have a strong rule.
But by inspection of the definition of nats-below, we see that when
(natp j) is false, (nats-below j) is the list (0) because (zp j) is
t. That is, nats-below treats all non-natural arguments like they
were 0. Thus, when (natp j) is false, (member k (nats-below j)) is
(member k '(0)), which is (equal k 0).
So the strong version is
(defthm member-nats-below-strong
(iff (member k (nats-below j))
(if (natp j)
(and (natp k)
(<= k j))
(equal k 0))))
This is a great :[rewrite] [{ICON}] rule. It gets rid of the member
and nats-below and introduces arithmetic.
This example illustrates the idea of putting an if on the
right-hand-side of the equivalence. Many users tend to limit
themselves to propositional forms inside iff or to simple
expressions inside of equal. But it is quite natural to use if to
express what the answer is: if j is a natural, then k is in
(nats-below j) precisely if k is a natural less than or equal to j;
if j is not a natural, then k is in (nats-below j) precisely if k
is 0.
Use if to lay out the cases you must consider, if you can think of a
simpler, equivalent expression for every possible case.
Use your browser's Back Button now to return to
[practice-formulating-strong-rules].")
(PRIMITIVE
(PROGRAMMING ACL2-BUILT-INS)
"Primitive functions built into ACL2 without definitions
The ACL2 [ground-zero] [theory] includes axioms about some built-in
functions that are not given explicit definitions, such as [<],
[car], and [symbolp]. We sometimes call such functions primitives.
The built-in constant *primitive-formals-and-guards* is an alist
that associates each primitive with its list of formals and its
[guard]; that is, each element of that alist is of the form (name
formals guard). The value of this constant is displayed below.
Definition: <*primitive-formals-and-guards*>
(defconst *primitive-formals-and-guards*
'((acl2-numberp (x) 't)
(bad-atom<= (x y)
(if (bad-atom x) (bad-atom y) 'nil))
(binary-* (x y)
(if (acl2-numberp x)
(acl2-numberp y)
'nil))
(binary-+ (x y)
(if (acl2-numberp x)
(acl2-numberp y)
'nil))
(unary-- (x) (acl2-numberp x))
(unary-/ (x)
(if (acl2-numberp x)
(not (equal x '0))
'nil))
(< (x y)
(if (rationalp x) (rationalp y) 'nil))
(car (x)
(if (consp x) 't (equal x 'nil)))
(cdr (x)
(if (consp x) 't (equal x 'nil)))
(char-code (x) (characterp x))
(characterp (x) 't)
(code-char (x)
(if (integerp x)
(if (< x '0) 'nil (< x '256))
'nil))
(complex (x y)
(if (rationalp x) (rationalp y) 'nil))
(complex-rationalp (x) 't)
(coerce (x y)
(if (equal y 'list)
(stringp x)
(if (equal y 'string)
(character-listp x)
'nil)))
(cons (x y) 't)
(consp (x) 't)
(denominator (x) (rationalp x))
(equal (x y) 't)
(if (x y z) 't)
(imagpart (x) (acl2-numberp x))
(integerp (x) 't)
(intern-in-package-of-symbol
(str sym)
(if (stringp str) (symbolp sym) 'nil))
(numerator (x) (rationalp x))
(pkg-imports (pkg) (stringp pkg))
(pkg-witness (pkg)
(if (stringp pkg)
(not (equal pkg '\"\"))
'nil))
(rationalp (x) 't)
(realpart (x) (acl2-numberp x))
(stringp (x) 't)
(symbol-name (x) (symbolp x))
(symbol-package-name (x) (symbolp x))
(symbolp (x) 't)))")
(PRINC$
(IO ACL2-BUILT-INS)
"Print an atom
Use princ$ to do basic printing of atoms (i.e., other than cons
pairs). In particular, princ$ prints a string without the
surrounding double-quotes and without escaping double-quote
characters within the string. Note that princ$ is sensitive to the
print-base, print-radix, and print-case; see [set-print-base-radix]
and see [set-print-case]. Princ$ returns [state].
Examples:
ACL2 !>(princ$ \"Howdy ho\" (standard-co state) state)
Howdy ho<state>
ACL2 !>(pprogn (princ$ \"Howdy ho\" (standard-co state) state)
(newline (standard-co state) state))
Howdy ho
<state>
ACL2 !>(princ$ \"ab\\\"cd\" *standard-co* state)
ab\"cd<state>
ACL2 !>
ACL2 !>(princ$ 17 *standard-co* state)
17<state>
ACL2 !>(set-print-base 16 state) ; might be nicer to use set-print-base-radix
<state>
ACL2 !>(princ$ 17 *standard-co* state)
11<state>
ACL2 !>(set-print-radix t state)
<state>
ACL2 !>(princ$ 17 *standard-co* state)
#x11<state>
ACL2 !>(princ$ 'xyz *standard-co* state)
XYZ<state>
ACL2 !>(set-print-case :downcase state)
<state>
ACL2 !>(princ$ 'xyz *standard-co* state)
xyz<state>
ACL2 !>
The [guard] for (princ$ x channel state) is essentially as follows;
see [io] for an explanation of guards of certain built-in functions
that take [state], such as princ$.
(and (or (acl2-numberp x)
(characterp x)
(stringp x)
(symbolp x))
(state-p1 state-state)
(symbolp channel)
(open-output-channel-p1 channel :character state-state))
See [fmt] for more sophisticated printing routines, and see [io] for
general information about input and output.")
(PRINT-BASE-P
(IO ACL2-BUILT-INS)
"Recognizer for print bases that are understood by functions such as
[explode-nonnegative-integer] and [explode-atom].
Function: <print-base-p>
(defun print-base-p (print-base)
(declare (xargs :guard t))
(and (member print-base '(2 8 10 16))
t))")
(PRINT-CONTROL
(IO)
"Advanced controls of ACL2 printing
See [io] for a summary of printing in ACL2. Here we document some
advanced ways to control what is printed by ACL2's primary printing
routines.
See [set-print-base-radix], [set-print-base], [set-print-radix], and
[set-print-case] for discussions of the most common ways to control
what is printed. Indeed, these are the only ways to control the
behavior of [princ$] and prin1$.
See [set-fmt-hard-right-margin] for how to set the right margin for
prover output and, more generally, all output from formatted
printing functions (see [fmt]). Note that set-print-right-margin,
mentioned below, does not affect such printing.
The rest of this topic is for advanced users of ACL2. We refer to
Common Lisp behavior, as described in any good Common Lisp
documentation.
Print-control variables. [Set-print-base], [set-print-radix], and
[set-print-case] assign to corresponding so-called ``[state] global
variables'' 'print-base, 'print-radix, and 'print-case, which can
be accessed using the expressions (@ print-base), (@ print-radix),
and (@ print-case), respectively; see [assign]. Here is a table
showing all print-control variables, their setters, and their
defaults. Also see [set-print-base-radix].
print-base set-print-base 10
print-case set-print-case :upcase
print-circle set-print-circle nil
[but see remark on print-circle-files, below]
print-escape set-print-escape t
print-length set-print-length nil
print-level set-print-level nil
print-lines set-print-lines nil
print-pretty set-print-pretty nil
print-radix set-print-radix nil
print-readably set-print-readably nil
print-right-margin set-print-right-margin nil
Each ACL2 print-control variable print-xxx can correspond in function
to Common Lisp variable *PRINT-XXX*. Specifically, the evaluation
of forms (set-print-base t), (set-print-radix t), and
(set-print-case t) affects ACL2 printing functions in much the same
way that setting to t Common Lisp variables *PRINT-BASE*,
*PRINT-RADIX*, and *PRINT-CASE*, respectively, affects Common Lisp
printing. The same is true for print-escape, except that this does
not affect [princ$] or prin1$, which correspond to Common Lisp
functions princ and prin1: princ treats *PRINT-ESCAPE* as nil while
prin1 treats *PRINT-ESCAPE* as t. Moreover, all print-control
variables not mentioned in this paragraph are set to their defaults
in [princ$] and prin1$, as indicated by ACL2 constant
*print-control-defaults*, except that print-readably is set to nil
in princ$.
[Fmt] and its related functions are sensitive to state globals
'print-base, 'print-radix, 'print-case, 'print-escape, and
'print-readably, in analogy with Common Lisp functions that don't
fix *PRINT-ESCAPE* or *PRINT-READABLY*. But the [fmt] functions do
not respect settings of other print-control variables; for example,
they act as though 'print-circle is nil. Since ACL2 output is
produced using the same underlying print routines as the [fmt]
functions, it also is insensitive to all print-control variables
except for the five above. To control the print-level and
print-length used for producing ACL2 output, see [set-evisc-tuple].
[Print-object$] is sensitive to all of the print-control variables.
Evaluate (reset-print-control) to restore all print-control variables
to their original settings, as stored in constant
*print-control-defaults*.
(Remark on print-circle-files: ACL2 typically binds 'print-circle to
t before writing [certificate] files, or auxiliary files that are
compiled when [make-event] forms are present in a book, or files in
support of :[comp] commands. This binding allows for structure
sharing that can keep these files from growing large. End of
Remark.)
(Remark for those using ACL2 built on CLtL1 (non-ANSI) Gnu Common
Lisp (GCL): Note that Common Lisp variables *PRINT-LINES*,
*PRINT-MISER-WIDTH*, *PRINT-READABLY*, *PRINT-PPRINT-DISPATCH*, and
*PRINT-RIGHT-MARGIN* do not have any effect for such GCL versions.)")
(PRINT-GV
(GUARD DEBUGGING)
"Print a form whose evaluation caused a guard violation
By default, ACL2 checks input constraints on functions, known as
[guard]s. When guards are violated, an informative message is
printed; but sometimes it is useful to investigate why the guard
check fails. The utility print-gv is provided for that purpose.
(Alternatively, you may prefer to avoid guards entirely with
(set-guard-checking :none); see [set-guard-checking].)
Example Forms:
(print-gv)
:print-gv ; same as above
(print-gv ; same as above, showing all system defaults
:conjunct nil
:evisc-tuple (print-gv-evisc-tuple)
:substitute nil)
(print-gv :evisc-tuple (evisc-tuple 4 4 nil nil))
(print-gv :evisc-tuple (evisc-tuple 4 4 nil nil))
(print-gv :evisc-tuple (evisc-tuple 4 ; print-level
5 ; print-length
(world-evisceration-alist state nil)
nil ; hiding-cars
))
General Form:
(print-gv :evisc-tuple x)
where the keyword arguments are optional. These arguments have the
following effects and system defaults, but note that the defaults
can be changed by the user; see [set-print-gv-defaults].
The :conjunct argument is nil by default, indicating that a form is
to be displayed whose evaluation represents the [guard] evaluation
that produced nil. A value of t indicates that ACL2 should parse
the guard into conjuncts, and display the conjunct that actually
evaluated to nil. It does this by evaluating each conjunct in turn
until one produces a result of nil.
The :evisc-tuple argument should be an [evisc-tuple]. Its default is
the value of the expression (print-gv-evisc-tuple), which specifies
hiding only the ACL2 logical [world], so that the symbol <world> is
printed instead of the actual world. See [evisc-tuple] for a
discussion of evisc-tuples.
The :substitute argument is nil by default, indicating that the
displayed form uses [flet], which avoids duplicate occurrences of
actual parameters. A value of t indicates that ACL2 should instead
substitute those actuals into the guard.
Again, the user can change these defaults; see
[set-print-gv-defaults].
To see how one might use print-gv, consider the following definition.
(defun foo (x)
(declare (xargs :guard (and (integerp x)
(posp (+ -2 x))
(posp (+ 3 x))
(posp (+ -4 x)))))
x)
Now suppose we evaluate a call of foo and obtain a guard violation.
ACL2 !>(foo 1)
ACL2 Error in TOP-LEVEL: The guard for the function call (FOO X),
which is (AND (INTEGERP X) (POSP (+ -2 X)) (POSP (+ 3 X)) (POSP (+ -4 X))),
is violated by the arguments in the call (FOO 1).
See :DOC set-guard-checking for information about suppressing this
check with (set-guard-checking :none), as recommended for new users.
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
Let us investigate this guard failure. First we use print-gv to
obtain a form that represents our guard violation. Just for fun,
we'll check that it indeed evaluates to nil.
ACL2 !>:print-gv
(FLET ((FOO{GUARD} (X)
(DECLARE (IGNORABLE X))
(AND (INTEGERP X)
(POSP (+ -2 X))
(POSP (+ 3 X))
(POSP (+ -4 X)))))
(FOO{GUARD} 1))
ACL2 !>(FLET ((FOO{GUARD} (X)
(DECLARE (IGNORABLE X))
(AND (INTEGERP X)
(POSP (+ -2 X))
(POSP (+ 3 X))
(POSP (+ -4 X)))))
(FOO{GUARD} 1))
NIL
This form doesn't tell us which of the four conjuncts actually
evaluated to nil. We can fix that by using the :conjunct keyword
argument.
ACL2 !>(print-gv :conjunct t)
Showing guard conjunct (#2 of 4) that evaluates to nil:
(FLET ((FOO{GUARD} (X) (POSP (+ -2 X)))) (FOO{GUARD} 1)).
ACL2 !>
But here's another way to analyze the guard failure. Let's change
[and] to [list] in the result of :print-gv, to see which conjuncts
are false. Of course, the user can massage the guard form in any
way that might be helpful.
ACL2 !>(FLET ((FOO{GUARD} (X)
(DECLARE (IGNORABLE X))
(list (INTEGERP X)
(POSP (+ -2 X))
(POSP (+ 3 X))
(POSP (+ -4 X)))))
(FOO{GUARD} 1))
(T NIL T NIL)
ACL2 !>
The NIL results show that the second and fourth conjuncts of the
guard were false in our particular case.
The following hack will give you access in raw Lisp to the form
printed by (print-gv). After a guard violation, just submit the
following form to raw Lisp.
(print-gv1 (wormhole-data (cdr (assoc 'ev-fncall-guard-er-wormhole
*wormhole-status-alist*)))
nil ; conjunct
nil ; substitute
'top state)
If you use local [stobj]s (see [with-local-stobj]) or stobj fields of
stobjs, you may need to edit the output of print-gv in order to
evaluate it. Consider the following example.
(defstobj st fld)
(defun g (x st)
(declare (xargs :guard (consp x) :stobjs st)
(ignore x))
(fld st))
(defun test ()
(with-local-stobj
st
(mv-let (result st)
(mv (g 3 st) st)
result)))
(test)
Then :print-gv yields the result shown below.
(FLET ((G{GUARD} (X ST)
(DECLARE (IGNORABLE X ST))
(AND (STP ST) (CONSP X))))
(G{GUARD} 3 |<some-stobj>|))
In this example you could replace ``|<some-stobj>|'' by ``st'' to
obtain a result of nil. But similar cases may require the use of a
local stobj that is no longer available, in which case you may need
to be creative in order to take advantage of :print-gv. Here is
such an example.
(defstobj st2 fld2)
(defun g2 (st2)
(declare (xargs :guard (null (fld2 st2)) :stobjs st2))
(mv 0 st2))
(defun test2 ()
(with-local-stobj
st2
(mv-let (result st2)
(let ((st2 (update-fld2 17 st2)))
(g2 st2))
result)))
(test2)
In this case, :print-gv yields the following.
(FLET ((G2{GUARD} (ST2)
(DECLARE (IGNORABLE ST2))
(AND (ST2P ST2) (NULL (FLD2 ST2)))))
(G2{GUARD} |<some-stobj>|))
But if you replace ``|<some-stobj>|'' by ``st'', the guard holds; it
is only the local stobj, which is no longer available, that
produced a guard violation (because its field had been updated to a
cons).
ACL2 !>(FLET ((G2{GUARD} (ST2)
(DECLARE (IGNORABLE ST2))
(AND (ST2P ST2) (NULL (FLD2 ST2)))))
(G2{GUARD} st2))
T
ACL2 !>
Finally, we note that while print-gv is a utility for debugging guard
violations, in contrast, see [guard-debug] for a utility to assist
in debugging failed proofs arising from guard verification.
Subtopics
[Set-print-gv-defaults]
Set default keyword values for [print-gv]")
(PRINT-OBJECT$ (POINTERS) "See [io].")
(PRINT-SUMMARY-USER (POINTERS)
"See [finalize-event-user].")
(PRINTING-TO-STRINGS
(IO)
"Printing to strings instead of files or standard output
Each of ACL2's formatted printing functions, FM*, has an analoguous
macro FM*-TO-STRING indicated below. These functions do not include
a channel or [state] as an argument, and FM*-TO-STRING returns the
string that FM* would print to the state, in place of state; see
[fmt]. The legal keyword arguments are described below.
General Forms: result
(fms-to-string string alist &key ...) ; string
(fmt-to-string string alist &key ...) ; (mv col string)
(fmt1-to-string string alist column &key ...) ; (mv col string)
(fms!-to-string string alist &key ...) ; string
(fmt!-to-string string alist &key ...) ; (mv col string)
(fmt1!-to-string string alist column &key ...) ; (mv col string)
The legal keyword arguments are as follows. They are all optional
with a default of nil.
Evisc-tuple is evaluated, and corresponds exactly to the evisc-tuple
argument of the corresponding FM* function; see [fmt].
Fmt-control-alist should typically evaluate to an alist that maps
print-control variables to values; see [print-control]. Any
alist mapping variables to values is legal, however. By default
the print controls are set according to the value of constant
*fmt-control-defaults*; fmt-control-alist overrides these
defaults. For example, *fmt-control-defaults* sets the right
margin just as it is set in the initial ACL2 [state], by
binding fmt-soft-right-margin and fmt-hard-right-margin to
their respective defaults of *fmt-soft-right-margin-default*
and *fmt-hard-right-margin-default*. The following example
shows how you can override those defaults, in this case
arranging to print flat by setting the right margin to a large
number.
(fmt-to-string \"~x0\"
(list (cons #\\0 (make-list 30)))
:fmt-control-alist
`((fmt-soft-right-margin . 10000)
(fmt-hard-right-margin . 10000)))
Iprint is typically nil, but t is also a legal value. See
[set-iprint] for the effect of value t, which however is local
to this call of a FM*-TO-STRING function; the behavior if
iprinting afterwards is not affected by this call. In
particular, you will not be able to look at the values of
iprint tokens printed by this call, so the value t is probably
of limited utility at best.
Also see [io] for a discussion of the utility
get-output-stream-string$, which allows for accumulating the
results of more than one printing call into a single string but
requires the use of [state].")
(PROFILE
(EVENTS)
"Turn on profiling for one function
NOTE: An alternative to this utility, which has significantly less
functionality but doesn't use [hons-enabled] features of ACL2, may
be found in community book books/misc/profiling.lisp. See
[hons-and-memoization] for a general discussion of [memoization],
on which this profile utility is built, and the related features of
hash consing and applicative hash tables.
Profile can be useful in Common Lisp debugging and performance
analysis, including examining the behavior of ACL2 functions.
Example:
(profile 'fn) ; keep count of the calls of fn
(profile 'fn ; as above, with with some memoize options
:trace t
:forget t)
(memsum) ; report statistics on calls of memoized functions (e.g., fn)
(clear-memoize-statistics) ; clear memoization (and profiling) statistics
Evaluation of (profile 'fn) redefines fn so that a count will be kept
of the calls of FN. The information recorded may be displayed, for
example, by invoking ([memoize-summary]) or (equivalently)
(memsum). If you wish to gather fresh statistics for the evaluation
of a top-level form, see [clear-memoize-statistics].
Profile is just a macro that calls [memoize] to do its work. Profile
gives the two keyword parameters :condition and :recursive of
[memoize] the value nil. Other keyword parameters for memoize,
which must not include :condition, :condition-fn, or :recursive,
are passed through. To eliminate profiling, use [unmemoize]; for
example, to eliminate profiling for function fn, evaluate
(unmemoize 'fn).
You may find raw Lisp functions profile-all and profile-acl2 to be
useful. These may be found in file
centaur/memoize/old/profile-raw.lsp distributed with the
[community-books].")
(PROG2$
(PROGN$ ACL2-BUILT-INS)
"Execute two forms and return the value of the second one
See [hard-error], see [illegal], and see [cw] for examples of
functions to call in the first argument of prog2$. Also see
[progn$] for an extension of prog2$ that handles than two
arguments.
Semantically, (Prog2$ x y) equals y; the value of x is ignored.
However, x is first evaluated for side effect. Since the ACL2
[programming] language is applicative, there can be no logical
impact of evaluating x. However, x may involve a call of a function
such as [hard-error] or [illegal], which can cause so-called ``hard
errors'', or a call of [cw] to perform output.
Here is a simple, contrived example using [hard-error]. The intention
is to check at run-time that the input is appropriate before
calling function bar.
(defun foo-a (x)
(declare (xargs :guard (consp x)))
(prog2$
(or (good-car-p (car x))
(hard-error 'foo-a
\"Bad value for x: ~p0\"
(list (cons #\\0 x))))
(bar x)))
The following similar function uses [illegal] instead of hard-error.
Since illegal has a guard of nil, [guard] verification would
guarantee that the call of illegal below will never be made (at
least when guard checking is on; see [set-guard-checking]).
(defun foo-b (x)
(declare (xargs :guard (and (consp x) (good-car-p (car x)))))
(prog2$
(or (good-car-p (car x))
(illegal 'foo-b
\"Bad value for x: ~p0\"
(list (cons #\\0 x))))
(bar x)))
We conclude with a simple example using [cw] from the ACL2 sources.
(defun print-terms (terms iff-flg wrld)
; Print untranslations of the given terms with respect to iff-flg, following
; each with a newline.
; We use cw instead of the fmt functions because we want to be able to use this
; function in print-type-alist-segments (used in brkpt1), which does not return
; state.
(if (endp terms)
terms
(prog2$
(cw \"~q0\" (untranslate (car terms) iff-flg wrld))
(print-terms (cdr terms) iff-flg wrld))))")
(PROGN
(EVENTS)
"Evaluate some [events]
Example Form:
(progn (defun foo (x) x)
(defmacro my-defun (&rest args)
(cons 'defun args))
(my-defun bar (x) (foo x)))
General form:
(progn event1 event2 ... eventk)
where k >= 0 and each eventi is a legal embedded event form (see
[embedded-event-form]). Each event is printed (by default) and
evaluated, in sequence. If any event fails, the entire progn call
is deemed to have failed, and the logical [world] is rolled back to
what it was immediately before the progn call was evaluated. A
utility is provided to assist in debugging failures of such
execution; see [redo-flat].
NOTE: If the eventi above are not all legal embedded event forms (see
[embedded-event-form]), consider using [er-progn] or (with great
care!) [progn!] instead. If your goal is simply to execute a
sequence of top-level forms that are not necessarily all legal
embedded event forms, consider using ld instead; see [ld].
For a related event form that does allow introduction of
[constraint]s and [local] [events], see [encapsulate].
ACL2 does not allow the use of progn in definitions. Instead, the
macro [er-progn] can be used for sequencing [state]-oriented
operations; see [er-progn] and see [state]. If you are using
single-threaded objects (see [stobj]) you may wish to define a
version of [er-progn] that cascades the object through successive
changes. ACL2's [pprogn] is the state analogue of such a macro.")
(PROGN!
(EVENTS)
"Evaluate some forms, not necessarily [events]
WARNING! This event is intended for advanced users who, in essence,
want to build extensions of ACL2. See see [defttag], in particular,
the ``WARNING'' there, and see the warning about [stobj]s at the
end of this documentation topic.
Progn! can be used like [progn], even in [books]. But unlike [progn],
progn! does not require its constituent forms to be [events] (see
[embedded-event-form]), except that the first form cannot be a
symbol unless it is :state-global-bindings (advanced feature,
described below). However, see [make-event] for a ``Restriction to
the Top Level'' that still applies under a call of progn!.
Because progn! allows non-events, it differs from progn in another
important respect: progn! is illegal unless there is an active
ttag; see [defttag].
See community book [hacker] for two macros, [with-raw-mode] and
[with-redef-allowed], each defined in terms of progn!, that allow
arbitrary forms in contexts that would normally require legal
embedded event forms.
Given a form (progn! form1 form2 ... formk), ACL2 will evaluate each
formi in turn (for i from 1 to k). If a form returns more than one
value (see [mv]) where the first value returned is not nil, then no
later form will be evaluated and the result returned by the progn!
call will be (mv erp val state) for some non-nil value erp,
signifying an error (see [ld-error-triples]). Otherwise the
evaluation is considered to have succeeded, and will continue with
later forms. The value returned by a call of progn! with no such
error is of the form (mv nil v state), where v depends on the last
form as follows. If the last form evaluates to a single value, then
v is that value, except if the value is a [stobj], say ST, then v
is the symbol REPLACED-ST. Otherwise the last form evaluates to
some (mv nil x ...), and v is x unless after the final form's
evaluation we are in raw-mode (see [set-raw-mode]), in which case
the progn! call returns nil (so that ACL2 can at least print the
result --- imagine Lisp returning a pathname object from a load
call, for example).
The normal undoing mechanism does not generally apply to forms within
a progn! that are not legal ACL2 [events] (see
[embedded-event-form]). In particular, note that a non-[local] call
of progn! in an [encapsulate] event will generally be evaluated
twice: once on each pass. This fact is worth keeping in mind if you
are using progn! to change the state of the system; ask yourself if
it is acceptable to apply that state-changing operation more than
once.
Please note that progn! may differ from [progn] in the following
sense: definitions within a call of progn! might not be compiled.
For example, consider the following book.
(in-package \"ACL2\")
(defttag :test)
(progn (defun f1 (x) x))
(progn! (defun f2 (x) x))
If the underlying Lisp is GCL 2.6.7, then after including this
certified book (where the default certification took place,
creating a compiled file), then f1 is a compiled function but f2 is
not. For other Lisps supported by ACL2, both f1 and f2 are
compiled, though we are not sure that every function under every
call of progn! would similarly be compiled.
We now describe, for system hackers only, a sophisticated extension
of progn! not mentioned above: support for keyword argument
:state-global-bindings. If the first argument of progn! is this
keyword, then the second argument is treated as a list of bindings
as expected by ACl2 system function [state-global-let*]. Thus, in
the ACL2 loop,
(progn! :state-global-bindings bindings form1 form2 ... formk)
is treated as follows:
(progn! (state-global-let* bindings (progn! form1 form2 ... formk)))
However, in raw Lisp the former is just:
(progn form1 form2 ... formk)
Thus, one should use the :state-global-bindings argument with care,
since the behavior in the ACL2 loop can differ from that in Common
Lisp. The intention is that one bind only [state] global variables
that are relevant to evaluation of the forms within the ACL2 loop
and are harmlessly ignored for evaluation of those forms in raw
Lisp. Here is a typical sort of example, as [state] global
ld-redefinition-action is not relevant to the evaluation of [defun]
in raw Lisp.
(progn! (remove-untouchable 'ld-redefinition-action nil)
(progn! :state-global-bindings
((ld-redefinition-action '(:doit . :overwrite)))
(defun foo (x)
(cons x x)))
(push-untouchable 'ld-redefinition-action nil))
Finally, we point out a pitfall of progn! related to [stobj]s. The
following book can cause a hard Lisp error, depending on the host
Common Lisp, when certified with a non-nil value for compile-flg
(see [certify-book]).
(in-package \"ACL2\")
(defstobj st fld)
(defttag :my-ttag)
(progn! (update-fld 3 st))
The problem is that the [stobj] variable st is not known to raw Lisp.
The compilation problem disappears if the last form above is
replaced with the following two forms.
(include-book \"hacking/hacker\" :dir :system)
(with-raw-mode (update-fld 3 *the-live-st*))")
(PROGN$
(BASICS ACL2-BUILT-INS)
"Execute a sequence of forms and return the value of the last one
This macro expands to a corresponding nest of calls of prog2$; see
[prog2$]. The examples below show how this works: the first case
below is typical, but we conclude with two special cases.
ACL2 !>:trans1 (progn$ (f1 x) (f2 x) (f3 x))
(PROG2$ (F1 X) (PROG2$ (F2 X) (F3 X)))
ACL2 !>:trans1 (progn$ (f1 x) (f2 x))
(PROG2$ (F1 X) (F2 X))
ACL2 !>:trans1 (progn$ (f1 x))
(F1 X)
ACL2 !>:trans1 (progn$)
NIL
ACL2 !>
Subtopics
[Prog2$]
Execute two forms and return the value of the second one")
(PROGRAM
(DEFUN-MODE)
"To set the default [defun-mode] to :[program]
Example:
ACL2 !>:program
ACL2 p!>
Typing the keyword :program sets the default [defun-mode] to
:program.
Functions defined in :program mode are logically undefined but can be
executed on constants outside of deductive contexts. See
[defun-mode].
Calls of the following macros are ignored (skipped) when in :program
mode.
local
verify-guards
verify-termination
defaxiom
defthm
deftheory
in-theory
in-arithmetic-theory
regenerate-tau-database
theory-invariant
defchoose
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
See [defun-mode] for a discussion of the [defun-mode]s available and
what their effects on the logic are. See [default-defun-mode] for a
discussion of how the default [defun-mode] is used. This event is
equivalent to (table acl2-defaults-table :defun-mode :program), and
hence is [local] to any [books] and [encapsulate] [events] in which
it occurs. See [ACL2-defaults-table].
Recall that the top-level form :program is equivalent to (program);
see [keyword-commands]. Thus, to change the default [defun-mode] to
:program in a book, use (program), which is an embedded event form,
rather than :program, which is not a legal form for [books]. See
[embedded-event-form].
See [program-wrapper] for how to use program-mode functions to avoid
expensive [guard] checks.
Subtopics
[Program-wrapper]
Avoiding expensive guard checks using [program]-mode functions")
(PROGRAM-WRAPPER
(PROGRAM PROGRAMMING ADVANCED-FEATURES)
"Avoiding expensive guard checks using [program]-mode functions
Application programs can benefit from the avoidance of expensive
[guard] checks, as illustrated by the following contrived example.
In this example, imagine that expensive-guard is a [guard] that is
expensive to evaluate, and that expensive-update is a function that
you want to run in a context where you know the guard is true, so
you want to avoid the expense of evaluating that guard. Then when
you call expensive-update-wrapper, the call will be evaluated
directly in raw Lisp, hence without any subsidiary guard-checking
for the function expensive-update.
(defun fib (n)
(declare (xargs :guard (natp n)))
(if (zp n)
0
(if (eql n 1)
1
(+ (fib (- n 1))
(fib (- n 2))))))
(defun expensive-guard (n)
(declare (xargs :guard t))
(and (natp n)
(natp (fib n))))
(defstobj st (fld :type integer :initially 0))
(defun expensive-update (n st)
(declare (xargs :stobjs st
:guard (expensive-guard n)))
(update-fld n st))
(defun expensive-update-wrapper (n st)
(declare (xargs :stobjs st :mode :program))
(expensive-update n st))
Remark. The example was chosen to illustrates an additional point: a
potential slowdown due to what could be called ``invariant-risk''.
This is might not be a significant issue in practice, so you may
wish to stop reading here unless you suspect a possibly significant
performance hit related to warnings like the following.
ACL2 Warning [Invariant-risk] in EXPENSIVE-UPDATE-WRAPPER: Invariant-
risk has been detected for a call of function EXPENSIVE-UPDATE-WRAPPER
(as possibly leading to an ill-guarded call of UPDATE-FLD); see :DOC
invariant-risk.
You can use [set-check-invariant-risk] either simply to avoid this
warning or, at the (perhaps small) risk of unsoundness, also to
avoid the potential slowdown.
(set-check-invariant-risk t) ; no change except to avoid the warning
(set-check-invariant-risk nil) ; risk unsoundness but gain some speed
See [set-check-invariant-risk].
To understand the issue, consider the case that a [stobj] updater
(such as update-fld above) is called on ill-guarded arguments. In
that case the resulting ACL2 [state] could be ill-formed. For
example, consider the call (expensive-update-wrapper nil st). That
call leads logically to the call (update-fld nil st), which
violates the invariant that (fld st) is an integer, as specified by
the :type in the [defstobj] form above. ACL2 takes measures to
prevent this mistake by checking guards on stobj updaters. The
resulting slowdown might be trivial; for example, the following
(legal) call runs virtually instantaneously after executing
(set-check-invariant-risk nil).
(expensive-update-wrapper 40 st)
We conclude with a technical note about how the implementation
handles calls of [program]-mode functions with ``invariant-risk'',
that is, for which ACL2 considers it possible for such a call to
lead to a call of a [stobj] updater that has a non-trivial [guard].
We need to avoid such updates whose guard is violated; but guards
aren't checked in raw Lisp. In the top-level loop, every function
call (f t1 ... tk) is essentially replaced by (ec-call (f t1 ...
tk)) before its evaluation, resulting in a corresponding call of
the so-called executable-counterpart of f, sometimes called the
``*1* function'' for f, or ``*1*f''. Normally, if f is a
[program]-mode function, then the body of *1*f leads directly to a
call of f. But if f has invariant-risk, then in most cases (with
exceptions including so-called ``safe mode'' as well as the case
that (set-guard-checking :all) has been executed), a call of *1*f
will lead to evaluation of a modified body of f, where each call of
an invariant-risk function has essentially been wrapped in ec-call.
The explanation above is a simplification; for example, it does not
describe how ``*1* code'' generation is modified for [logic]-mode
functions with invariant-risk. To see exactly what is generated,
evaluate (trace! (oneify-cltl-code :native t)) immediately before
submitting the definition.")
(PROGRAMMING
(ACL2)
"Programming in ACL2
This [documentation] topic is a parent topic under which we include
documentation topics for built-in functions, macros, and special
forms, as well as topics for notions important to programming with
ACL2. If you don't find what you're looking for, see the Index or
see individual topics that may be more directly appropriate; for
example, see [events] for top-level event constructors like
[defun]. A subtopic, [ACL2-built-ins], contains as subtopics
(displayed in a flat list) most of the topics in the
[documentation] hierarchy that appear under this `programming'
topic.
Also see [debugging] for utilities that can aid in programming.
Subtopics
[ACL2-built-ins]
''Catch-all'' topic for built-in ACL2 functions
[Alists]
Operations on association lists, which bind keys to values.
[Arrays]
ACL2 arrays and operations on them
[Basics]
Basic control structures for [programming] like [if] and [cond],
binding operators like [let] and [flet], multiple-value
constructs like [mv], and so forth.
[Characters]
Characters in ACL2 and operations on them
[Compilation]
Compiling ACL2 functions
[Conses]
A cons is an ordered pair. In ACL2, data structures like [lists],
[alists], etc., are made up of conses.
[Declare]
Extra declarations that can occur in function definitions, [let]
bindings, and so forth.
[Defabbrev]
A convenient form of macro definition for simple expansions
[Defconst]
Define a constant
[Defmacro]
Define a macro
[Defpkg]
Define a new symbol package
[Defun]
Define a function symbol
[Equality-variants]
Versions of a function using different equality tests
[Errors]
Support for causing runtime errors, breaks, assertions, etc.
[Fast-alists]
Alists with hidden hash tables for faster execution
[Get-internal-time]
Runtime vs. realtime in ACL2 timings
[Guard]
Restricting the domain of a function
[Hons]
([hons] x y) returns a [normed] object equal to ([cons] x y).
[Io]
Input/output facilities in ACL2
[Irrelevant-formals]
Formals that are used but only insignificantly
[Lists]
Lists of objects, the classic Lisp data structure.
[Mbe]
Attach code for execution
[Memoize]
Turn on memoization for a specified function
[Mutual-recursion]
Define some mutually recursive functions
[Numbers]
Numbers in ACL2 and operations on them
[Packages]
Collections of symbols that act as namespaces.
[Primitive]
Primitive functions built into ACL2 without definitions
[Program-wrapper]
Avoiding expensive guard checks using [program]-mode functions
[Programming-with-state]
Programming using the von Neumannesque ACL2 [state] object
[Redefining-programs]
An explanation of why we restrict redefinitions
[Set-check-invariant-risk]
Potential slowdown for [program]-mode updates to [stobj]s or
[arrays]
[Set-duplicate-keys-action]
Control action for macro calls with duplicate keyword arguments
[Sleep]
Sleep for some number of seconds
[State]
The von Neumannesque ACL2 state object
[Stobj]
Single-threaded objects or ``von Neumann bottlenecks''
[Strings]
Strings are atomic objects that contain character sequences, like
\"Hello World\".
[Symbols]
Symbols in ACL2 and operations on them
[System-utilities]
List of system-level programming utilities
[Time$]
Time an evaluation
[Unmemoize]
Turn off memoization for the specified function")
(PROGRAMMING-KNOWLEDGE-TAKEN-FOR-GRANTED
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Background knowledge in ACL2 programming for theorem prover tutorial
This brief review of the programming language is presented as a
sequence of questions and answers meant to test your knowledge of
the ACL2 programming language. If you want a gentle introduction to
the programming language, see
{http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html
|
http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html}.
Before we get started with the programming drill, let us remind you
that all we're interested in here is the language, not the
``program development environment.'' It's impossible to program in
ACL2 or any other language without a decent environment, one that
at the very least includes a way to prepare and edit files of
programs. The two most popular program development environments
among ACL2 users are [Emacs] [{ICON}] and the Eclipse-based
[ACL2-Sedan] [{ICON}]. The Sedan provides the most support for the
new user, including real-time syntax checking and a facility for
testing among many other features. But in this drill we're not
interested in the program development environment, we're interested
in your understanding of the ACL2 language.
Q: What do you think this command does?
(defun rev (x)
(if (endp x)
nil
(append (rev (cdr x)) (list (car x)))))
A: It defines a function named rev that takes one argument, treats it
like a list, and reverses the order of the elements in that list.
To figure this out from the definition, you have to know that
append concatenates two lists. Logically speaking, the defun of rev
adds the axiom:
(rev x)
=
(if (endp x)
nil
(append (rev (cdr x)) (list (car x)))),
implicitly quantified for all x.
Q: Given the defun of rev above, what are the formal parameters? What
is the body of the definition? Write down a call of append that
occurs in the body of rev. What are the actuals of that call? A:
The formals of rev is the list of variables after the first rev in
the defun, namely (x). We say x is the first (and only) formal
here. The body of rev is the entire if-expression. The only call of
append in the body is
(append (rev (cdr x)) (list (car x)))
and the actuals of that call are, respectively, (rev (cdr x)) and
(list (car x)).
Q: What do you get if you evaluate (rev '(a b c d))? A: (D C B A).
Q: How did rev change the case of the elements, e.g., lowercase a was
in the input list but uppercase A was in the output? A: This is a
trick question. Rev doesn't change the case of the elements. ACL2
is case-insensitive when dealing with symbols. The symbol a is read
in as the symbol A. Thus, when writing function names, for example,
we can write rev, Rev, REV, or even ReV and always be referring to
the function REV. By default, ACL2 prints symbols in uppercase.
Q: What does (rev '((a b c) \"Abc\" \"a\" b #\\c)) return? A: (#\\c B \"a\"
\"Abc\" (A B C)). If you thought the answer was any of these, then
you need to think or read more carefully:
(#\\C B \"A\" \"ABC\" (A B C))
(#\\C B \"A\" \"ABC\" (C B A))
The first wrong answer above is wrong because Lisp is ``case
insensitive'' only for symbols, not for character objects like #\\c
(the lowercase character c) or for strings. Furthermore, \"A\" is a
string, not a symbol; it is different from A. The second wrong
answer above is wrong because rev does not go into the individual
elements of the list, it just reverses the order of the elements.
So it doesn't change the element (A B C) to (C B A).
Q: In the question about what (rev '(a b c d)) returns, we put a
quote mark before the (a b c d) but not before the answer, (D C B
A). Why? A: The phrase ``x evaluates to y'' treats x as a term to
be evaluated and y as an object. (Rev '(a b c d)) is a term to be
evaluated and denotes a call of the function rev on the value of
the argument term '(a b c d). The value of that argument term is
the object (a b c d). The value of the call of rev is the object (d
c b a). If you have an object, obj, and you wish to create a term
whose value is obj, then you put a quote mark in front of it, 'obj.
Q: Can rev be applied to something other than a list? A: Yes, every
ACL2 function can be applied to any object. ACL2 is an untyped
programming language: every variable ranges over the entire
universe of objects. In normal usage, rev is applied to lists but
there is nothing about the syntax of the language that prevents it
being applied to non-lists.
Q: So what does (rev 23) evaluate to? A: Nil.
Q: Why? A: Because (endp 23) is t, because endp is defined:
(defun endp (x) (not (consp x)))
Thus, if rev is applied to anything that is not a cons, it returns
nil.
Q: So what does (rev '(a b c . d)) evaluate to? A: (c b a). To
explain why requires demonstrating that you know what (a b c . d)
means. It is the object computed by evaluating:
(cons 'a
(cons 'b
(cons 'c
'd))).
That is, it is a list whose ``terminal marker'' is the atom D. Rev
treats that list exactly as it treats the nil-terminated list of
the same elements, (a b c), because (endp 'D) = (endp nil) = t.
Q: What does (rev 1 2 3) evaluate to? A: That's a trick question. Rev
takes one argument, not three. So (rev 1 2 3) is an ill-formed
term.
Q: What does (rev '(a b c . d . nil)) evaluate to? A: That is a trick
question. There is no such object. In Lisp's ``dot notation'' every
dot must be followed by a well-formed object and then a close
parenthesis. Usually that ``well-formed object'' is an atom. If it
is not an atom, i.e., if it is a cons, then the entire expression
could have been written without that dot. For example, (a b c . (d
e)) is an object, but it could be written (a b c d e).
Q: Do (rev (rev x)) and x always evaluate to the same object? A: No.
(Rev (rev 23)) evaluates to nil, not 23.
Q: Do (rev (rev x)) and x always evaluate to the same object when x
is a cons? A: No. (rev (rev '(a b c . d))) evaluates to (a b c),
not (a b c . d).
Q: When are (rev (rev x)) and x equal? A: When the terminal marker of
x is nil.
Q: Can you define a Lisp function that recognizes nil-terminated
lists? A: Yes, but it is not necessary for the user to define that
concept because Common Lisp provides such a function which is
logically defined as follows:
(defun true-listp (x)
(if (consp x)
(true-listp (cdr x))
(equal x nil))).
This can be paraphrased: (true-listp x) means that if x is a cons,
its cdr is a true-listp and if x is not a cons, it must be nil.
Thus, (true-listp '(a b c)) is t and (true-listp '(a b c . d)) is
nil.
Q: Can you write a Lisp formula that says ``If z is a nil-terminated
list then reversing the result of reversing z is z''?
A: Yes:
(implies (true-listp z)
(equal (rev (rev z)) z)).
Q: Is this all there is to ACL2 programming? A: No! ACL2 provides
many other features. For a full list of all the primitive functions
in ACL2 see [programming] [{ICON}]. Some highlights for the
beginner are mentioned below, but all of the links below ought to
be tagged with the [{ICON}] sign.
* [list]: build a nil-terminated list from the values of n terms,
e.g., (list x (+ 1 x) (+ 2 x)) returns (3 4 5) if x is 3.
* [list*]: build a non-nil terminated list of n objects from the
values of n+1 terms, e.g., (list* x (+ 1 x) (+ 2 x) (* -1 x))
returns the list (3 4 5 . -3) if x is 3.
* [and], [or], [not], [implies], [iff]: The propositional
connectives. And and or are allowed to take a varying number of
arguments, e.g., (and p q r) is just an abbreviation for (and p
(and q r)). In Lisp, and returns nil if any of its arguments
evaluates to nil; otherwise it returns the value of the last
argument! Thus, (and t t 3) returns 3! If you object to the idea
that and is not Boolean, don't give it non-Boolean arguments!
Similarly, or returns the value of the first argument that
evaluates to non-nil, or nil if they all evaluate to nil. Both and
and or can be thought of as ``lazy'' in that they don't always have
to evaluate all their arguments. This is really accomplished by
treating and and or as abbrevations for if nests.
* [+], [*], [-], [/], [floor], [mod], [<], [<=], [>=], [>]: the Lisp
elementary arithmetic operators. Both + and * allow varying numbers
of arguments. All the arithmetic operators default non-numeric
arguments to 0. If you don't like the idea that (+ 1 2 t) is 3,
don't ask + to add t to something!
* [natp], [integerp], [rationalp], [characterp], [stringp],
[symbolp], [consp]: the recognizers for the primitive data types.
The first three recognize subsets of the ACL2 numeric universe. The
naturals are a subset of the integers, the integers are a subset of
the rationals, and the rationals are a subset of the objects
recognized by [ACL2-numberp], which also includes the
[complex-rationalp]s. The other recognizers listed above recognize
characters, strings, symbols, and conses.
* [cond]: a convenient way to write a cascading nest of ifs, e.g.,
(cond ((not (natp x)) 'non-natural)
((equal x 0) 'zero)
((evenp x) 'positive-even)
(t 'positive-odd))
abbreviates
(if (not (natp x))
'non-natural
(if (equal x 0)
'zero
(if (evenp x)
'positive-even
'positive-odd))).
* [case]: a convenient way to case split on the identity of an
object.
(case key
(non-natural -1)
(zero 0)
((positive-even positive-odd) 'positive-natural)
(otherwise 'unknown))
abbreviates
(cond ((eql key 'non-natural) -1)
((eql key 'zero) 0)
((member key '(positive-even positive-odd))
'positive-natural)
(t 'unknown)).
* user defined macros: using [defmacro] [{ICON}] you can introduce
your own abbreviations. We recommend you not do this until you're
good at list processing since macros are functions that build
objects representing terms.
* [mutual-recursion]: allows you to define mutually-recursive
functions.
* [mv] and [mv-let]: allow functions to return ``multiple-values''.
In Lisp, such functions return vectors of values, the vectors are
represented as lists of values, but the implementations are
generally more efficient. For example, (mv x y z) returns a
``vector'' consisting of the values of x, y, and z.
(mv-let (a b c)
(foo x)
(bar a b c x))
evaluates (foo x), treats the result as a vector of three values,
binds the variables a, b, and c to those three values, and
evaluates and returns (bar a b c x).
ACL2 also provides many other features, such as single-threaded
objects which may be ``destructively modified'' (see [stobj]
[{ICON}], including a very special single-threaded object that
records the [state] [{ICON}] of the ACL2 system), file input and
output (see [io] [{ICON}]), applicative arrays (see [arrays]
[{ICON}]) and property lists (see [getprop] [{ICON}]) and other
facilities necessary for it to be a practical programming language.
However, we strongly recommend that as a new user you stay away
from these features until you are good at proving theorems about
elementary list processing!
If this little drill made sense to you, you know enough of the
programming language to get started. Use your browser's Back Button
now to return to [introduction-to-the-theorem-prover].
If you are uncomfortable with ACL2 programming, we recommend that you
study
{http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html
|
http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html}
and
{http://www.cs.utexas.edu/users/moore/publications/acl2-programming-exercises1.html
|
http://www.cs.utexas.edu/users/moore/publications/acl2-programming-exercises1.html}.
However, we strongly recommend that you first invest in learning
either the [Emacs] or Eclipse-based [ACL2-Sedan] program
development environments, since it is foolish to try to learn how
to program in a stand-alone read-eval-print loop!
While getting started, many users find the Hyper-Card a handy index
into the documentation for the ACL2 language:
{http://www.cs.utexas.edu/users/moore/publications/hyper-card.html |
http://www.cs.utexas.edu/users/moore/publications/hyper-card.html}
Once you are comfortable with the ACL2 programming language, use your
browser's Back Button to return to
[introduction-to-the-theorem-prover].")
(PROGRAMMING-WITH-STATE
(STATE PROGRAMMING)
"Programming using the von Neumannesque ACL2 [state] object
This [documentation] section introduces some common techniques for
programming using the ACL2 state object. A prerequisite is thus a
basic understanding of that object; see [state]. We hope this
section is useful, and we invite suggestions for improvements and
additions.
A supplement to this section is the ACL2 source code, which uses most
(and probably all) of the techniques discussed here. That code is
thus a source of many examples, which can serve as ``templates'' to
guide one's own programming with state.
Recall that ``ACL2'' stands for ``A Computational Logic for
Applicative Common Lisp''. In particular, the language is
applicative: there are no global variables or side effects. For
many purposes this does not feel restrictive; for example, an ACL2
user who is programming in raw Lisp may well be more comfortable
coding a factorial function applicatively, using recursion, rather
than using iteration with repeated assignment to the same variable.
However, there are situations that call for reading or modifying the
system state, such as performing input and output, signalling
errors, saving information from one computation for use in a later
one, or reading and updating system-level or environmental data.
This section provides an introductory guide for writing functions
that traffic in state. We emphasize that this guide is intended as
an introduction; more complete documentation may often be found by
following links to documentation of individual utilities, and
again, more examples may be found by searching the ACL2 source code
for uses of the functions and macros mentioned below. The rest of
this section is organized as follows.
ENABLING PROGRAMMING WITH STATE
STATE GLOBALS AND THE ACL2 LOGICAL WORLD
A REMARK ON GUARDS
ERRORS AND ERROR TRIPLES
SEQUENTIAL PROGRAMMING
BINDING VARIABLES USING ERROR TRIPLES
BINDING STATE GLOBAL VARIABLES
INPUT AND OUTPUT
TIMINGS
ENVIRONMENT AND SYSTEM
REMARKS ON EVENTS AND LD
ADVANCED TOPICS
ENABLING PROGRAMMING WITH STATE
In order to submit a definition that takes [state] as a formal
parameter, you must either declare state as a :[stobj] (see
[xargs]) or first evaluate the following form at the top level:
(set-state-ok t).
Consider for example the following trivial definition.
(defun foo (state)
(mv 3 state))
If you submit the above definition in a fresh ACL2 session, you will
get this error message.
ACL2 Error in ( DEFUN FOO ...): The variable symbol STATE should not
be used as a formal parameter of a defined function unless you are
aware of its unusual status and the restrictions enforced on its use.
See :DOC set-state-ok.
If first you evaluate (set-state-ok t), you can admit the above
definition. Alternatively, you can declare state as a :[stobj], as
follows.
(defun foo (state)
(declare (xargs :stobjs state))
(mv 3 state))
A difference in the two approaches is that for the latter, a [guard]
proof obligation is generated by default. See the section below
entitled ``A remark on guards''.
STATE GLOBALS AND THE ACL2 LOGICAL WORLD
Recall (see [state]) that one of the fields of the ACL2 state object
is the global-table, which logically is an alist associating
symbols, known as ``state globals'' or ``state global variables'',
with values. But no such alist actually exists in the
implementation. Instead, ACL2 provides utilities for reading state
globals --- see [@] and see [f-get-global] --- and utilities for
writing them --- see [assign] and see [f-put-global]. The following
log shows how they work; further explanation follows below.
ACL2 !>(assign my-var (+ 3 4))
7
ACL2 !>(@ my-var)
7
ACL2 !>(f-put-global 'my-var (+ 1 5) state)
<state>
ACL2 !>(f-get-global 'my-var state)
6
ACL2 !>
Note that the first result is indented by one space. This is ACL2's
way to indicate that the [assign] expression returned an ``error
triple'' and that no error was signalled. We discuss error triples
in more detail below; also see [error-triple].
As illustrated above, the output signatures of the utilities for
assigning to state globals differ from each other as follows:
[f-put-global] returns state, but [assign] returns an error triple
(mv nil val state) where val is the value assigned to the state
global. The output signatures of the utilities for reading, @ and
f-get-global, are identical. In fact, the form (f-get-global
'my-var state) is the single-step macroexpansion of the form (@
my-var), as can be confirmed using [trans1].
ACL2 !>:trans1 (@ my-var)
(F-GET-GLOBAL 'MY-VAR STATE)
ACL2 !>
State globals are useful for conveying persistent state information.
Consider for example the utility [set-inhibit-output-lst]. The form
(set-inhibit-output-lst '(prove proof-tree)) is approximately
equivalent to (assign inhibit-output-lst '(prove proof-tree)). We
say ``approximately'' because set-inhibit-output-lst additionally
does some error checking to insure that all the tokens in the new
list are legal. When deciding whether to print output, the ACL2
system reads the value of state global variable inhibit-output-lst.
A particularly useful state global is current-acl2-world, whose value
is the ACL2 logical [world]. Because the ACL2 world is commonly
accessed in applications that use the ACL2 state, ACL2 provides a
function that returns the world: (w state) = (f-get-global
'current-acl2-world state). While it is common to read the world,
only functions set-w and set-w! are available to write the world,
but these are untouchable and these should generally be avoided
except by system implementors (pl[remove-untouchable]).
A REMARK ON GUARDS
For a function definition (see [defun]), if state is specified as a
[stobj] as with the form (declare (xargs :stobjs state)), then the
[guard] for that function is considered to include the condition
(state-p state). By default, [guard] verification will then be
performed.
We can illustrate this point by modifying the example above as
follows, to read the value of state global gag-mode.
(defun foo (state)
(declare (xargs :stobjs state))
(f-get-global 'gag-mode state))
If you try this in a fresh ACL2 session, the proof will fail with the
following key checkpoint, which says that the state global gag-mode
is bound in the global-table of the state.
(IMPLIES (STATE-P1 STATE)
(ASSOC-EQUAL 'GAG-MODE (NTH 2 STATE)))
How can we deal with this proof failure? One way is simply to ignore
the issue by defining the function in :[program] mode, as follows.
(defun foo (state)
(declare (xargs :stobjs state
:mode :program))
(f-get-global 'gag-mode state))
Perhaps a better way is to strengthen the guard to assert that the
indicated state global is bound, as follows.
(defun foo (state)
(declare (xargs :guard (boundp-global 'gag-mode state)
:stobjs state))
(f-get-global 'gag-mode state))
Also see [guard-miscellany] for a discussion of how guards are
generated from [xargs] fields of [declare] forms, specifically, for
keywords :guard and :stobjs.
ERRORS AND ERROR TRIPLES
When evaluation returns three values, where the first two are
ordinary objects and the third is the ACL2 state, the result may be
called an ``error triple''. (Whether it is treated as an error
triple depends on the programmer.) Error triples are often denoted
(mv erp val state), and common ACL2 programming idioms treat erp as
a flag indicating whether an error is being signalled and val as
the ``value'' computed. Also see [error-triple].
Even ACL2 users who are not programmers encounter error triples,
because these are the values returned by evaluation of ACL2
[events]. Consider the following log, where the only user input is
the defun form following the [prompt].
ACL2 !>(defun foo (x) x)
Since FOO is non-recursive, its admission is trivial. We observe that
the type of FOO is described by the theorem (EQUAL (FOO X) X).
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO
ACL2 !>
All output above results from explicit calls of output functions,
except for the next-to-last line, which contains FOO. Notice the
single-space indentation preceding FOO. That space indicates that
in fact, the value returned by evaluation of the defun form is the
error triple whose error flag is nil and whose computed value is
FOO. By default, ACL2 prints any error triple (mv nil val state) by
inserting a space before printing val. You can change the default
by setting state global [ld-post-eval-print] to t; notice how the
same result is printed below.
ACL2 !>:u
0:x(EXIT-BOOT-STRAP-MODE)
ACL2 !>(set-ld-post-eval-print t state)
(NIL T <state>)
ACL2 !>(defun foo (x) x)
Since FOO is non-recursive, its admission is trivial. We observe that
the type of FOO is described by the theorem (EQUAL (FOO X) X).
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
(NIL FOO <state>)
ACL2 !>
The way error triples are printed by ld is controlled not only by
state global ld-post-eval-print, but also by state global
ld-error-triples. These are examples of ``ld specials''; see [ld],
see [ld-post-eval-print], and see [ld-error-triples].
It is so common to produce an error triple whose first (error flag)
component is nil that ACL2 provides a handy macro, value, for this
purpose. Thus, (value <expression>) is equivalent to (mv nil
<expression> state). Also see [value-triple] for a similar
construct that is a legal event form.
We turn now to the topic of errors. The macro [er] ``causes'' an
error, but there are really two quite different kinds of errors:
``soft'' and ``hard'' errors. We use the term ``soft error'' to
refer to a form that returns an error triple (mv erp val state) for
which erp is non-nil. Soft errors do not interrupt the normal flow
of evaluation: the error triple is returned to the caller which
interprets the erp flag and val as directed by the programmer.
Macros discussed below make it convenient to think about soft
errors as short-circuiting the computation. Hard errors, on the
other hand, do actually rip control away from the current
evaluation and return it to the top-level loop. Logically speaking,
expressions that cause hard errors return nil in the error case,
but the nil is never seen in actual evaluation because control does
not return to the caller.
Note that the function [abort!], which you can invoke by typing
:[a!], always returns to the top level. Note that ACL2 can prove
that (abort!) returns nil but that this cannot be confirmed by
computation.
ACL2 !>(thm (equal (abort!) nil))
Q.E.D.
Summary
Form: ( THM ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL)
(:TYPE-PRESCRIPTION ABORT!))
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Proof succeeded.
ACL2 !>(equal (abort!) nil)
Abort to ACL2 top-level
...
ACL2 !>
(What actually happens with a hard error, including non-default
cases, is a bit subtle; most readers will probably want to skip
this paragraph. The read-eval-print loop implemented by [ld] is
implemented by a call of the ACL2 evaluator function, trans-eval,
on each input form. If a hard error occurs during evaluation of an
input form, its trans-eval call will return with a soft error.
[Ld], in turn handles that soft error appropriately; see
[ld-error-action].)
The most common way to signal errors is the macro [er], which prints
a formatted error message and returns a soft or hard error as
specified by the call. Note however that soft errors are signalled
using :[program] mode functions.
Since the output signatures of soft and hard errors are different ---
hard errors ``return'' a single value while soft errors return a
triple --- mixing them in an expression requires embedding the hard
error form in (an irrelevant) triple, as illustrated below. All
branches of the expression must produce an error triple if any
branch does.
ACL2 !>(defun chk-find-or-abort (e x state)
(declare (xargs :mode :program))
(if (endp x)
(value ; Note use of VALUE!
(er hard 'chk-find-or-abort
\"Did not find ~x0!\"
e))
(if (not (integerp (car x)))
(er soft 'chk-find-or-abort
\"Non-integer, ~x0, in list!\"
(car x))
(if (eql (car x) e)
(value x)
(chk-find-or-abort e (cdr x) state)))))
Summary
Form: ( DEFUN CHK-FIND-OR-ABORT ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
CHK-FIND-OR-ABORT
ACL2 !>(chk-find-or-abort 3 '(1 2 3 4 5) state)
(3 4 5)
ACL2 !>(chk-find-or-abort 3 '(1 A 3 4 5) state)
ACL2 Error in CHK-FIND-OR-ABORT: Non-integer, A, in list!
ACL2 !>(chk-find-or-abort 3 '(1 2 4 5) state)
HARD ACL2 ERROR in CHK-FIND-OR-ABORT: Did not find 3!
...
ACL2 !>
See [er] for further discussion of errors. For some other individual
topics related to errors see [assert$], see [break-on-error], see
[error1], see [hard-error], see [illegal], and see
[ld-error-triples].
In the next section we discuss soft errors further, in the context of
programming.
SEQUENTIAL PROGRAMMING
This section describes handy ways to modify state in steps, using
macros that implement a sequence of [let] or [mv-let] bindings. For
example, suppose you want to assign the values 1 and 2 to two state
globals one-var and two-var, respectively. Because of ACL2's
syntactic restrictions on [state], it is not legal simply to write
(f-put-global 'two-var 2 (f-put-global 'one-var 1 state)). However,
[let] comes to the rescue as follows.
(let ((state (f-put-global 'one-var 1 state)))
(let ((state (f-put-global 'two-var 2 state)))
state))
It is so common to bind state successively in such a manner that ACL2
provides a macro, [pprogn], for this purpose. Thus, an equivalent
solution to the problem above is
(pprogn (f-put-global 'one-var 1 state)
(f-put-global 'two-var 2 state)
state)
or, more simply, as follows.
(pprogn (f-put-global 'one-var 1 state)
(f-put-global 'two-var 2 state))
See [pprogn]. Note that the last form is allowed to return multiple
values; the only requirement on the last form is that its value
include state.
It is also common to update the state using a sequence of forms such
that each returns an error triple, where the intention is for
evaluation to short-circuit immediately if a soft error is
encountered. Suppose <expr1> and <expr2> are expressions that
return error triples, where the state components of the error
triples might be updated, and one wishes to evaluate <expr1> and
then <expr2>, returning the (multiple) values returned by <expr2>
unless the error triple returned by <expr1> is a soft error, in
which case that error triple is returned. One can of course do so
as follows.
(mv-let (erp val state)
<expr1>
(cond (erp (mv erp val state))
(t <expr2>)))
But ACL2 provides a handy macro, [er-progn], for this purpose. The
following code is equivalent to the code just above.
(er-progn <expr1> <expr2>)
See [er-progn] for more details. Note that unlike [pprogn], the
return [signature] for the last expression must be the same as that
of the others: an error triple.
Let's consider how to use pprogn and er-progn together. In the
following example f1 and f2 both return state, while each of g1 and
g2 returns an error triple. The following code modifies state by
executing these in the order f1, g1, f2, and finally g2, returning
(mv nil val state) where val is the value component of the error
triple returned by g2 --- except we return a soft error if g1 or g2
returns a soft error.
(pprogn (f1 x state)
(er-progn (g1 x state)
(pprogn (f2 x state)
(g2 x state))))
Finally, consider the [events] [progn] and [progn!]. These have
similar behavior to that of [er-progn]. However, [progn] and
[progn!] may only be used in event contexts, for example at the top
level or immediately underneath a call of [encapsulate] or [progn],
while [er-progn] has no such restriction. So when writing code, use
er-progn rather than [progn] or [progn!]. In particular, the body
of a [defun] must not have any calls of progn (or of progn!
either), and the same restriction holds for any code to be
executed, such as the body of a [make-event] form.
BINDING VARIABLES USING ERROR TRIPLES
In this section we discuss the macro er-let*, which is a variant of
the special form, [let*], that is useful when programming with
state.
The macro er-let* is useful when binding variables to the value
components of error triples. It is actually quite similar to
er-progn, described above, except that er-let* binds variables.
First consider the following example.
(er-let* ((x1 (f1 state))
(x2 (f2 x1 state)))
(value (cons x1 x2)))
The code just above is essentially equivalent to writing the
following.
(mv-let (erp x1 state)
(f1 state)
(cond (erp (mv erp x1 state))
(t (mv-let (erp x2 state)
(f2 x1 state)
(cond (erp (mv erp x2 state))
(t (value (cons x1 x2))))))))
As suggested by the example above, er-let* has the same syntax as
let*, except that declarations are not supported. (But note that
ignore declarations are not needed; all variables that are bound
are also used, at least in the error case. Consider replacing (cons
x1 x2) by nil in the example displayed immediately above, and note
that x1 and x2 are still used.) However, unlike let*, er-let*
requires that for each binding (var expr), the expression expr must
evaluate to an error triple and, moreover, it requires that the
second argument (the ``body'') of er-let* must evaluate to an error
triple. If one of the variable expressions (e.g., the f1 and f2
calls above) signals an error, its error triple is returned as the
value of the er-let*.
Of course, soft errors can be ``caught'' by using [mv-let] instead of
er-let* and simply ignoring the error flag or, more generally, by
returning a non-erroneous error triple even if the error flag was
on.
BINDING STATE GLOBAL VARIABLES
In this section we introduce a utility, [state-global-let*], that is
an analogue of let* for state global variables. Consider the
following example.
(state-global-let*
((inhibit-output-lst (add-to-set-eq 'summary (@ inhibit-output-lst))))
(thm (equal x x)))
This form binds state global variable inhibit-output-lst to the
result of adding the symbol, summary, to the current value of that
state global. Thus (see [set-inhibit-output-lst]), the usual
summary is not printed when evaluating this call of [thm].
See [state-global-let*] for more complete [documentation].
INPUT AND OUTPUT
In ACL2, most input and output involves the ACL2 state. See [io].
TIMINGS
For how to obtain the time elapsed since the start of the ACL2
session, see [read-run-time].
For a utility for saving times into the ACL2 state and for printing
those saved times, see the community book misc/save-time.lisp.
To time an evaluation (though this really isn't about state), see
[time$].
ENVIRONMENT AND SYSTEM
Next, we mention briefly some ways in which ACL2 interacts with its
environment using the ACL2 state.
For how to read and write environment variables, see [getenv$] and
see [setenv$].
For how to run a command in the host operating system, see [sys-call]
and [sys-call+].
REMARKS ON EVENTS AND LD
In general, undefined or surprising behavior may occur when using
ACL2 [events] or calling [ld] in your programs. In some cases ACL2
enforces restrictions against these uses. We strongly discourage
using [ld] in programs, as it has been designed to be called only
at the top level of a read-eval-print loop. However, you may wish
to read or write [ld] specials in your programs; see [ld].
There is also a restriction on contexts in which [make-event] may be
called: it may only be called in a context where an event is
expected, such as the top level, in a book, or as an argument of
[encapsulate] or [progn]. The reason is that ACL2 does very subtle
and careful tracking of [make-event] expansions; and it is only
able to do this in event contexts, where it is able to carry out
such tracking accurately.
ADVANCED TOPICS
ACL2 provides the function trans-eval to evaluate an arbitrary form
(after translating it to a [term], i.e., into internal form). For
more information, we refer to reader to comments in the definition
of trans-eval in the ACL2 source code. There are also many examples
of its use in the ACL2 sources.
For a function that provides the true absolute filename, with soft
links resolved, see [canonical-pathname].
For a function that returns a check-sum on the characters in a
channel, see [check-sum].
To obtain a random number, see [random$].
If you are programming in raw-mode (see [set-raw-mode]) or in raw
Lisp, use the variable *the-live-state* in place of the variable
state.
We invite suggestions for additional advanced topics.
Subtopics
[@]
Get the value of a global variable in [state]
[Assign]
Assign to a global variable in [state]
[Canonical-pathname]
The true absolute filename, with soft links resolved
[Cbd]
Connected book directory string
[Er-progn]
Perform a sequence of state-changing ``error triples''
[Error-triple]
A common ACL2 programming idiom
[F-get-global]
Get the value of a global variable in [state]
[F-put-global]
Assign to a global variable in [state]
[Getenv$]
Read an environment variable
[Last-prover-steps]
The number of prover steps most recently taken
[Oracle-apply]
Call a function argument on the given list of arguments
[Oracle-apply-raw]
Call a function argument on the given list of arguments, no
restrictions
[Oracle-funcall]
Call a function argument on the remaining arguments
[Pprogn]
Evaluate a sequence of forms that return [state]
[Read-ACL2-oracle]
Pop the oracle field of the state
[Read-run-time]
Read elapsed runtime
[Setenv$]
Set an environment variable
[State-global-let*]
Bind [state] global variables
[With-live-state]
Allow a reference to state in raw Lisp")
(PROMPT
(LD)
"The prompt printed by [ld]
The prompt printed by ACL2 conveys information about various
``modes.'' See [default-print-prompt] and see [ld-prompt] for
details.
The prompt during raw Lisp breaks is, with most Common Lisp
implementations, adjusted by ACL2 to include the string \"[RAW
LISP\"], in order to reminder users not to submit ACL2 forms there;
see [breaks]. For Lisps that seem to use the same code for printing
prompts at the top-level as in [breaks], the top-level prompt is
similarly adjusted. For Lisps with the above prompt adjustment, The
following forms may be executed in raw Lisp (i.e., after typing
:q).
(install-new-raw-prompt) ; install prompt with [RAW LISP] as described above
(install-old-raw-prompt) ; revert to original prompt from host Common Lisp")
(PROOF-CHECKER
(ACL2 DEBUGGING)
"An interactive tool for controlling ACL2's proof processes.
Call this up with (verify ...).
This is an interactive system for checking ACL2 theorems, or at least
exploring their proofs. One enters it using the VERIFY command (see
[verify]), and then invokes commands at the resulting prompt to
operate on a stack of goals, starting with the single goal that was
supplied to VERIFY. The final command (or ``instruction'') can be
an exit command, which can print out a [defthm] event if the goal
stack is empty; see [proof-checker-commands], in particular the
exit command. That resulting defthm event includes an
:[instructions] parameter, which directs replay of the
proof-checker commands (for example during certification of a book
containing that event; see [books]).
If you exit the proof-checker interactive loop, you may re-enter that
session at the same point using the command (verify), i.e., with no
arguments. The commands save and retrieve may be invoked to manage
more than one session.
The proof-checker can be invoked on a specific subgoal, and the
resulting :instructions can be given as a hint to the theorem
prover for that subgoal. See [instructions].
A tutorial is available on the world-wide web:
{http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html |
http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html}.
The tutorial illustrates more than just the proof-checker. The
portion relevant to the proof-checker may be accessed directly:
{http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html#slide29
|
http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html#slide29}
See [set-evisc-tuple] for how to arrange that output is printed in
abbreviated form. In general, the proof-checker uses the :TERM
[evisc-tuple] described in that documentation.
Individual proof-checker commands are documented in subsection
[proof-checker-commands].
Subtopics
[Define-pc-help]
Define a macro command whose purpose is to print something
[Define-pc-macro]
Define a proof-checker macro command
[Define-pc-meta]
Define a proof-checker meta command
[Dive-into-macros-table]
Right-associated function information for the [proof-checker]
[Instructions]
Instructions to the proof checker
[Macro-command]
Compound command for the proof-checker
[Proof-checker-commands]
List of commands for the proof-checker
[Retrieve]
Re-enter a (specified) [proof-checker] state
[Toggle-pc-macro]
Change an ordinary macro command to an atomic macro, or vice-versa
[Unsave]
Remove a [proof-checker] state
[Verify]
Enter the interactive proof checker")
(PROOF-CHECKER-COMMANDS
(PROOF-CHECKER)
"List of commands for the proof-checker
This documentation section contains documentation for individual
commands that can be given inside the interactive [proof-checker]
loop that is entered using [verify].
Subtopics
[ACL2-pc::=]
(atomic macro) attempt an equality (or equivalence) substitution
[ACL2-pc::ACL2-wrap]
(macro) same as (lisp x)
[ACL2-pc::add-abbreviation]
(primitive) add an abbreviation
[ACL2-pc::al]
(macro) same as apply-linear
[ACL2-pc::apply-linear]
(primitive) apply a linear rule
[ACL2-pc::bash]
(atomic macro) call the ACL2 theorem prover's simplifier
[ACL2-pc::bdd]
(atomic macro) prove the current goal using bdds
[ACL2-pc::bk]
(atomic macro) move backward one argument in the enclosing term
[ACL2-pc::bookmark]
(macro) insert matching ``bookends'' comments
[ACL2-pc::casesplit]
(primitive) split into two cases
[ACL2-pc::cg]
(macro) change to another goal.
[ACL2-pc::change-goal]
(primitive) change to another goal.
[ACL2-pc::cl-proc]
(macro) same as clause-processor
[ACL2-pc::claim]
(atomic macro) add a new hypothesis
[ACL2-pc::clause-processor]
(atomic macro) use a clause-processor
[ACL2-pc::comm]
(macro) display instructions from the current interactive session
[ACL2-pc::commands]
(macro) display instructions from the current interactive session
[ACL2-pc::comment]
(primitive) insert a comment
[ACL2-pc::contradict]
(macro) same as contrapose
[ACL2-pc::contrapose]
(primitive) switch a hypothesis with the conclusion, negating both
[ACL2-pc::demote]
(primitive) move top-level hypotheses to the conclusion
[ACL2-pc::dive]
(primitive) move to the indicated subterm
[ACL2-pc::do-all]
(macro) run the given instructions
[ACL2-pc::do-all-no-prompt]
(macro) run the given instructions, halting once there is a
``failure''
[ACL2-pc::do-strict]
(macro) run the given instructions, halting once there is a
``failure''
[ACL2-pc::doc]
(macro) access documentation inside the proof-checker
[ACL2-pc::drop]
(primitive) drop top-level hypotheses
[ACL2-pc::dv]
(atomic macro) move to the indicated subterm
[ACL2-pc::elim]
(atomic macro) call the ACL2 theorem prover's elimination process
[ACL2-pc::equiv]
(primitive) attempt an equality (or congruence-based) substitution
[ACL2-pc::ex]
(macro) exit after possibly saving the state
[ACL2-pc::exit]
(meta) exit the interactive proof-checker
[ACL2-pc::expand]
(primitive) expand the current function call without simplification
[ACL2-pc::fail]
(macro) cause a failure
[ACL2-pc::finish]
(macro) require completion of instructions; save error if inside
:[hints]
[ACL2-pc::forwardchain]
(atomic macro) forward chain from an implication in the hyps
[ACL2-pc::free]
(atomic macro) create a ``free variable''
[ACL2-pc::geneqv]
(macro) show the generated equivalence relation maintained at the
current subterm
[ACL2-pc::generalize]
(primitive) perform a generalization
[ACL2-pc::goals]
(macro) list the names of goals on the stack
[ACL2-pc::help]
(macro) proof-checker help facility
[ACL2-pc::hyps]
(macro) print the hypotheses
[ACL2-pc::illegal]
(macro) illegal instruction
[ACL2-pc::in-theory]
(primitive) set the current proof-checker theory
[ACL2-pc::induct]
(atomic macro) generate subgoals using induction
[ACL2-pc::lemmas-used]
(macro) print the runes (definitions, lemmas, ...) used
[ACL2-pc::lisp]
(meta) evaluate the given form in Lisp
[ACL2-pc::negate]
(macro) run the given instructions, and ``succeed'' if and only if
they ``fail''
[ACL2-pc::nil]
(macro) used for interpreting control-d
[ACL2-pc::noise]
(meta) run instructions with output
[ACL2-pc::nx]
(atomic macro) move forward one argument in the enclosing term
[ACL2-pc::orelse]
(macro) run the first instruction; if (and only if) it ``fails'',
run the second
[ACL2-pc::p]
(macro) prettyprint the current term
[ACL2-pc::p-top]
(macro) prettyprint the conclusion, highlighting the current term
[ACL2-pc::pl]
(macro) print the rules for a given name
[ACL2-pc::pp]
(macro) prettyprint the current term
[ACL2-pc::pr]
(macro) print the rules for a given name
[ACL2-pc::print]
(macro) print the result of evaluating the given form
[ACL2-pc::print-all-concs]
(macro) print all the conclusions of (as yet unproved) goals
[ACL2-pc::print-all-goals]
(macro) print all the (as yet unproved) goals
[ACL2-pc::print-main]
(macro) print the original goal
[ACL2-pc::pro]
(atomic macro) repeatedly apply promote
[ACL2-pc::promote]
(primitive) move antecedents of conclusion's implies term to
top-level hypotheses
[ACL2-pc::protect]
(macro) run the given instructions, reverting to existing state upon
failure
[ACL2-pc::prove]
(primitive) call the ACL2 theorem prover to prove the current goal
[ACL2-pc::pso]
(macro) print the most recent proof attempt from inside the
proof-checker
[ACL2-pc::pso!]
(macro) print the most recent proof attempt from inside the
proof-checker
[ACL2-pc::psog]
(macro) print the most recent proof attempt from inside the
proof-checker
[ACL2-pc::put]
(macro) substitute for a ``free variable''
[ACL2-pc::quiet]
(meta) run instructions without output
[ACL2-pc::r]
(macro) same as rewrite
[ACL2-pc::reduce]
(atomic macro) call the ACL2 theorem prover's simplifier
[ACL2-pc::reduce-by-induction]
(macro) call the ACL2 prover without induction, after going into
induction
[ACL2-pc::remove-abbreviations]
(primitive) remove one or more abbreviations
[ACL2-pc::repeat]
(macro) repeat the given instruction until it ``fails''
[ACL2-pc::repeat-rec]
(macro) auxiliary to repeat
[ACL2-pc::replay]
(macro) replay one or more instructions
[ACL2-pc::restore]
(meta) remove the effect of an UNDO command
[ACL2-pc::retain]
(atomic macro) drop all but the indicated top-level hypotheses
[ACL2-pc::retrieve]
(macro) re-enter the proof-checker
[ACL2-pc::rewrite]
(primitive) apply a rewrite rule
[ACL2-pc::run-instr-on-goal]
(macro) auxiliary to THEN
[ACL2-pc::run-instr-on-new-goals]
(macro) auxiliary to then
[ACL2-pc::runes]
(macro) print the runes (definitions, lemmas, ...) used
[ACL2-pc::s]
(primitive) simplify the current subterm
[ACL2-pc::s-prop]
(atomic macro) simplify propositionally
[ACL2-pc::save]
(macro) save the proof-checker state (state-stack)
[ACL2-pc::sequence]
(meta) run the given list of instructions according to a multitude
of options
[ACL2-pc::show-abbreviations]
(macro) display the current abbreviations
[ACL2-pc::show-linears]
(macro) display the applicable [linear] rules
[ACL2-pc::show-rewrites]
(macro) display the applicable [rewrite] rules
[ACL2-pc::show-type-prescriptions]
(macro) display the applicable [type-prescription] rules
[ACL2-pc::skip]
(macro) ``succeed'' without doing anything
[ACL2-pc::sl]
(atomic macro) simplify with lemmas
[ACL2-pc::sls]
(macro) same as SHOW-LINEARS
[ACL2-pc::split]
(atomic macro) split the current goal into cases
[ACL2-pc::sr]
(macro) same as SHOW-REWRITES
[ACL2-pc::st]
(macro) same as SHOW-TYPE-PRESCRIPTIONS
[ACL2-pc::succeed]
(macro) run the given instructions, and ``succeed''
[ACL2-pc::th]
(macro) print the top-level hypotheses and the current subterm
[ACL2-pc::then]
(macro) apply one instruction to current goal and another to new
subgoals
[ACL2-pc::top]
(atomic macro) move to the top of the goal
[ACL2-pc::type-alist]
(macro) display the [type-alist] from the current context
[ACL2-pc::undo]
(meta) undo some instructions
[ACL2-pc::unsave]
(macro) remove a proof-checker state
[ACL2-pc::up]
(primitive) move to the parent (or some ancestor) of the current
subterm
[ACL2-pc::use]
(atomic macro) use a lemma instance
[ACL2-pc::wrap]
(atomic macro) execute the indicated instructions and combine all
the new goals
[ACL2-pc::wrap-induct]
(atomic macro) same as induct, but create a single goal
[ACL2-pc::wrap1]
(primitive) combine goals into a single goal
[ACL2-pc::x]
(atomic macro) expand and (maybe) simplify function call at the
current subterm
[ACL2-pc::x-dumb]
(atomic macro) expand function call at the current subterm, without
simplifying")
(PROOF-OF-WELL-FOUNDEDNESS
(ORDINALS)
"A proof that [o<] is well-founded on [o-p]s
The soundness of ACL2 rests in part on the well-foundedness of [o<]
on [o-p]s. This can be taken as obvious if one is willing to grant
that those concepts are simply encodings of the standard
mathematical notions of the ordinals below epsilon-0 and its
natural ordering relation. But it is possible to prove that [o<] is
well-founded on [o-p]s without having to assert any connection to
the ordinals and that is what we do here. The community book
books/ordinals/proof-of-well-foundedness carries out the proof
outlined below in ACL2, using only that the natural numbers are
well-founded.
Before outlining the above mentioned proof, we note that in the
analogous documentation page of ACL2 Version_2.7, there is a proof
of the well-foundedness of e0-ord-< on e0-ordinalps, the less-than
relation and recognizer for the old ordinals (that is, for the
ordinals appearing in ACL2 up through that version). Manolios and
Vroon have given a proof in ACL2 Version_2.7 that the current
ordinals (based on [o<] and [o-p]) are order-isomorphic to the old
ordinals (based on e0-ord-< and e0-ordinalp). Their proof
establishes that switching from the old ordinals to the current
ordinals preserves the soundness of ACL2. For details see their
paper:
Manolios, Panagiotis & Vroon, Daron.
Ordinal arithmetic in ACL2.
Kaufmann, Matt, & Moore, J Strother (eds).
Fourth International Workshop on the ACL2 Theorem
Prover and Its Applications (ACL2-2003),
July, 2003.
See {http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/ | http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/}.
We now give an outline of the above mentioned proof of
well-foundedness. We first observe three facts about [o<] on
ordinals that have been proved by ACL2 using only structural
induction on lists. These theorems can be proved by hand.
(defthm transitivity-of-o<
(implies (and (o< x y)
(o< y z))
(o< x z))
:rule-classes nil)
(defthm non-circularity-of-o<
(implies (o< x y)
(not (o< y x)))
:rule-classes nil)
(defthm trichotomy-of-o<
(implies (and (o-p x)
(o-p y))
(or (equal x y)
(o< x y)
(o< y x)))
:rule-classes nil)
These three properties establish that [o<] orders the [o-p]s. To put
such a statement in the most standard mathematical nomenclature, we
can define the macro:
(defmacro o<= (x y)
`(not (o< ,y ,x)))
and then establish that o<= is a relation that is a simple, complete
(i.e., total) order on ordinals by the following three lemmas,
which have been proved:
(defthm antisymmetry-of-o<=
(implies (and (o-p x)
(o-p y)
(o<= x y)
(o<= y x))
(equal x y))
:rule-classes nil
:hints ((\"Goal\" :use non-circularity-of-o<)))
(defthm transitivity-of-o<=
(implies (and (o-p x)
(o-p y)
(o<= x y)
(o<= y z))
(o<= x z))
:rule-classes nil
:hints ((\"Goal\" :use transitivity-of-o<)))
(defthm trichotomy-of-o<=
(implies (and (o-p x)
(o-p y))
(or (o<= x y)
(o<= y x)))
:rule-classes nil
:hints ((\"Goal\" :use trichotomy-of-o<)))
Crucially important to the proof of the well-foundedness of [o<] on
[o-p]s is the concept of ordinal-depth, abbreviated od:
(defun od (l)
(if (o-finp l)
0
(1+ (od (o-first-expt l)))))
If the od of an [o-p] x is smaller than that of an [o-p] y, then x is
[o<] y:
(defun od-1 (x y)
(if (o-finp x)
(list x y)
(od-1 (o-first-expt x) (o-first-expt y))))
(defthm od-implies-ordlessp
(implies (and (o-p x)
(< (od x) (od y)))
(o< x y))
:hints ((\"Goal\"
:induct (od-1 x y))))
Remark. A consequence of this lemma is the fact that if s = s(1),
s(2), ... is an infinite, [o<] descending sequence of [o-p]s, then
od(s(1)), od(s(2)), ... is a ``weakly'' descending sequence of
non-negative integers: od(s(i)) is greater than or equal to
od(s(i+1)).
Lemma Main. For each non-negative integer n, [o<] well-orders the set
of [o-p]s with od less than or equal to n .
Base Case. n = 0. The o-ps with 0 od are the non-negative
integers. On the non-negative integers, o< is the same as <.
Induction Step. n > 0. We assume that o< well-orders the
o-ps with od less than n.
If o< does not well-order the o-ps with od less than or equal to n,
consider, D, the set of infinite, o< descending sequences of o-ps of od
less than or equal to n. The first element of a sequence in D has od n.
Therefore, the o-first-expt of the first element of a sequence in D has od
n-1. Since o<, by IH, well-orders the o-ps with od less than n, the set
of o-first-expts of first elements of the sequences in D has a minimal
element, which we denote by B and which has od of n-1.
Let k be the minimum integer such that for some infinite, o< descending
sequence s of o-ps with od less than or equal to n, the first element of s
has an o-first-expt of B and an o-first-coeff of k. Notice that k is
positive.
Having fixed B and k, let s = s(1), s(2), ... be an infinite, o<
descending sequence of o-ps with od less than or equal to n such that s(1)
has a o-first-expt of B and an o-first-coeff of k.
We show that each s(i) has a o-first-expt of B and an o-first-coeff of
k. For suppose that s(j) is the first member of s either with o-first-expt
B and o-first-coeff m (m neq k) or with o-first-expt B' and o-first-coeff
B' (B' neq B). If (o-first-expt s(j)) = B', then B' has od n-1 (otherwise,
by IH, s would not be infinite) and B' is o< B, contradicting the
minimality of B. If 0 < m < k, then the fact that the sequence beginning
at s(j) is infinitely descending contradicts the minimality of k. If m >
k, then s(j) is greater than its predecessor; but this contradicts the
fact that s is descending.
Thus, by the definition of o<, for s to be a decreasing sequence of o-ps,
(o-rst s(1)), (o-rst s(2)), ... must be a decreasing sequence. We end by
showing this cannot be the case. Let t = t(1), t(2), ... be an infinite
sequence of o-ps such that t(i) = (o-rst s(i)). Then t is infinitely
descending. Furthermore, t(1) begins with an o-p B' that is o< B. Since t
is in D, t(1) has od n, therefore, B' has od n-1. But this contradicts the
minimality of B. Q.E.D.
Theorem. [o<] well-orders the [o-p]s. Proof. Every infinite, o<
descending sequence of [o-p]s has the property that each member has
od less than or equal to the od, n, of the first member of the
sequence. This contradicts Lemma Main. Q.E.D.")
(PROOF-SUPPORTERS-ALIST (POINTERS)
"See [dead-events].")
(PROOF-TREE
(DEBUGGING)
"Proof tree displays
A view of ACL2 proofs may be obtained by way of ``proof tree
displays,'' which appear in proof output (see [proofs-co]) when
proof-tree output is enabled (see below) When ACL2 starts a proof
and proof-tree output is enabled, the proof output begins with the
following string.
<< Starting proof tree logging >>
Then for each goal encountered during the proof, a corresponding
proof tree display (as described below) is printed into the proof
output: first the characters in the constant string
*proof-tree-start-delimiter* are printed, then the proof tree
display, and finally the characters in the constant string
*proof-tree-end-delimiter*.
External tools may present proof tree displays in a separate window.
In particular, a tool distributed with the ACL2 community books
customizes the emacs environment to provide window-based proof tree
displays together with commands for traversing the proof
transcript; see the discussion of ``ACL2 proof-tree support'' in
file emacs/emacs-acl2.el distributed with ACL2.
The command :start-proof-tree enables proof-tree output, while
:stop-proof-tree disables proof-tree output; see [start-proof-tree]
and see [stop-proof-tree].
Here is an example of a proof tree display, with comments. Lines
marked with ``c'' are considered ``checkpoints,'' i.e., goals whose
scrutiny may be of particular value.
( DEFTHM PLUS-TREE-DEL ...) ;currently proving PLUS-TREE-DEL
1 Goal preprocess ;\"Goal\" creates 1 subgoal by preprocessing
2 | Goal' simp ;\"Goal'\" creates 2 subgoals by simplification
c 0 | | Subgoal 2 PUSH *1 ;\"Subgoal 2\" pushes \"*1\" for INDUCT
++++++++++++++++++++++++++++++ ;first pass thru waterfall completed
c 6 *1 INDUCT ;Proof by induction of \"*1\" has
| <5 more subgoals> ; created 6 top-level subgoals. At
; this point, one of those 6 has been
; proved, and 5 remain to be proved.
; We are currently working on the
; first of those 5 remaining goals.
See [proof-tree-examples] for many examples that contain proof tree
displays. But first, we summarize the kinds of lines that may
appear in a proof tree display. The simplest form of a proof tree
display is a header showing the current event, followed by list of
lines, each having one of the following forms.
n <goal> <process> ...
Says that the indicated goal created n subgoals using the indicated
process. Here ``...'' refers to possible additional information.
c n <goal> <process> ...
As above, but calls attention to the fact that this goal is a
``checkpoint'' in the sense that it may be of particular interest.
Some displays may overwrite ``c'' with ``>'' to indicate the
current checkpoint being shown in the proof transcript.
| <goal> ...
| | <k subgoals>
Indicates that the goal just above this line, which is pointed to by
the rightmost vertical bar (``|''), has k subgoals, none of which
have yet been processed.
| <goal> ...
| | <k more subgoals>
As above, except that some subgoals have already been processed.
++++++++++++++++++++++++++++++
Separates successive passes through the ``waterfall''. Thus, this
``fencepost'' mark indicates the start of a new proof by induction
or of a new forcing round.
See [proof-tree-examples] for detailed examples. See
[checkpoint-forced-goals] to learn how to mark goals as checkpoints
that [force] the creation of goals in forcing rounds. Finally, see
[proof-tree-details] for some points not covered elsewhere.
Subtopics
[Checkpoint-forced-goals]
Cause forcing goals to be checkpointed in proof trees
[Proof-tree-details]
Proof tree details not covered elsewhere
[Proof-tree-examples]
Proof tree example
[Start-proof-tree]
Start displaying proof trees during proofs
[Stop-proof-tree]
Stop displaying proof trees during proofs")
(PROOF-TREE-DETAILS
(PROOF-TREE)
"Proof tree details not covered elsewhere
See [proof-tree] for an introduction to proof trees, and for a list
of related topics. Here we present some details not covered
elsewhere.
1. When proof tree display is enabled (because the command
:[stop-proof-tree] has not been executed, or has been superseded by
a later :[start-proof-tree] command), then time summaries will
include the time for proof tree display. This time includes the
time spent computing with proof trees, such as the pruning process
described briefly above. Even when proof trees are not displayed,
such as when their display is turned off in the middle of a proof,
this time will be printed if it is not 0.
2. When a goal is given a :bye in a proof (see [hints]), it is
treated for the purpose of proof tree display just as though it had
been proved.
3. Several [state] global variables affect proof tree display. (@
proof-tree-indent) is initially the string \"| \": it is the string
that is laid down the appropriate number of times to effect
indentation. (@ proof-tree-buffer-width) is initially the value of
(fmt-soft-right-margin state), and is used to prevent printing of
the annotation ``([force]d ...)'' in any greater column than this
value. However, (assign proof-tree-buffer-width nil) to avoid any
such suppression. Finally, (@ checkpoint-processors) is a list of
processors from the constant list *preprocess-clause-ledge*,
together with :induct. You may remove elements of (@
checkpoint-processors) to limit which processes are considered
checkpoints, but note that this can affect what is printed by
gag-mode (see [set-gag-mode]).
4. When :[otf-flg] is not set to t in a proof, and the prover then
decides to revert to the original goal and prove it by induction,
the proof tree display will reflect this fact as shown here:
c 0 | | Subgoal 2 PUSH (reverting)
5. The usual [failure] message is printed as part of the prooftree
display when a proof has failed.")
(PROOF-TREE-EXAMPLES
(PROOF-TREE)
"Proof tree example
See [proof-tree] for an introduction to proof trees, and for a list
of related topics. Here we present a detailed example followed by a
shorter example that illustrates proof by induction.
Consider the [guard] proof for the definition of a function
cancel_equal_plus; the body of this definition is of no importance
here. The first proof tree display is:
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
| <18 subgoals>
This is to be read as follows.
At this stage of the proof we have encountered the top-level goal,
named \"Goal\", which generated 18 subgoals using the
``preprocess'' process. We have not yet begun to work on those
subgoals.
The corresponding message from the ordinary prover output is:
By case analysis we reduce the conjecture to the following 18
conjectures.
Note that the field just before the name of the goal (\"Goal\"), which
here contains the number 18, indicates the number of cases
(children) created by the goal using the indicated process. This
number will remain unchanged as long as this goal is displayed.
The next proof tree display is:
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
1 | Subgoal 18 simp
| | <1 subgoal>
| <17 more subgoals>
which indicates that at this point, the prover has used the
simplification (``simp'') process on Subgoal 18 to create one
subgoal (``<1 subgoal>''). The vertical bar (``|'') below ``Subgoal
18'', accompanied by the line below it, signifies that there are 17
siblings of Subgoal 18 that remain to be processed.
The next proof tree displayed is:
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
1 | Subgoal 18 simp
c 2 | | Subgoal 18' ELIM
| | | <2 subgoals>
| <17 more subgoals>
Let us focus on the fourth line of this display:
c 2 | | Subgoal 18' ELIM
The ``c'' field marks this goal as a ``checkpoint'', i.e., a goal
worthy of careful scrutiny. In fact, any goal that creates children
by a process other than ``preprocess'' or ``simp'' is marked as a
checkpoint. In this case, the destructor-elimination (``[elim]'')
process has been used to create subgoals of this goal. The
indentation shows that this goal, Subgoal 18', is a child of
Subgoal 18. The number ``2'' indicates that 2 subgoals have been
created (by [elim]). Note that this information is consistent with
the line just below it, which says ``<2 subgoals>''.
Finally, the last line of this proof tree display,
| <17 more subgoals>
is connected by vertical bars (``|'') up to the string \"Subgoal 18\",
which suggests that there are 17 immediate subgoals of Goal
remaining to process after Subgoal 18. Note that this line is
indented one level from the second line, which is the line for the
goal named \"Goal\". The display is intended to suggest that the
subgoals of Goal that remain to be proved consist of Subgoal 18
together with 17 more subgoals.
The next proof tree display differs from the previous one only in
that now, Subgoal 18' has only one more subgoal to be processed.
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
1 | Subgoal 18 simp
c 2 | | Subgoal 18' ELIM
| | | <1 more subgoal>
| <17 more subgoals>
Note that the word ``more'' in ``<1 more subgoal>'' tells us that
there was originally more than one subgoal of Subgoal 18. In fact
that information already follows from the line above, which (as
previously explained) says that Subgoal 18' originally created 2
subgoals.
The next proof tree display occurs when the prover completes the
proof of that ``1 more subgoal'' referred to above.
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
| <17 more subgoals>
Then, Subgoal 17 is processed and creates one subgoal, by
simplification:
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
1 | Subgoal 17 simp
| | <1 subgoal>
| <16 more subgoals>
... and so on.
Later in the proof one might find the following successive proof tree
displays.
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
| <9 more subgoals>
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
0 | Subgoal 9 simp (FORCED)
| <8 more subgoals>
These displays tell us that Subgoal 9 simplified to t (note that the
``0'' shows clearly that no subgoals were created), but that some
rule's hypotheses were [force]d. Although this goal is not
checkpointed (i.e., no ``c'' appears on the left margin), one can
cause such goals to be checkpointed; see [checkpoint-forced-goals].
In fact, the proof tree displayed at the end of the ``main
proof''(the 0-th forcing round) is as follows.
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
0 | Subgoal 9 simp (FORCED)
0 | Subgoal 8 simp (FORCED)
0 | Subgoal 7 simp (FORCED)
0 | Subgoal 6 simp (FORCED)
0 | Subgoal 4 simp (FORCED)
0 | Subgoal 3 simp (FORCED)
This is followed by the following proof tree display at the start of
the forcing round.
18 Goal preprocess
0 | Subgoal 9 simp (FORCED [1]Subgoal 4)
0 | Subgoal 8 simp (FORCED [1]Subgoal 6)
0 | Subgoal 7 simp (FORCED [1]Subgoal 1)
0 | Subgoal 6 simp (FORCED [1]Subgoal 3)
0 | Subgoal 4 simp (FORCED [1]Subgoal 5)
0 | Subgoal 3 simp (FORCED [1]Subgoal 2)
++++++++++++++++++++++++++++++
6 [1]Goal FORCING-ROUND
2 | [1]Subgoal 6 preprocess
| | <2 subgoals>
| <5 more subgoals>
This display shows which goals to ``blame'' for the existence of each
goal in the forcing round. For example, Subgoal 9 is to blame for
the creation of [1]Subgoal 4.
Actually, there is no real goal named \"[1]Goal\". However, the line
6 [1]Goal FORCING-ROUND
appears in the proof tree display to suggest a ``parent'' of the six
top-level goals in that forcing round. As usual, the numeric field
before the goal name contains the original number of children of
that (virtual, in this case) goal --- in this case, 6.
In our example proof, Subgoal 6 eventually gets proved, without doing
any further forcing. At that point, the proof tree display looks as
follows.
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
0 | Subgoal 9 simp (FORCED [1]Subgoal 4)
0 | Subgoal 7 simp (FORCED [1]Subgoal 1)
0 | Subgoal 6 simp (FORCED [1]Subgoal 3)
0 | Subgoal 4 simp (FORCED [1]Subgoal 5)
0 | Subgoal 3 simp (FORCED [1]Subgoal 2)
++++++++++++++++++++++++++++++
6 [1]Goal FORCING-ROUND
| <5 more subgoals>
Notice that the line for Subgoal 8,
0 | Subgoal 8 simp (FORCED [1]Subgoal 6)
no longer appears. That is because the goal [1]Subgoal 6 has been
proved, along with all its children; and hence, the proof of
Subgoal 8 no longer depends on any further reasoning.
The final two proof tree displays in our example are as follows.
( DEFUN CANCEL_EQUAL_PLUS ...)
18 Goal preprocess
0 | Subgoal 7 simp (FORCED [1]Subgoal 1)
++++++++++++++++++++++++++++++
6 [1]Goal FORCING-ROUND
2 | [1]Subgoal 1 preprocess
1 | | [1]Subgoal 1.1 preprocess
1 | | | [1]Subgoal 1.1' simp
c 3 | | | | [1]Subgoal 1.1'' ELIM
| | | | | <1 more subgoal>
( DEFUN CANCEL_EQUAL_PLUS ...)
<<PROOF TREE IS EMPTY>>
The explanation for the empty proof tree is simple: once [1]Subgoal
1.1.1 was proved, nothing further remained to be proved. In fact,
the much sought-after ``Q.E.D.'' appeared shortly after the final
proof tree was displayed.
Let us conclude with a final, brief example that illustrates proof by
induction. Partway through the proof one might come across the
following proof tree display.
( DEFTHM PLUS-TREE-DEL ...)
1 Goal preprocess
2 | Goal' simp
c 0 | | Subgoal 2 PUSH *1
| | <1 more subgoal>
This display says that in the attempt to prove a theorem called
plus-tree-del, preprocessing created the only child Goal' from
Goal, and Goal' simplified to two subgoals. Subgoal 2 is
immediately pushed for proof by induction, under the name ``*1''.
In fact if Subgoal 1 simplifies to t, then we see the following
successive proof tree displays after the one shown above.
( DEFTHM PLUS-TREE-DEL ...)
1 Goal preprocess
2 | Goal' simp
c 0 | | Subgoal 2 PUSH *1
( DEFTHM PLUS-TREE-DEL ...)
1 Goal preprocess
2 | Goal' simp
c 0 | | Subgoal 2 PUSH *1
++++++++++++++++++++++++++++++
c 6 *1 INDUCT
| <5 more subgoals>
The separator ``+++++...'' says that we are beginning another trip
through the waterfall. In fact this trip is for a proof by
induction (as opposed to a forcing round), as indicated by the word
``INDUCT''. Apparently *1.6 was proved immediately, because it was
not even displayed; a goal is only displayed when there is some
work left to do either on it or on some goal that it brought
(perhaps indirectly) into existence.
Once a proof by induction is completed, the ``PUSH'' line that refers
to that proof is eliminated (``pruned''). So for example, when the
present proof by induction is completed, the line
c 0 | | Subgoal 2 PUSH *1
is eliminated, which in fact causes the lines above it to be
eliminated (since they no longer refer to unproved children).
Hence, at that point one might expect to see:
( DEFTHM PLUS-TREE-DEL ...)
<<PROOF TREE IS EMPTY>>
However, if the proof by induction of *1 necessitates further proofs
by induction or a forcing round, then this ``pruning'' will not yet
be done.")
(PROOFS-CO
(IO ACL2-BUILT-INS)
"The proofs character output channel
Proofs-co is an [ld] special (see [ld]). The accessor is (proofs-co
state) and the updater is (set-proofs-co val state). Proofs-co must
be an open character output channel. It is to this channel that
[defun], [defthm], and the other event [command]s print their
commentary.
``Proofs-co'' stands for ``proofs character output.'' The initial
value of proofs-co is the same as the value of [*standard-co*] (see
[*standard-co*]).")
(PROPER-CONSP
(LISTS ACL2-BUILT-INS)
"Recognizer for proper (null-terminated) non-empty lists
Proper-consp is the function that checks whether its argument is a
non-empty list that ends in nil. Also see [true-listp].
Function: <proper-consp>
(defun proper-consp (x)
(declare (xargs :guard t))
(and (consp x) (true-listp x)))")
(PROPS
(WORLD)
"Print the ACL2 properties on a symbol
Example:
:props assoc-eq
Props takes one argument, a symbol, and prints all of the properties
that are on that symbol in the ACL2 [world].")
(PROTECT-MEMOIZE-STATISTICS
(MEMOIZE)
"Ensure the integrity of memoization statistics even upon aborts
Example Forms:
(f-put-global 'protect-memoize-statistics t state)
(assign protect-memoize-statistics t) ; same effect as above
By default, if calls of [memoize]d functions are aborted, then
statistics reported by [memsum] for those calls will often be
incorrect. Since aborts are relatively rare, this seems a
reasonable default, since avoiding such inaccuracy incurs some
additional computation time. However, evaluation of either of the
forms above will arrange that for functions memoized after such
evaluation, the accuracy of the statistics will not be adversely
affected by aborts (again, at the expense of some additional
computation time).
Once again: evaluation of a form displayed above only affects
behavior for future calls of [memoize], not for functions already
memoized at the time of that form's evaluation (unless the function
is subsequently [unmemoize]d and then once again [memoize]d).
To revert to the default state in which performance is preferred to
accuracy of memoization statistics after aborts, evaluate either of
the following forms.
(f-put-global 'protect-memoize-statistics nil state)
(assign protect-memoize-statistics nil) ; same effect as above
The following demo illustrates the effect of assigning to
protect-memoize-statistics.
(defun foo (n)
(declare (xargs :guard (natp n)))
(progn$
(sleep n)
n))
; OPTIONALLY:
(assign protect-memoize-statistics t)
(memoize 'foo)
(clear-memoize-statistics) ; for good measure
(memsum) ; should have nothing to report
(foo 1)
(memsum) ; reports 1 call, 1 second
; Now: submit this and then abort with an interrupt it after about 3 seconds.
(foo 15)
; See explanation below.
(memsum)
If the ``OPTIONAL'' form above is omitted, we get the default
behavior: the statistics from [memsum] will show 2 calls of foo
taking only took 1 second total, for an average of only 0.5
seconds, because no time was recorded for the aborted call.
However, if the ``OPTIONAL'' form above is included, then you will
see statistics that look accurate.")
(PROVER-OUTPUT
(ACL2)
"Methods for controlling the output produced by ACL2 during proofs and
in other situations.
Subtopics
[Finalize-event-user]
User-supplied code to complete [events], e.g., with extra summary
output
[Gag-mode]
Verbosity of proof output
[Get-event-data]
Obtain data stored after at the conclusion of an event
[Initialize-event-user]
User-supplied code to initiate [events]
[Pso]
Show the most recently saved output
[Pso!]
Show the most recently saved output, including [proof-tree] output
[Psof]
Show the most recently saved output
[Psog]
Show the most recently saved output in [gag-mode]
[Set-duplicate-keys-action!]
Non-[local] version of [set-duplicate-keys-action]
[Set-gag-mode]
Modify the nature of proof output
[Set-inhibit-output-lst]
Control output
[Set-inhibit-warnings]
Control warnings
[Set-inhibit-warnings!]
Control warnings non-[local]ly
[Set-inhibited-summary-types]
Control which parts of the summary are printed
[Set-let*-abstractionp]
To shorten many prettyprinted clauses
[Set-print-clause-ids]
Cause subgoal numbers to be printed when 'prove output is inhibited
[Set-raw-proof-format]
Print runes as lists in proof output from simplification
[Set-raw-warning-format]
Print some warnings in a ``raw'', s-expression format
[Warnings]
Warnings emitted by the ACL2 proof process
[With-output]
Suppressing or turning on specified output for an event")
(PROVING_THEOREMS_ABOUT_MODELS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Proving Theorems about Models
[{IMAGE}]
But ACL2 is a logic. We can prove theorems about the model.
{IMAGE}
Theorem. MC 'mult is a multiplier
(implies (and (natp x)
(natp y))
(equal (lookup 'z (mc (s 'mult x y) (mclk x)))
(* x y))).
This theorem says that a certain program running on the mc machine
will correctly multiply any two natural numbers.
It is a statement about an infinite number of test cases!
We know it is true about the model because we proved it.
Of course, models of actual machines usually only accept a finite
number of different inputs. For example, engineers at Advanced
Micro Devices (AMD), Centaur, and IBM have ACL2 models of floating
point units that operate on double precision IEEE floating point
numbers. These are finite models. But the size of their inputs is
sufficiently large that they are verified by the same mathematical
methods used to prove theorems about infinite state systems like
our little mc.
[{IMAGE}]")
(PROVISIONAL-CERTIFICATION
(BOOKS-CERTIFICATION)
"Certify a book in stages for improved book-level parallelism
Provisional certification is a process that can increase parallelism
when certifying books in parallel, typically using `make', when
certifying a collection of [books]. We got this idea from Jared
Davis, who developed rudimentary provisional certification schemes
first at Rockwell Collins and later for his `Milawa' project. Our
design has also benefited from conversations with Sol Swords.
Warning: as of November 2014, enabling provision certification via
the ACL2_PCERT flag can not be reliably enabled at the Makefile
level (as is shown below). See {Github Issue 255 |
https://github.com/acl2/acl2/issues/255} for more information.
To invoke provisional certification, see [books-certification]. For
example, you could issue the following command.
ACL2_PCERT=t cert.pl -j 4 `find . -name '*.lisp'`
Alternatively, see [books-certification-classic] for a discussion of
classic ACL2 `make'-based certification (which may disappear in a
future ACL2 release); here we extend those instructions to show how
to use provisional certification. (Also, you may wish to look at
community books file books/system/pcert/Makefile for an example.)
We begin by describing a few ways to do that. A simple way is to
add the line `ACL2_PCERT=t' to a `make' command that you use for
book certification, for example as follows.
make -j 4 ACL2_PCERT=t
The following works too, in a bash shell.
(export ACL2_PCERT=t ; time make -j 4)
Alternatively, add the line
ACL2_PCERT ?= t
to the Makefile residing in the directory, placed above the line that
specifies the `include' of file Makefile-generic. A successful
`make' will result in creating the desired [certificate] (.cert)
files.
Warning: If you put the line ``ACL2_PCERT ?= t'' below the include of
Makefile-generic, it might have no effect. For example, try editing
community books file books/system/pcert/Makefile by moving the line
``ACL2_PCERT ?= t'' to the bottom of the file, and watch ``make
top.cert'' fail to invoke provisional certification.
The description above may be sufficient for you to use provisional
certification. We provide additional documentation below for the
reader who wants to understand more about this process, for example
when not using `make'. Below we assume prior familiarity with
[books], in particular [certify-book] and [include-book]. The
remainder of this [documentation] topic is divided into sections:
Summary, Correctness Claim and Issues, Combining Pcertify and
Convert into Pcertify+, and Further Information.
Summary
Recall that certification of a book, bk, produces a [certificate]
file bk.cert. The provisional certification process produces this
file as well, but as the last of the following three steps. All of
these steps are carried out by calls of [certify-book] using its
:pcert keyword argument. We typically call these steps
``procedures'', to distinguish them from the steps of an individual
call of [certify-book].
* The ``Pcertify'' procedure (sometimes called the ``Create''
procedure) is invoked by calling [certify-book] with keyword
argument :pcert :create. It produces a file bk.pcert0,
sometimes called the ``.pcert0'' file (pronounced ``dot pee
cert zero''). Proofs are skipped during this procedure, which
can be viewed as an elaborate syntax check, augmented by
compilation if specified (as it is by default).
* The ``Convert'' procedure is invoked by calling [certify-book] with
keyword argument :pcert :convert. It creates file bk.pcert1
from bk.pcert0, by doing proofs for all events in bk.lisp. Note
that the third argument (the `compile-flg' argument) is ignored
by such a call of certify-book unless its value is :all (either
explicitly or by way of environment variable ACL2_COMPILE_FLG).
A subtlety is that if there is a compiled file at least as
recent as the corresponding .pcert0 file, then that compiled
file's write date will be updated to the current time at the
end of this procedure. The usual [local-incompatibility] check
at the end of [certify-book] is omitted for the Convert
procedure, since it was performed towards the end of the Create
procedure.
* The ``Complete'' procedure is invoked by calling [certify-book] with
keyword argument :pcert :complete. It checks that every
included book (including every one that is [local]ly included)
has a .cert file that is at least as recent as the
corresponding book. The effect is to move bk.pcert1 to bk.cert.
Note that all arguments of certify-book other than the :pcert
argument are ignored for this procedure, other than for some
trivial argument checking.
You can combine the Pcertify and Convert procedures into a single
procedure, Pcertify+, which may be useful for books that contain
expensive [include-book] [events] but do few proofs. We defer
discussion of that feature to the section below, ``Combining
Pcertify and Convert into Pcertify+''.
The main idea of provisional certification is to break sequential
dependencies caused by [include-book], that is, so that a book's
proofs are carried out even when it includes books (sometimes
called ``sub-books'') that have not themselves been fully
certified. For example, suppose that a proof development consists
of books A.lisp, B.lisp, and C.lisp, where file A.lisp contains the
form (include-book \"B\") and file B.lisp contains the form
(include-book \"C\"). Normally one would first certify C, then B, and
finally, A. However, the provisional certification process can
speed up the process on a multi-core machine, as follows: the
Pcertify (pronounced ``pee certify'') procedure respects this order
but (one hopes) is fast since proofs are skipped; the Convert
procedure essentially completes the certification in parallel by
doing proofs and creating .pcert1 files based on .pcert0 files; and
the Complete procedure respects book order when quickly renaming
.pcert1 files to .cert files. In our example, the steps would be as
follows, but note that we need not finish all Pcertify steps before
starting some Convert steps, nor need we finish all Convert steps
before starting some Complete steps, as explained further below.
* Pcertify books \"C\", \"B\",and then \"A\", sequentially, skipping proofs
but doing compilation.
* Do proofs in parallel for the books using the Convert procedure,
where each book relies on the existence of its own .pcert0 file
as well as a .cert, .pcert0, or .pcert1 file for each of its
included sub-books. Write out a .pcert1 file for the book when
the proof succeeds.
* Rename the .pcert1 file to a corresponding .cert file when a .cert
file exists and is up-to-date for each included book.
The Convert step can begin for bk.lisp any time after bk.pcert0 is
built. The Complete step can begin for this book any time after
bk.pcert1 and every sub-bk.cert are built, for sub-bk a sub-book of
bk.
The new procedures --- Pcertify, Convert, and Complete --- are
invoked by supplying a value for the keyword argument :pcert of
[certify-book], namely :create, :convert, or :complete,
respectively. Typically, and by default, the compile-flg argument
of [certify-book] is t for the Pcertify procedure, so that
[compilation] can take full advantage of parallelism. This argument
is treated as nil for the other procedures except when its value is
:all in the Convert procedure, as mentioned above.
For those who use [make-event], we note that expansion is done in the
Pcertify procedure; the later steps use the expansion resulting
from that procedure. The reason is that although a call of
[make-event] is similar to a macro call, a difference is that the
expansion of a make-event form can depend on the [state].
Therefore, we insist on doing such an expansion only once, so that
all books involved agree on the expansion. We say more about
make-event below.
Correctness Claim and Issues
The Basic Claim for certification is the same whether or not the
provisional certification process is employed: all books should be
certified from scratch, with no files written to the directories of
the books except by ACL2. Moreover, no trust tags should be used
(see [defttag]), or else it is the responsibility of the user to
investigate every occurrence of ``TTAG NOTE'' that is printed to
standard output.
But common practice is to certify a set of books in stages: certify a
few books, fix some books, re-certify changed books, certify some
more books, and so on. In practice, we expect this process to be
sound even though it does not meet the preconditions for the Basic
Claim above. In particular, we expect that the use of checksums in
[certificate]s will make it exceedingly unlikely that a book is
still treated as certified after any events in the book or any
sub-book, or any [portcullis] [command]s of the book or any
sub-book, have been modified.
Provisional certification makes it a bit easier for a determined user
to subvert correctness. For example, the Complete procedure only
checks write dates to ensure that each sub-book's .cert file is no
older than the corresponding .lisp file, but it does not look
inside .cert files of sub-books; in particular it does not look at
their checksum information. Of course, the automatic dependency
analysis provided by classic ACL2 `make'-based certification avoids
accidental problems of this sort. And, checksum information will
indeed be applied at [include-book] time, at least for sub-books
included non-[local]ly.
In short: while we believe that the provisional certification process
can be trusted, we suggest that for maximum trust, it is best for
all books in a project to be certified from scratch without the
provisional certification process.
Combining Pcertify and Convert into Pcertify+
You can combine the Pcertify and Convert procedure into a single
procedure, Pcertify+, which may be useful for books that contain
expensive [include-book] [events] but do few proofs. If you are
using `make' to do provisional certification as described above,
just set `make' variable ACL2_BOOKS_PCERT_ARG_T to the list of
books for which you want the Pcertify+ procedure performed instead
of separate Pcertify and Convert procedures. Either of two common
methods may be used to set this variable, as illustrated below for
the case that books sub.lisp and mid.lisp are the ones on which you
want Pcertify+ performed. One method is to add the following to
your directory's Makefile, above the include of Makefile-generic.
ACL2_BOOKS_PCERT_ARG_T = sub mid
Alternatively, you can specify the desired books on the command line,
for example as follows.
make -j 4 ACL2_BOOKS_PCERT_ARG_T='sub mid'
Note that the books are given without their .lisp extensions.
At the ACL2 level, the Pcertify+ procedure is performed when the
value t is supplied to the :pcert keyword argument of
[certify-book]. Thus, :pcert t can be thought of as a combination
of :pcert :create and :pcert :convert. However, what ACL2 actually
does is to perform the Pcertify step without skipping proofs, and
at the end of the certify-book run, it writes out both the .pcert0
and .pcert1 file, with essentially the same contents. (We say
``essentially'' because the implementation writes :PCERT-INFO
:PROVED to the end of the .pcert0 file, but not to the .pcert1
file.)
Further Information
Some errors during provisional certification cannot be readily
solved. For example, if there are circular directory dependencies
(for example, some book in directory D1 includes some book in
directory D2 and vice-versa), then classic ACL2 `make'-based
certification will quite possibly fail. For another example,
perhaps your directory's Makefile is awkward to convert to one with
suitable dependencies. When no fix is at hand, it might be best
simply to avoid provisional certification. If you are using classic
ACL2 `make'-based certification, you can simply add the following
line to your directory's Makefile, or use ``ACL2_PCERT= '' on the
`make' command line, to avoid provisional certification.
override ACL2_PCERT =
We invite anyone who has troubleshooting tips to contact the ACL2
developers with suggestions for adding such tips to this section.
Our next remark is relevant only to users of [make-event], and
concerns the interaction of that utility with state global
[ld-skip-proofsp]. Normally, the global value of [ld-skip-proofsp]
is unchanged during make-event expansion, except that it is bound
to nil when the make-event form has a non-nil :check-expansion
argument. But during the Pcertify procedure (not the Pcertify+
procedure), [ld-skip-proofsp] is always bound to nil at the start
of make-event expansion. To see why, consider for example the
community book books/make-event/proof-by-arith.lisp. This book
introduces a macro, proof-by-arith, that expands to a call of
[make-event]. This make-event form expands by trying to prove a
given theorem using a succession of included arithmetic books,
until the proof succeeds. Now proofs are skipped during the
Pcertify procedure, and if proofs were also skipped during
make-event expansion within that procedure, the first arithmetic
book's [include-book] form would always be saved because the
theorem's proof ``succeeded'' (as it was skipped!). Of course, the
theorem's proof could then easily fail during the Convert step. If
you really want to inhibit proofs during make-event expansion in
the Pcertify step, consider using a form such as the following:
(state-global-let* ((ld-skip-proofsp nil)) ...).
Finally, we describe what it means for there to be a valid
[certificate] file for including a certified book. Normally, this
is a file with extension .cert. However, if that .cert file does
not exist, then ACL2 looks for a .pcert0 file instead; and if that
also does not exist, it looks for a .pcert1 file. (To see why does
the .pcert0 file take priority over the .pcert1 file, note that the
Convert procedure copies a .pcert0 file to a .pcert1 file, so both
might exist --- but the .pcert1 file might be incomplete if copying
is in progress.) Once the candidate certificate file is thus
selected, it must be valid in order for the book to be considered
certified (see [certificate]). For the certificate file as chosen
above, then in order for a compiled file to be loaded, it must be
at least as recent as that certificate file.
Again, as discussed above, a .pcert0 or .pcert1 file may serve as a
valid certificate file when the .cert file is missing. But when
that happens, a warning may be printed that a ``provisionally
certified'' book has been included. No such warning occurs if
environment variable ACL2_PCERT has a non-empty value, or if that
warning is explicitly inhibited (see [set-inhibit-warnings] and see
[set-inhibit-output-lst]).")
(PSEUDO-TERMP
(TERM ACL2-BUILT-INS)
"A predicate for recognizing term-like s-expressions
Example Forms:
(pseudo-termp '(car (cons x 'nil))) ; has value t
(pseudo-termp '(car x y z)) ; also has value t!
(pseudo-termp '(delta (h x))) ; has value t
(pseudo-termp '(delta (h x) . 7)) ; has value nil (not a true-listp)
(pseudo-termp '((lambda (x) (car x)) b)) ; has value t
(pseudo-termp '(if x y 123)) ; has value nil (123 is not quoted)
(pseudo-termp '(if x y '123)) ; has value t
If x is the quotation of a term, then (pseudo-termp x) is t. However,
if x is not the quotation of a term it is not necessarily the case
that (pseudo-termp x) is nil.
See [term] for a discussion of the various meanings of the word
``term'' in ACL2. In its most strict sense, a term is either a
legal variable symbol, a quoted constant, or the application of an
n-ary function symbol or closed lambda-expression to n terms. By
``legal variable symbol'' we exclude constant symbols, such as t,
nil, and *ts-rational*. By ``quoted constants'' we include 't (aka
(quote t)), 'nil, '31, etc., and exclude constant names such as t,
nil and *ts-rational*, unquoted constants such as 31 or 1/2, and
ill-formed quote expressions such as (quote 3 4). By ``closed
lambda expression'' we exclude expressions, such as (lambda (x)
(cons x y)), containing free variables in their bodies. Terms typed
by the user are translated into strict terms for internal use in
ACL2.
The predicate termp checks this strict sense of ``term'' with respect
to a given ACL2 logical world; See [world]. Many ACL2 functions,
such as the rewriter, require certain of their arguments to satisfy
termp. However, as of this writing, termp is in :[program] mode and
thus cannot be used effectively in conjectures to be proved.
Furthermore, if regarded simply from the perspective of an
effective [guard] for a term-processing function, termp checks many
irrelevant things. (Does it really matter that the variable symbols
encountered never start and end with an asterisk?) For these
reasons, we have introduced the notion of a ``pseudo-term'' and
embodied it in the predicate pseudo-termp, which is easier to
check, does not require the logical [world] as input, has :[logic]
mode, and is often perfectly suitable as a [guard] on
term-processing functions.
A pseudo-termp is either a symbol, a true list of length 2 beginning
with the word quote, the application of an n-ary pseudo-lambda
expression to a true list of n pseudo-terms, or the application of
a symbol to a true list of n pseudo-termps. By an ``n-ary
pseudo-lambda expression'' we mean an expression of the form
(lambda (v1 ... vn) pterm), where the vi are symbols (but not
necessarily distinct legal variable symbols) and pterm is a
pseudo-termp.
Metafunctions may use pseudo-termp as a [guard].")
(PSO
(PROVER-OUTPUT)
"Show the most recently saved output
Evaluate :pso in order to print output that was generated in an
environment where output was being saved; see [set-saved-output]
for details. However, [proof-tree] output will be suppressed; use
:[pso!] if you want that output to be printed as well.
Also see [psog], for printing saved output in [gag-mode].")
(PSO!
(PROVER-OUTPUT)
"Show the most recently saved output, including [proof-tree] output
Evaluate :pso! in order to print output that was generated in an
environment where output was being saved; see [set-saved-output]
for details. Note that [proof-tree] will be included; use :[pso] if
you want that output to be suppressed.
Also see [psog], for printing saved output in [gag-mode].")
(PSOF
(PROVER-OUTPUT)
"Show the most recently saved output
For a similar utility, see [pso]. Like :pso, the :psof command prints
output that was generated in an environment where output was being
saved, typically [gag-mode]; also see [set-saved-output]. But
unlike :pso, :psof takes a filename argument and saves output to
that file, instead of to the terminal. For large proofs, :[psof]
may complete more quickly than :[pso]. Note that as with :pso,
[proof-tree] output will be suppressed.
The first line of output from :psof directs the Emacs editor to use
auto-revert mode. You can change the frequency of auto-reverting
the buffer connected to a file by evaluating a suitable command in
Emacs. For example, the command (setq auto-revert-interval .1)
arranges for auto-revert mode to update as needed every 1/10 of a
second.")
(PSOG
(PROVER-OUTPUT)
"Show the most recently saved output in [gag-mode]
Evaluate :psog in order to print output in [gag-mode] that was
generated in an environment where output was being saved; see
[set-saved-output] for details.
Also see [pso] and see [pso!] for printing the full output.")
(PSTACK
(DEBUGGING)
"Seeing what the prover is up to
General Forms:
(pstack) ; inspect break
(pstack t) ; inspect break, printing all calls in abbreviated form
(pstack :all) ; as above, but only abbreviating the ACL2 world
When the form (pstack) is executed during a break from a proof, or at
the end of a proof that the user has aborted, a ``process stack''
(or ``prover stack'') will be printed that gives some idea of what
the theorem prover has been doing. Moreover, by evaluating
(verbose-pstack t) before starting a proof (see [verbose-pstack])
one can get trace-like information about prover functions,
including time summaries, printed to the screen during a proof.
This feature is currently quite raw and may be refined considerably
as time goes on, based on user suggestions. For example, the usual
control of printing given by [set-inhibit-output-lst] is irrelevant
for printing the pstack.
The use of (pstack t) or (pstack :all) should only be used by those
who are comfortable looking at functions in the ACL2 source code.
Otherwise, simply use (pstack).
Entries in the pstack include the following (listed here
alphabetically, except for the first).
preprocess-clause, simplify-clause, etc. (in general,xxx-clause):
top-level processes in the prover ``waterfall''
clausify: splitting a goal into subgoals
ev-fncall: evaluating a function on explicit arguments
ev-fncall-meta: evaluating a metafunction
forward-chain: building a context for the current goal using
[forward-chaining] rules
induct: finding an induction scheme
pop-clause: getting the next goal to prove by induction
process-assumptions: creating forcing rounds
remove-built-in-clauses: removing built-in clauses (see
[built-in-clause])
process-equational-polys: deducing interesting equations
remove-trivial-equivalences: removing trivial equalities (and
equivalences) from the current goal
rewrite-atm: rewriting a top-level term in the current goal
setup-simplify-clause-pot-lst: building the linear arithmetic
database for the current goal
strip-branches, subsumption-replacement-loop: subroutines of clausify
waterfall: top-level proof control
Subtopics
[Verbose-pstack]
Seeing what the prover is up to (for system hackers)")
(PUFF
(HISTORY)
"Replace a compound [command] by its immediate subevents
Example Forms:
ACL2 !>:puff :max
ACL2 !>:puff :x
ACL2 !>:puff 15
ACL2 !>:puff \"book\"
General Form:
:puff cd
where cd is a [command] descriptor (see [command-descriptor]) for a
``puffable'' [command] (see below). Puff replaces the [command] at
cd by the immediate subevents of the [command], executed as
[command]s. Puff then prints, using [pcs], the puffed region.
We consider puff to be a sort of hack; it is generally robust and
sound, but that is not guaranteed. If any existing ACL2 event
resulted from puff, ACL2 considers proofs to have been skipped, and
thus [certify-book] is disallowed until such events have been
undone (see [ubt]).
A ``puffable'' [command] is an [encapsulate] [command], an
[include-book] command, or any command other than those consisting
of a single primitive event. For example, since [defun] is a
primitive event, a [defun] command is not puffable. But a macro
form that expands into one or more [events] is puffable. The only
primitive events that are puffable are calls of [encapsulate] or
[include-book]. In this sense, [make-event] is not considered
primitive --- that is, it can be puffed --- and moreover, an
immediate subevent that is a call of make-event is generally
replaced by its expansion (see [make-event]). A puffable [command]
contains (interesting) subevents, namely, the events in the body of
the [encapsulate], in the file of the book included, or in the
[command] block.
The puff [command] ``lifts'' the immediate subevents of the indicated
[command] so that they become [command]s themselves. The [command]
[puff*] recursively puffs the newly introduced [command]s. See
[puff*], which also gives an example illustrating both puff and
[puff*]. Puff undoes the [command] at cd and replaces it by its
immediate subevents. Thus, in general the length of the [history]
grows when a puff [command] is executed. If puff causes an error
(see below), the logical [world] remains unchanged from its initial
configuration.
The intended use of puff is to allow the user access to the [events]
``hidden'' inside compound [command]s. For example, while trying to
prove some theorem, p, about a constrained function, fn, one might
find that the [encapsulate], cd, that introduced fn failed to
include an important [constraint], q. Without puff, the only way to
proceed is to undo back through cd, create a suitable [encapsulate]
that proves and exports q as well as the old [constraint]s,
re-execute the new [encapsulate], re-execute the [events] since cd,
and then try p again. Unfortunately, it may be hard to prove q and
additional [events] may have to be inserted into the [encapsulate]
to prove it. It may also be hard to formulate the ``right'' q,
i.e., one that is provable in the [encapsulate] and provides the
appropriate facts for use in the proof of p.
Using puff, the user can erase the [encapsulate] at cd, replacing it
by the [events] in its body. Now the formerly constrained function,
fn, is defined as its witness. The user can experiment with
formulations and proofs of q suitable for p. Of course, to get into
the ultimately desired [state] --- where fn is constrained rather
than defined and q is exported by an [encapsulate] at cd --- the
user must ultimately undo back to cd and carry out the more tedious
program described above. But by using puff it is easier to
experiment.
Similar applications of puff allow the user of a book to expose the
top-level [events] in the book as though they had all been typed as
[command]s. The user might then ``partially undo'' the book,
keeping only some of the events in it.
Puff operates as follows. First, it determines the list of immediate
subevents of the [command] indicated by cd. It causes an error if
there is only one subevent and that subevent is identical to the
[command] --- i.e., if the [command] at cd is a primitive. Next,
puff undoes back through the indicated [command]. This not only
erases the [command] at cd but all the [command]s executed after
it. Finally, puff re-executes the subevents of (the now erased) cd
followed by all the [command]s that were executed afterwards.
Observe that the [command]s executed after cd will generally have
higher [command] numbers than they did before the puff. For
example, suppose 100 [command]s have been executed and that :puff
80 is then executed. Suppose [command] 80 contains 5 immediate
subevents (i.e., is an encapsulation of five [events]). Then, after
puffing, [command] 80 is the first event of the puffed [command],
[command] 81 is the second, and so on; 104 [command]s appear to
have been executed.
When puffing an [encapsulate] or [include-book], the [local]
[command]s are executed. Note that this will replace constrained
functions by their witnesses.
Here are some details and small exceptions.
* An [encapsulate] command generated by the macro
[define-trusted-clause-processor] is not puffable.
* An attempt to puff an [include-book] command may fail for a book that
has been modified, as describe late in this documentation
topic.
* The puff of an an [include-book] command for an uncertified book will
simply expose the contents of the book. However, if the book is
certified then the puff will replace each event by its
[make-event] expansion. Moreover, any such expansion that is
[local] will be ignored; similarly for local make-event
expansions in [encapsulate] commands. This will result in an
error if the elided event is necessary to support later events
in the puff of the command.
Finally, we note that it is an error to puff in the presence of
[include-book] [events] for certified books that have been altered
since they were included. (Note that this restriction only applies
to [include-book], not to [certify-book].) To be specific, suppose
\"arith\" is a certified book that has been included in a session.
Suppose that after \"arith\" was included, the source file is
modified. (This might happen if the user of \"arith\" is not its
author and the author happens to be working on a new version of
\"arith\" during the same time period.) Now suppose the user tries to
puff the [command] that included \"arith\". The attempt to obtain the
subevents in \"arith\" will discover that the check sum of \"arith\"
has changed and an error will be caused. No change is made in the
logical [world]. A similar error is caused if, in this same
situation, the user tries to puff any command that occurred before
the inclusion of \"arith\"! That is, puff may cause an error and
leave the [world] unchanged even if the [command] puffed is not one
involving the modified book. This happens because in order to
reconstruct the [world] after the puffed [command], puff must
obtain the [events] in the book and if the book's source file has
changed there is no assurance that the reconstructed [world] is the
one the user intends.
Warning: We do not detect changes to uncertified [books] that have
been included and are then puffed or re-included! The act of
including an uncertified book leaves no trace of the check sum of
the book. Furthermore, the act prints a warning message disclaiming
soundness. In light of this, :puff quietly ``re-''executes the
current contents of the book.")
(PUFF*
(HISTORY)
"Replace a compound [command] by its subevents
Example Forms:
ACL2 !>:puff* :max
ACL2 !>:puff* :x
ACL2 !>:puff* 15
ACL2 !>(puff* 15) ; same as just above
ACL2 !>(puff* 15 t) ; same as just above, but keep partial results
ACL2 !>:puff* \"book\"
General Forms:
:puff* cd
(puff* 'cd) ; argument can be any expression evaluating to cd
(puff* 'cd b) ; where b is t or nil
where cd is a [command] descriptor (see [command-descriptor]) for a
``puffable'' [command]. See [puff] for the definition of
``puffable'' and for a description of the basic act of ``puffing''
a [command]. In particular, see [puff] for a discussion of a sense
in which puff, and hence puff*, should be viewed as a hack. Puff*
is just the recursive application of [puff]. Puff* prints the
region [puff]ed, using [pcs].
To [puff] a [command] is to replace it by its immediate subevents,
each of which is executed as a [command]. To puff* a [command] is
to replace the [command] by each of its immediate subevents and
then to puff* each of the puffable [command]s among the newly
introduced ones.
For example, suppose \"ab\" is a book containing the following
(in-package \"ACL2\")
(include-book \"a\")
(include-book \"b\")
Suppose that book \"a\" only contained [defun]s for the functions a1
and a2 and that \"b\" only contained [defun]s for b1 and b2.
Now consider an ACL2 [state] in which only two [command]s have been
executed, the first being (include-book \"ab\") and the second being
(include-book \"c\"). Thus, the relevant part of the display produced
by :[pbt] 1 would be:
1 (INCLUDE-BOOK \"ab\")
2 (INCLUDE-BOOK \"c\")
Call this [state] the ``starting [state]'' in this example, because
we will refer to it several times.
Suppose :puff 1 is executed in the starting [state]. Then the first
[command] is replaced by its immediate subevents and :pbt 1 would
show:
1 (INCLUDE-BOOK \"a\")
2 (INCLUDE-BOOK \"b\")
3 (INCLUDE-BOOK \"c\")
Contrast this with the execution of :puff* 1 in the starting [state].
Puff* would first [puff] (include-book \"ab\") to get the [state]
shown above. But then it would recursively puff* the puffable
[command]s introduced by the first [puff]. This continues
recursively as long as any [puff] introduced a puffable [command].
The end result of :puff* 1 in the starting [state] is
1 (DEFUN A1 ...)
2 (DEFUN A2 ...)
3 (DEFUN B1 ...)
4 (DEFUN B2 ...)
5 (INCLUDE-BOOK \"c\")
Observe that when puff* is done, the originally indicated [command],
(include-book \"ab\"), has been replaced by the corresponding
sequence of primitive [events]. Observe also that puffable
[command]s elsewhere in the [history], for example, [command] 2 in
the starting [state], are not affected (except that their [command]
numbers grow as a result of the splicing in of earlier [command]s).
If there is an error during execution of puff*, then the logical
[world] is reverted to its value before that execution, unless the
optional Boolean second argument is t, in which case the result is
preserved from the succesful :puff commands executed before the
erroneous one.")
(PUSH-UNTOUCHABLE
(DEFTTAG)
"Add name or list of names to the list of untouchable symbols
Examples:
(push-untouchable my-var nil)
(push-untouchable set-mem t)
General Form:
(push-untouchable name{s} fn-p)
where name{s} is a non-nil symbol or a non-nil true list of symbols,
and fn-p is any value (but generally nil or t). If name{s} is a
symbol it is treated as the singleton list containing that symbol.
The effect of this event is to union the given symbols into the
list of ``untouchable variables'' in the current world if fn-p is
nil, else to union the symbols into the list of ``untouchable
functions''. This event is redundant if every symbol listed is
already a member of the appropriate untouchables list (variables or
functions).
There is a further restriction on which function names may be made
untouchable: If a function symbol, g, may be introduced into a
proof by a metatheorem (via the metafunction or the hypothesis
metafunction) or by a clause processor and the metatheorem or
clause processor has a :[well-formedness-guarantee] then g may not
be made untouchable.
When a symbol is on the untouchables list it is syntactically illegal
for any event to call a function or macro of that name, if fn-p is
non-nil, or to change the value of a state global variable of that
name, if fn-p is nil. Thus, the effect of pushing a function
symbol, name, onto untouchables is to prevent any future event from
using that symbol as a function or macro, or as a state global
variable (according to fn-p). This is generally done to ``fence
off'' some primitive function symbol from ``users'' after the
developer has used the symbol freely in the development of some
higher level mechanism.
Also see [remove-untouchable].")
(PUT-ASSOC
(ALISTS ACL2-BUILT-INS)
"Modify an association list by associating a value with a key
General Forms:
(put-assoc name val alist)
(put-assoc name val alist :test 'eql) ; same as above (eql as equality test)
(put-assoc name val alist :test 'eq) ; same, but eq is equality test
(put-assoc name val alist :test 'equal) ; same, but equal is equality test
(Put-assoc name val alist) returns an alist that is the same as the
list alist, except that the first pair in alist with a [car] of
name is replaced by (cons name val), if there is one. If there is
no such pair, then (cons name val) is added at the end. Note that
the order of the keys occurring in alist is unchanged (though a new
key may be added).
The [guard] for a call of put-assoc depends on the test. In all
cases, the last argument must satisfy [alistp]. If the test is
[eql], then either the first argument must be suitable for [eql]
(see [eqlablep]) or the last argument must satisfy
[eqlable-alistp]. If the test is [eq], then either the first
argument must be a symbol or the last argument must satisfy
[symbol-alistp].
See [equality-variants] for a discussion of the relation between
put-assoc and its variants:
(put-assoc-eq name val alist) is equivalent to (put-assoc name val
alist :test 'eq);
(put-assoc-equal name val alist) is equivalent to (put-assoc name val
alist :test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function put-assoc-equal.
Function: <put-assoc-equal>
(defun put-assoc-equal (name val alist)
(declare (xargs :guard (alistp alist)))
(cond ((endp alist) (list (cons name val)))
((equal name (caar alist))
(cons (cons name val) (cdr alist)))
(t (cons (car alist)
(put-assoc-equal name val (cdr alist))))))")
(PUT-ASSOC-EQ (POINTERS)
"See [put-assoc].")
(PUT-ASSOC-EQL (POINTERS)
"See [put-assoc].")
(PUT-ASSOC-EQUAL (POINTERS)
"See [put-assoc].")
(PUTPROP
(WORLD ACL2-BUILT-INS)
"Update fast property lists
General form:
(putprop symbol key value world-alist)
See community book books/misc/getprop.lisp for an example that
illustrates the use of ACL2 utilities [getprop] and putprop to take
advantage of under-the-hood Lisp (hashed) property lists.
Function: <putprop>
(defun putprop (symb key value world-alist)
(declare (xargs :guard (and (symbolp symb)
(symbolp key)
(plist-worldp world-alist))))
(cons (cons symb (cons key value))
world-alist))")
(Q
(LP)
"Quit ACL2 (type :q) --- reenter with (lp)
Example:
ACL2 !>:Q
The keyword command :q typed at the top-level of the ACL2 loop will
terminate the loop and return control to the Common Lisp top-level
(or, more precisely, to whatever program invoked [lp]). To reenter
the ACL2 loop, execute (acl2::lp) in Common Lisp. You will be in
the same state as you were when you exited with :q, unless during
your stay in Common Lisp you messed the data structures
representating the ACL2 [state] (including files, property lists,
and single-threaded objects).
Unlike all other keyword commands, typing :q is not equivalent to
invoking the function q. There is no function q.")
(QUANTIFIER-TUTORIAL
(DEFUN-SK)
"A Beginner's Guide to Reasoning about Quantification in ACL2
The initial version of this tutorial was written by Sandip Ray.
Additions and revisions are welcome. Sandip has said:
``This is a collection of notes that I wrote to remind myself of how
to reason about quantifiers when I just started. Most users
after they have gotten the hang of quantifiers probably will
not need this and will be able to use their intuitions to guide
them in the process. But since many ACL2 users are not used to
quantification, I am hoping that this set of notes might help
them to think clearly while reasoning about quantifiers in
ACL2.''
Many ACL2 papers start with the sentence ``ACL2 is a quantifier-free
first-order logic of recursive functions.'' It is true that the
syntax of ACL2 is quantifier-free; every formula is assumed to be
universally quantified over all free variables in the formula. But
the logic in fact does afford arbitrary first-order quantification.
This is obtained in ACL2 using a construct called defun-sk. See
[defun-sk].
Many ACL2 users do not think in terms of [quantifiers]. The focus is
almost always on defining recursive functions and reasoning about
them using induction. That is entirely justified, in fact, since
proving theorems about recursive functions by induction plays to
the strengths of the theorem prover. Nevertheless there are
situations where it is reasonable and often useful to think in
terms of quantifiers. However, reasoning about quantifiers requires
that you get into the mindset of thinking about theorems in terms
of quantification. This note is about how to do this effectively
given ACL2's implementation of quantification. This does not
discuss [defun-sk] in detail, but merely shows some examples. A
detailed explanation of the implementation is in the ACL2
[documentation] (see [defun-sk]); also see
[conservativity-of-defchoose].
[Note: Quantifiers can be used for some pretty cool things in ACL2.
Perhaps the most interesting example is the way of using
quantifiers to introduce arbitrary tail-recursive equations; see
the paper ``Partial Functions in ACL2'' by Panagiotis Manolios and
J Strother Moore. This note does not address applications of
quantifiers, but merely how you would reason about them once you
think you want to use them.]
Assume that you have some function P. I have just left P as a unary
function stub below, since I do not care about what P is.
(defstub P (*) => *)
Now suppose you want to specify the concept that ``there exists some
x such that (P x) holds''. ACL2 allows you to write that directly
using quantifiers.
(defun-sk exists-P () (exists x (P x)))
If you submit the above form in ACL2 you will see that the theorem
prover specifies two functions exists-p and exists-p-witness, and
exports the following constraints:
1. (defun exists-P () (P (exists-P-witness)))
2. (defthm exists-P-suff (implies (p x) (exists-p)))
Here exists-P-witness is a new function symbol in the current ACL2
theory. What do the constraints above say? Notice the constraint
exists-p-suff. It says that if you can provide any x such that (P
x) holds, then you know that exists-p holds. Think of the other
constraint (definition of exists-p) as going the other way. That
is, it says that if exists-p holds, then there is some x, call it
(exists-p-witness), for which P holds. Notice that nothing else is
known about exists-p-witness than the two constraints above.
[Note: exists-p-witness above is actually defined in ACL2 using a
special form called defchoose. See [defchoose]. This note does not
talk about defchoose. So far as this note is concerned, think of
exists-p-witness as a new function symbol that has been generated
somehow in ACL2, about which nothing other than the two facts above
is known.]
Similarly, you can talk about the concept that ``for all x (P x)
holds.'' This can be specified in ACL2 by the form:
(defun-sk forall-P () (forall x (P x)))
This produces the following two constraints:
1. (defun forall-P () (P (forall-p-witness)))
2. (defthm forall-p-necc (implies (not (P x)) (not (forall-p))))
To understand these, think of for-all-p-witness as producing some x
which does not satisfy P, if such a thing exists. The constraint
forall-p-necc merely says that if forall-p holds then P is
satisfied for every x. (To see this more clearly, just think of the
contrapositive of the formula shown.) The other constraint
(definition of forall-p) implies that if forall-p does not hold
then there is some x, call it (forall-p-witness), which does not
satisfy P. To see this, just consider the following formula which
is immediately derivable from the definition.
(implies (not (forall-p)) (not (P (forall-witness))))
The description above suggests that to reason about quantifiers, the
following Rules of Thumb, familiar to most any student of logic,
are useful.
RT1: To prove (exists-p), construct some object A such that P holds
for A and then use exists-P-suff.
RT2: If you assume exists-P in your hypothesis, use the definition of
exists-p to know that P holds for exists-p-witness. To use this
to prove a theorem, you must be able to derive the theorem
based on the hypothesis that P holds for something, whatever
the something is.
RT3: To prove forall-P, prove the theorem (P x) (that is, that P
holds for an arbitrary x), and then simply instantiate the
definition of forall-p, that is, show that P holds for the
witness.
RT4: If you assume forall-p in the hypothesis of the theorem, see how
you can prove your conclusion if indeed you were given (P x) as
a theorem. Possibly for the conclusion to hold, you needed that
P holds for some specific set of x values. Then use the theorem
forall-p-necc by instantiating it for the specific x values you
care about.
Perhaps the above is too terse. In the remainder of the note, we will
consider several examples of how this is done to prove theorems in
ACL2 that involve quantified notions.
Let us consider two trivial theorems. Assume that for some unary
function r, you have proved (r x) as a theorem. Let us see how you
can prove that (1) there exists some x such that (r x) holds, and
(2) for all x (r x) holds.
We first model these things using [defun-sk]. Below, r is simply some
function for which (r x) is a theorem.
(encapsulate
(((r *) => *))
(local (defun r (x) (declare (ignore x)) t))
(defthm r-holds (r x)))
(defun-sk exists-r () (exists x (r x)))
(defun-sk forall-r () (forall x (r x)))
ACL2 does not have too much reasoning support for quantifiers. So in
most cases, one would need :use hints to reason about quantifiers.
In order to apply :use [hints], it is preferable to keep the
function definitions and theorems disabled.
(in-theory (disable exists-r exists-r-suff forall-r forall-r-necc))
Let us now prove that there is some x such that (r x) holds. Since we
want to prove exists-r, we must use exists-r-suff by RT1. We do not
need to construct any instance here since r holds for all x by the
theorem above.
(defthm exists-r-holds
(exists-r)
:hints ((\"Goal\" :use ((:instance exists-r-suff)))))
Let us now prove the theorem that for all x, (r x) holds. By RT3, we
must be able to prove it by definition of forall-r.
(defthm forall-r-holds
(forall-r)
:hints ((\"Goal\" :use ((:instance (:definition forall-r))))))
[Note: Probably no ACL2 user in his or her right mind would prove the
theorems exists-r-holds and forall-r-holds above. The theorems
shown are only for demonstration purposes.]
For the remainder of this note we will assume that we have two
stubbed out unary functions M and N, and we will look at proving
some quantified properties of these functions.
(defstub M (*) => *)
(defstub N (*) => *)
Let us now define the predicates all-M, all-N, ex-M, and ex-N
specifying the various quantifications.
(defun-sk all-M () (forall x (M x)))
(defun-sk all-N () (forall x (N x)))
(defun-sk some-M () (exists x (M x)))
(defun-sk some-N () (exists x (N x)))
(in-theory (disable all-M all-N all-M-necc all-N-necc))
(in-theory (disable some-M some-N some-M-suff some-N-suff))
Let us prove the classic distributive properties of quantification:
the distributivity of universal quantification over conjunction,
and the distributivity of existential quantification over
disjunction. We can state these properties informally in ``pseudo
ACL2'' notation as follows:
1. (exists x: (M x)) or (exists x: (N x)) <=> (exists x: (M x) or (N x))
2. (forall x: (M x)) and (forall: x (N x)) <=> (forall x: (M x) and (N x))
To make these notions formal we of course need to define the formulas
at the right-hand sides of 1 and 2. So we define some-MN and all-MN
to capture these concepts.
(defun-sk some-MN () (exists x (or (M x) (N x))))
(defun-sk all-MN () (forall x (and (M x) (N x))))
(in-theory (disable all-MN all-MN-necc some-MN some-MN-suff))
First consider proving property 1. The formal statement of this
theorem would be: (iff (some-MN) (or (some-M) (some-N))).
How do we prove this theorem? Looking at RT1-RT4 above, note that
they suggest how one should reason about quantification when one
has an ``implication''. But here we have an ``equivalence''. This
suggests another rule of thumb.
RT5: Whenever possible, prove an equivalence involving quantifiers by
proving two implications.
Let us apply RT5 to prove the theorems above. So we will first prove:
(implies (some-MN) (or (some-M) (some-N)))
How can we prove this? This involves assuming a quantified predicate
(some-MN), so we must use RT2 and apply the definition of some-MN.
Since the conclusion involves a disjunction of two quantified
predicates, by RT1 we must be able to construct two objects A and B
such that either M holds for A or N holds for B, so that we can
then invoke some-M-suff and some-N-suff to prove the conclusion.
But now notice that if some-MN is true, then there is already an
object, in fact some-MN-witness, such that either M holds for it,
or N holds for it. And we know this is the case from the definition
of some-MN! So we will simply prove the theorem instantiating
some-M-suff and some-N-suff with this witness. The conclusion is
that the following event will go through with ACL2.
(defthm le1
(implies (some-MN)
(or (some-M) (some-N)))
:rule-classes nil
:hints ((\"Goal\"
:use ((:instance (:definition some-MN))
(:instance some-M-suff
(x (some-MN-witness)))
(:instance some-N-suff
(x (some-MN-witness)))))))
This also suggests the following rule of thumb:
RT6: If a conjecture involves assuming an existentially quantified
predicate in the hypothesis from which you are trying to prove
an existentially quantified predicate, use the witness of the
existential quantification in the hypothesis to construct the
witness for the existential quantification in the conclusion.
Let us now try to prove the converse of le1, that is: (implies (or
(some-M) (some-N)) (some-MN))
Since the hypothesis is a disjunction, we will just prove each case
individually instead of proving the theorem by a :cases hint. So we
prove the following two lemmas.
(defthm le2
(implies (some-M) (some-MN))
:rule-classes nil
:hints ((\"Goal\"
:use ((:instance (:definition some-M))
(:instance some-MN-suff
(x (some-M-witness)))))))
(defthm le3
(implies (some-N) (some-MN))
:rule-classes nil
:hints ((\"Goal\"
:use ((:instance (:definition some-N))
(:instance some-MN-suff
(x (some-N-witness)))))))
Note that the hints above are simply applications of RT6 as in le1.
With these lemmas, of course the main theorem is trivial.
(defthmd |some disjunction|
(iff (some-MN) (or (some-M) (some-N)))
:hints ((\"Goal\"
:use ((:instance le1)
(:instance le2)
(:instance le3)))))
Let us now prove the distributivity of universal quantification over
conjunction, that is, the formula: (iff (all-MN) (and (all-M)
(all-N)))
Applying RT5, we will again decompose this into two implications. So
consider first the one-way implication: (implies (and (all-M)
(all-N)) (all-MN)).
Here we get to assume all-M and all-N. Thus by RT4 we can use
all-M-necc and all-N-necc to think as if we are given the formulas
(M x) and (N x) as theorems. The conclusion here is also a
universal quantification, namely we have to prove all-MN. Then RT3
tells us to proceed as follows. Take any object y. Try to find an
instantiation z of the hypothesis that implies (and (M y) (N y)).
Then instantiate y with all-MN-witness. Note that the hypothesis
lets us assume (M x) and (N x) to be theorems. Thus to justify we
need to instantiate x with y, and in this case, therefore, with
all-MN-witness. To make the long story short, the following event
goes through with ACL2:
(defthm lf1
(implies (and (all-M) (all-N))
(all-MN))
:rule-classes nil
:hints ((\"Goal\"
:use ((:instance (:definition all-MN))
(:instance all-M-necc (x (all-MN-witness)))
(:instance all-N-necc (x (all-MN-witness)))))))
This suggests the following rule of thumb which is a dual of RT6:
RT7: If a conjecture assumes some universally quantified predicate in
the hypothesis and its conclusion asserts a universallly
quantified predicate, then instantiate the ``necessary
condition'' (forall-mn-necc) of the hypothesis with the witness
of the conclusion to prove the conjecture.
Applying RT7 now we can easily prove the other theorems that we need
to show that universal quantification distributes over conjunction.
Let us just go through this motion in ACL2.
(defthm lf2
(implies (all-MN)
(all-M))
:rule-classes nil
:hints ((\"Goal\"
:use ((:instance (:definition all-M))
(:instance all-MN-necc
(x (all-M-witness)))))))
(defthm lf3
(implies (all-MN)
(all-N))
:rule-classes nil
:hints ((\"Goal\"
:use ((:instance (:definition all-N))
(:instance all-MN-necc
(x (all-N-witness)))))))
(defthmd |all conjunction|
(iff (all-MN)
(and (all-M) (all-N)))
:hints ((\"Goal\" :use ((:instance lf1)
(:instance lf2)
(:instance lf3)))))
The rules of thumb for universal and existential quantification
should make you realize the duality of their use. Every reasoning
method about universal quantification can be cast as a way of
reasoning about existential quantification, and vice versa. Whether
you reason using universal and existential quantifiers depends on
what is natural in a particular context. But just for the sake of
completeness let us prove the duality of universal and existential
quantifiers. So what we want to prove is the following:
3. (forall x (not (M x))) = (not (exists x (M x)))
We first formalize the notion of (forall x (not (M x))) as a
quantification.
(defun-sk none-M () (forall x (not (M x))))
(in-theory (disable none-M none-M-necc))
So we now want to prove: (equal (none-M) (not (some-M))).
As before, we should prove this as a pair of implications. So let us
prove first: (implies (none-M) (not (some-M))).
This may seem to assert an existential quantification in the
conclusion, but rather, it asserts the negation of an existential
quantification. We are now trying to prove that something does not
exist. How do we do that? We can show that nothing satisfies M by
just showing that (some-M-witness) does not satisfy M. This
suggests the following rule of thumb:
RT8: When you encounter the negation of an existential quantification
think in terms of a universal quantification, and vice-versa.
Ok, so now applying RT8 and RT3 you should be trying to apply the
definition of some-M. The hypothesis is just a pure (non-negated)
universal quantification so you should apply RT4. A blind
application lets us prove the theorem as below.
(defthm nl1
(implies (none-M) (not (some-M)))
:rule-classes nil
:hints ((\"Goal\"
:use ((:instance (:definition some-M))
(:instance none-M-necc (x (some-M-witness)))))))
How about the converse implication? I have deliberately written it as
(implies (not (none-M)) (some-M)) instead of switching the
left-hand and right-hand sides of nl1, which would have been
equivalent. Again, RH8 tells us how to reason about it, in this
case using RH2, and we succeed.
(defthm nl2
(implies (not (none-M)) (some-M))
:rule-classes nil
:hints ((\"Goal\"
:use ((:instance (:definition none-M))
(:instance some-M-suff (x (none-M-witness)))))))
So finally we just go through the motions of proving the equality.
(defthmd |forall not = not exists|
(equal (none-M) (not (some-M)))
:hints ((\"Goal\"
:use ((:instance nl1)
(:instance nl2)))))
Let us now see if we can prove a slightly more advanced theorem which
can be stated informally as: If there is a natural number x which
satisfies M, then there is a least natural number y that satisfies
M.
[Note: Any time I have had to reason about existential quantification
I have had to do this particular style of reasoning and state that
if there is an object satisfying a predicate, then there is also a
``minimal'' object satisfying the predicate.]
Let us formalize this concept. We first define the concept of
existence of a natural number satisfying x.
(defun-sk some-nat-M () (exists x (and (natp x) (M x))))
(in-theory (disable some-nat-M some-nat-M-suff))
We now talk about what it means to say that x is the least number
satisfying M.
(defun-sk none-below (y)
(forall r (implies (and (natp r) (< r y)) (not (M r))))))
(in-theory (disable none-below none-below-necc))
(defun-sk min-M () (exists y (and (M y) (natp y) (none-below y))))
(in-theory (disable min-M min-M-suff))
The predicate none-below says that no natural number less than y
satisfies M. The predicate min-M says that there is some natural
number y satisfying M such that none-below holds for y.
So the formula we want to prove is: (implies (some-nat-M) (min-M)).
Since the formula requires that we prove an existential
quantification, RT1 tells us to construct some object satisfying
the predicate over which we are quantifying. We should then be able
to instantiate min-M-suff with this object. That predicate says
that the object must be the least natural number that satisfies M.
Since such an object is uniquely computable if we know that there
exists some natural number satisfying M, let us just write a
recursive function to compute it. This function is least-M below.
(defun least-M-aux (i bound)
(declare (xargs :measure (nfix (- (1+ bound) i))))
(cond ((or (not (natp i))
(not (natp bound))
(> i bound))
0)
((M i) i)
(t (least-M-aux (+ i 1) bound))))
(defun least-M (bound) (least-M-aux 0 bound))
Let us now reason about this function as one does typically. So we
prove that this object is indeed the least natural number that
satisfies M, assuming that bound is a natural number that satisfies
M.
(defthm least-aux-produces-an-M
(implies (and (natp i)
(natp bound)
(<= i bound)
(M bound))
(M (least-M-aux i bound))))
(defthm least-<=bound
(implies (<= 0 bound)
(<= (least-M-aux i bound) bound)))
(defthm least-aux-produces-least
(implies (and (natp i)
(natp j)
(natp bound)
(<= i j)
(<= j bound)
(M j))
(<= (least-M-aux i bound) j)))
(defthm least-aux-produces-natp
(natp (least-M-aux i bound)))
(defthmd least-is-minimal-satisfying-m
(implies (and (natp bound)
(natp i)
(< i (least-M bound)))
(not (M i)))
:hints ((\"Goal\"
:in-theory (disable least-aux-produces-least least-<=bound)
:use ((:instance least-<=bound
(i 0))
(:instance least-aux-produces-least
(i 0)
(j i))))))
(defthm least-has-m
(implies (and (natp bound)
(m bound))
(M (least-M bound))))
(defthm least-is-natp
(natp (least-M bound)))
So we have done that, and hopefully this is all that we need about
least-M. So we disable everything.
(in-theory (disable least-M natp))
Now of course we note that the statement of the conjecture we are
interested in has two quantifiers, an inner forall (from
none-below) and an outer exists (from min-M). Since ACL2 is not
very good with quantification, we hold its hands to reason with the
quantifier part. So we will first prove something about the forall
and then use it to prove what we need about the exists.
RT9: When you face nested quantifiers, reason about each nesting
separately.
So what do we want to prove about the inner quantifier? Looking
carefully at the definition of none-below we see that it is saying
that for all natural numbers r < y, (M r) does not hold. Well, how
would we want to use this fact when we want to prove our final
theorem? We expect that we will instantiate min-M-suff with the
object (least-M bound) where we know (via the outermost existential
quantifier) that M holds for bound, and we will then want to show
that none-below holds for (least-M bound). So let us prove that for
any natural number (call it bound), none-below holds for (least-M
bound). For the final theorem we only need it for natural numbers
satisfying M, but note that from the lemma
least-is-minimal-satisfying-m we really do not need that bound
satisfies M.
So we are now proving: (implies (natp bound) (none-below (least-M
bound))).
Well since this is a standard case of proving a universally
quantified predicate, we just apply RT3. We have proved that for
all naturals i < (least-M bound), i does not satisfy M (lemma
least-is-minimal-satisfying-M), so we merely need the instantiation
of that lemma with none-below-witness of the thing we are trying to
prove, that is, (least-M bound). The theorem below thus goes
through.
(defthm least-is-minimal
(implies (natp bound)
(none-below (least-M bound)))
:hints ((\"Goal\"
:use ((:instance (:definition none-below)
(y (least-M bound)))
(:instance least-is-minimal-satisfying-m
(i (none-below-witness (least-M bound))))))))
Finally we are in the outermost existential quantifier, and are in
the process of applying min-M-suff. What object should we
instantiate it with? We must instantiate it with (least-M bound)
where bound is an object which must satisfy M and is a natural. We
have such an object, namely (some-nat-M-witness) which we know have
all these qualities given the hypothesis. So the proof now is just
RT1 and RT2.
(defthm |minimal exists|
(implies (some-nat-M) (min-M))
:hints ((\"Goal\"
:use ((:instance min-M-suff
(y (least-M (some-nat-M-witness))))
(:instance (:definition some-nat-M))))))
If you are comfortable with the reasoning above, then you are
comfortable with quantifiers and probably will not need these notes
any more. In my opinion, the best way of dealing with ACL2 is to
ask yourself why you think something is a theorem, and the rules of
thumb above are simply guides to the questions that you need to ask
when you are dealing with quantification.
Here are a couple of simple exercises for you to test if you
understand the reasoning process.
Exercise 1. Formalize and prove the following theorem. Suppose there
exists x such that (R x) and suppose that all x satisfy (P x). Then
prove that there exists x such that (P x) & (R x). (See
{http://www.cs.utexas.edu/users/moore/acl2/contrib/quantifier-exercise-1-solution.html
|
http://www.cs.utexas.edu/users/moore/acl2/contrib/quantifier-exercise-1-solution.html}
for a solution.)
Exercise 2. Recall the example just before the preceding exercise,
where we showed that if there exists a natural number x satisfying
M then there is another natural number y such that y satisfies M
and for every natural number z < y, z does not. What would happen
if we remove the restriction of x, y, and z being naturals? Of
course, we will not talk about < any more, but suppose you use a
total order on all ACL2 objects such as [<<]. More concretely,
consider the definition of some-M above. Let us now define two
other functions:
(include-book \"misc/total-order\" :dir :system)
(defun-sk none-below-2 (y)
(forall r (implies (<< r y) (not (M r)))))
(defun-sk min-M2 () (exists y (and (M y) (none-below-2 y))))
The question is whether (implies (some-M) (min-M2)) is a theorem. Can
you prove it? Can you disprove it?")
(QUANTIFIERS
(DEFUN-SK)
"Issues about quantification in ACL2
ACL2 supports first-order quantifiers [exists] and [forall] by way of
the [defun-sk] event. However, proof support for quantification is
quite limited. Therefore, you may prefer using recursion in place
of defun-sk when possible (following common ACL2 practice).
For example, the notion ``every member of x has property p'' can be
defined either with recursion or explicit quantification, but
proofs may be simpler when recursion is used. We illustrate this
point with two proofs of the same informal claim, one of which uses
recursion which the other uses explicit quantification. Notice that
with recursion, the proof goes through fully automatically; but
this is far from true with explicit quantification (especially
notable is the ugly hint).
The informal claim for our examples is: If every member a of each of
two lists satisfies the predicate (p a), then this holds of their
[append]; and, conversely.
See [quantifiers-using-recursion] for a solution to this example
using recursion.
See [quantifiers-using-defun-sk] for a solution to this example using
[defun-sk]. Also See [quantifiers-using-defun-sk-extended] for an
elaboration on that solution.
But perhaps first, see [defun-sk] for an ACL2 utility to introduce
first-order quantification in a direct way. Examples of the use of
defun-sk are also available: see [defun-sk-example] and see
[Tutorial4-Defun-Sk-Example] for basic examples, and see
[quantifier-tutorial] for a more complete, careful beginner's
introduction that takes you through typical kinds of
quantifier-based reasoning in ACL2.
Subtopics
[Quantifiers-using-defun-sk]
Quantification example
[Quantifiers-using-defun-sk-extended]
Quantification example with details
[Quantifiers-using-recursion]
Recursion for implementing quantification")
(QUANTIFIERS-USING-DEFUN-SK
(QUANTIFIERS)
"Quantification example
See [quantifiers] for the context of this example. It should be
compared to a corresponding example in which a simpler proof is
attained by using recursion in place of explicit quantification;
see [quantifiers-using-recursion].
(in-package \"ACL2\")
; We prove that if every member A of each of two lists satisfies the
; predicate (P A), then this holds of their append; and, conversely.
; Here is a solution using explicit quantification.
(defstub p (x) t)
(defun-sk forall-p (x)
(forall a (implies (member a x)
(p a))))
(defthm member-append
(iff (member a (append x1 x2))
(or (member a x1) (member a x2))))
(defthm forall-p-append
(equal (forall-p (append x1 x2))
(and (forall-p x1) (forall-p x2)))
:hints ((\"Goal\" ; ``should'' disable forall-p-necc, but no need
:use
((:instance forall-p-necc
(x (append x1 x2))
(a (forall-p-witness x1)))
(:instance forall-p-necc
(x (append x1 x2))
(a (forall-p-witness x2)))
(:instance forall-p-necc
(x x1)
(a (forall-p-witness (append x1 x2))))
(:instance forall-p-necc
(x x2)
(a (forall-p-witness (append x1 x2))))))))
Also see [quantifiers-using-defun-sk-extended] for an elaboration on
this example.")
(QUANTIFIERS-USING-DEFUN-SK-EXTENDED
(QUANTIFIERS)
"Quantification example with details
See [quantifiers-using-defun-sk] for the context of this example.
(in-package \"ACL2\")
; We prove that if every member A of each of two lists satisfies the
; predicate (P A), then this holds of their append; and, conversely.
; Here is a solution using explicit quantification.
(defstub p (x) t)
(defun-sk forall-p (x)
(forall a (implies (member a x)
(p a))))
; The defun-sk above introduces the following axioms. The idea is that
; (FORALL-P-WITNESS X) picks a counterexample to (forall-p x) if there is one.
; (DEFUN FORALL-P (X)
; (LET ((A (FORALL-P-WITNESS X)))
; (IMPLIES (MEMBER A X) (P A))))
;
; (DEFTHM FORALL-P-NECC
; (IMPLIES (NOT (IMPLIES (MEMBER A X) (P A)))
; (NOT (FORALL-P X)))
; :HINTS ((\"Goal\" :USE FORALL-P-WITNESS)))
; The following lemma seems critical.
(defthm member-append
(iff (member a (append x1 x2))
(or (member a x1) (member a x2))))
; The proof of forall-p-append seems to go out to lunch, so we break into
; directions as shown below.
(defthm forall-p-append-forward
(implies (forall-p (append x1 x2))
(and (forall-p x1) (forall-p x2)))
:hints ((\"Goal\" ; ``should'' disable forall-p-necc, but no need
:use
((:instance forall-p-necc
(x (append x1 x2))
(a (forall-p-witness x1)))
(:instance forall-p-necc
(x (append x1 x2))
(a (forall-p-witness x2)))))))
(defthm forall-p-append-reverse
(implies (and (forall-p x1) (forall-p x2))
(forall-p (append x1 x2)))
:hints ((\"Goal\"
:use
((:instance forall-p-necc
(x x1)
(a (forall-p-witness (append x1 x2))))
(:instance forall-p-necc
(x x2)
(a (forall-p-witness (append x1 x2))))))))
(defthm forall-p-append
(equal (forall-p (append x1 x2))
(and (forall-p x1) (forall-p x2)))
:hints ((\"Goal\" :use (forall-p-append-forward
forall-p-append-reverse))))")
(QUANTIFIERS-USING-RECURSION
(QUANTIFIERS)
"Recursion for implementing quantification
The following example illustrates the use of recursion as a means of
avoiding proof difficulties that can arise from the use of explicit
quantification (via [defun-sk]). See [quantifiers] for more about
the context of this example.
(in-package \"ACL2\")
; We prove that if every member A of each of two lists satisfies the
; predicate (P A), then this holds of their append; and, conversely.
; Here is a solution using recursively-defined functions.
(defstub p (x) t)
(defun all-p (x)
(if (atom x)
t
(and (p (car x))
(all-p (cdr x)))))
(defthm all-p-append
(equal (all-p (append x1 x2))
(and (all-p x1) (all-p x2))))")
(QUICK-AND-DIRTY-SUBSUMPTION-REPLACEMENT-STEP
(DEBUGGING)
"(advanced topic) controlling a heuristic in the prover's clausifier
This topic is probably only of interest to those who are undertaking
particularly complex proof developments.
The ACL2 prover's handling of propositional logic uses a heuristic
that we believe might cause the prover to slow down significantly
or even to trigger a stack overflow. However, we believe these
negative effects are only felt on very large formulas --- formulas
that are likely to cause similar degradation of many other parts of
ACL2.
The following two events turn off that heuristic (by eliminating
calls to source function
quick-and-dirty-subsumption-replacement-step, after which this
[documentation] topic is named).
(defun quick-and-dirty-srs-off (cl1 ac)
(declare (ignore cl1 ac)
(xargs :mode :logic :guard t))
nil)
(defattach quick-and-dirty-srs quick-and-dirty-srs-off)
However, if you feel the need to try this out, please remember that
the proof is likely to fail anyway since other parts of ACL2 will
probably be stressed. A more basic problem with your proof strategy
may exist: the formulas are getting extraordinarily large. A common
approach for avoiding such problem include disabling functions (see
[in-theory]). Other less common approaches might help if you are
sufficiently desperate, such as defining your own IF function to
use in place of the built-in IF.
If you do find an example for which the above two events provide
significant benefit, we (the ACL2 implementors) would be interested
in hearing about it.
To turn the heuristic back on:
(defattach quick-and-dirty-srs quick-and-dirty-srs-builtin)")
(QUIT (GOOD-BYE)
"Quit entirely out of Lisp
Same as [good-bye].")
(QUOTE
(BASICS ACL2-BUILT-INS)
"Create a constant
The form (quote x) evaluates to x. See any Common Lisp documentation.
Also see [unquote].
Subtopics
[Unquote]
Obtain the object being quoted")
(R-EQLABLE-ALISTP
(ALISTS ACL2-BUILT-INS)
"Recognizer for a true list of pairs whose [cdr]s are suitable for
[eql]
The predicate r-eqlable-alistp tests whether its argument is a
[true-listp] of [consp] objects whose [cdr]s all satisfy
[eqlablep].
Function: <r-eqlable-alistp>
(defun r-eqlable-alistp (x)
(declare (xargs :guard t))
(cond ((atom x) (equal x nil))
(t (and (consp (car x))
(eqlablep (cdr (car x)))
(r-eqlable-alistp (cdr x))))))")
(R-SYMBOL-ALISTP
(ALISTS ACL2-BUILT-INS)
"Recognizer for association lists with symbols as values
(R-symbol-alistp x) is true if and only if x is a list of pairs of
the form (cons key val) where val is a [symbolp].
Function: <r-symbol-alistp>
(defun r-symbol-alistp (x)
(declare (xargs :guard t))
(cond ((atom x) (equal x nil))
(t (and (consp (car x))
(symbolp (cdr (car x)))
(r-symbol-alistp (cdr x))))))")
(RANDOM$
(STATE NUMBERS ACL2-BUILT-INS)
"Obtain a random value
Example:
(random$ 10 state) ==> (mv 7 <state>)
(Random$ limit state), where limit is a positive integer, returns a
random non-negative integer together with a new [state]. Logically,
it simply returns the first element of a list that is a field of
the ACL2 [state], called the acl2-oracle (see [read-ACL2-oracle]),
together with the new state resulting from removing that element
from that list. (Except, if that element is not in range as
specified above, then 0 is returned.) However, random$ actually
invokes a Common Lisp function to choose the integer returned.
Quoting from the Common Lisp HyperSpec(TM),
{http://www.lispworks.com/documentation/HyperSpec/Front |
http://www.lispworks.com/documentation/HyperSpec/Front}: ``An
approximately uniform choice distribution is used... each of the
possible results occurs with (approximate) probability 1/limit.''
Consider enabling rules natp-random$ and random$-linear if you want
to reason about random$.
Function: <random$>
(defun random$ (limit state)
(declare (type (integer 1 *) limit)
(xargs :stobjs state))
(mv-let (erp val state)
(read-acl2-oracle state)
(mv (cond ((and (null erp)
(natp val)
(< val limit))
val)
(t 0))
state)))")
(RASSOC
(ALISTS ACL2-BUILT-INS)
"Look up value in association list
General Forms:
(rassoc x alist)
(rassoc x alist :test 'eql) ; same as above (eql as equality test)
(rassoc x alist :test 'eq) ; same, but eq is equality test
(rassoc x alist :test 'equal) ; same, but equal is equality test
(Rassoc x alist) is the first member of alist whose [cdr] is x, or
nil if no such member exists. (rassoc x alist) is thus similar to
(assoc x alist), the difference being that it looks for the first
pair in the given alist whose [cdr], rather than [car], is [eql] to
x. See [assoc]. The optional keyword, :TEST, has no effect
logically, but provides the test (default [eql]) used for comparing
x with the [cdr]s of successive elements of lst.
The [guard] for a call of rassoc depends on the test. In all cases,
the second argument must satisfy [alistp]. If the test is [eql],
then either the first argument must be suitable for [eql] (see
[eqlablep]) or the second argument must satisfy [r-eqlable-alistp].
If the test is [eq], then either the first argument must be a
symbol or the second argument must satisfy [r-symbol-alistp].
See [equality-variants] for a discussion of the relation between
rassoc and its variants:
(rassoc-eq x lst) is equivalent to (rassoc x lst :test 'eq);
(rassoc-equal x lst) is equivalent to (rassoc x lst :test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function rassoc-equal.
Function: <rassoc-equal>
(defun rassoc-equal (x alist)
(declare (xargs :guard (alistp alist)))
(cond ((endp alist) nil)
((equal x (cdr (car alist)))
(car alist))
(t (rassoc-equal x (cdr alist)))))
Rassoc is defined by Common Lisp. See any Common Lisp documentation
for more information.")
(RASSOC-EQ (POINTERS) "See [rassoc].")
(RASSOC-EQUAL (POINTERS)
"See [rassoc].")
(RATIONAL-LISTP
(NUMBERS LISTS ACL2-BUILT-INS)
"Recognizer for a true list of rational numbers
The predicate rational-listp tests whether its argument is a true
list of rational numbers.
Function: <rational-listp>
(defun rational-listp (l)
(declare (xargs :guard t))
(cond ((atom l) (eq l nil))
(t (and (rationalp (car l))
(rational-listp (cdr l))))))")
(RATIONALP
(NUMBERS ACL2-BUILT-INS)
"Recognizer for rational numbers (ratios and integers)
(rationalp x) is true if and only if x is an rational number.")
(READ-ACL2-ORACLE
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Pop the oracle field of the state
ACL2 has a mutable `state' that contains a number of fields; see
[state]. One of these fields is a list, called the acl2-oracle
field. There are no constraints on the elements of this list; thus,
you will not be able to prove anything about those elements.
However, as a convenience, ACL2 permits you to evaluate the form
(read-acl2-oracle state), which returns the multiple value (mv nil
nil state).
The ACL2 implementation uses read-acl2-oracle, but you will likely
find this function to be useless unless you do advanced, scurrilous
things using trust tags (see [defttag]).
The following definition is the logical definition of
read-acl2-oracle, but as explained above does not really
characterize its behavior under the hood.
Function: <read-acl2-oracle>
(defun read-acl2-oracle (state-state)
(declare (xargs :guard (state-p1 state-state)))
(mv (null (acl2-oracle state-state))
(car (acl2-oracle state-state))
(update-acl2-oracle (cdr (acl2-oracle state-state))
state-state)))")
(READ-BYTE$ (POINTERS) "See [io].")
(READ-CHAR$ (POINTERS) "See [io].")
(READ-FILE-INTO-STRING
(IO)
"The contents of a file as a string
When this function is passed a valid filename (and the ACL2 [state]),
it generally returns the contents of the file as a string.
Otherwise, it returns nil.
Example Form:
(read-file-into-string \"foo.lisp\" state)
General Form:
(read-file-into-string filename state)
where filename is a string, which is typically the name of a file.
This function provides functionality that can be obtained through the
usual [io] routines provided by ACL2, as shown by the sequence of
definitions below. However, under-the-hood raw Lisp code provides
an implementation that not only is efficient, but also does not
return [state]. Note that the use of [with-local-state] in the
definition of subroutine read-file-into-string2 does not require a
trust tag (see [defttag]) because that function is defined by ACL2,
not in a book.
A minor detail is that the constant *read-file-into-string-bound*
(see the definition below) is a strict upper bound on the size of a
file for which a non-nil result may be returned. However, a given
implementation might return nil for smaller file sizes as well.
There are two checks to guarantee that read-file-into-string is truly
a function --- that is, it returns the same value for two calls
with the same inputs. One check ensures that the write date of the
file has not changed between two such calls; otherwise ACL2 will
cause a raw Lisp error of the following form.
************ ABORTING from raw Lisp ***********
Error: Illegal consecutive reads from file \"MY-FILE\".
See :DOC read-file-into-string.
***********************************************
The other check ensures that the write date of the file has not
changed while the second call is in progress. For simplicity, ACL2
actually makes this check even for the first call. When the check
fails the corresponding raw Lisp error is of the following form.
************ ABORTING from raw Lisp ***********
Error: Illegal attempt to call READ-FILE-INTO-STRING concurrently with some write to that file!
See :DOC read-file-into-string.
***********************************************
The first of these errors can actually occur when the second read is
performed by [open-input-channel] of type :character. But we expect
all such errors to be rare, since they only occur when there are
two reads to the same file with an intervening external write, in
the case that the two ACL2 states have the same file-clock field
(see [state]). That field is updated any time a channel is opened
or closed.
We close by showing the relevant ACL2 definitions, not including the
special raw Lisp (under the hood) code in the definition of
read-file-into-string2.
Function: <read-file-into-string1>
(defun
read-file-into-string1
(channel state ans bound)
(declare (xargs :stobjs state
:guard (and (symbolp channel)
(open-input-channel-p channel
:character state)
(character-listp ans)
(natp bound))))
(cond
((zp bound) (mv nil state))
(t
(mv-let
(val state)
(read-char$ channel state)
(cond ((not (characterp val))
(mv (coerce (reverse ans) 'string)
state))
(t (read-file-into-string1 channel state (cons val ans)
(1- bound))))))))
Definition: <*read-file-into-string-bound*>
(defconst *read-file-into-string-bound*
(1- (ash 1 60)))
Function: <read-file-into-string2>
(defun
read-file-into-string2 (filename state)
(declare (xargs :stobjs state
:guard (stringp filename)))
(let*
((st (coerce-state-to-object state)))
(mv-let
(erp val)
(with-local-state
(mv-let
(erp val state)
(let
((state (coerce-object-to-state st)))
(mv-let
(chan state)
(open-input-channel filename
:character state)
(cond
((or (null chan) (not (state-p state)))
(mv nil nil state))
(t
(pprogn
(f-put-global 'guard-checking-on
t state)
(mv-let (val state)
(ec-call (read-file-into-string1
chan state
nil *read-file-into-string-bound*))
(pprogn (ec-call (close-input-channel chan state))
(mv nil val state))))))))
(mv erp val)))
(declare (ignore erp))
val)))
Function: <read-file-into-string>
(defun read-file-into-string (filename state)
(declare (xargs :stobjs state
:guard (stringp filename)))
(and (mbt (stringp filename))
(read-file-into-string2 filename state)))")
(READ-OBJECT (POINTERS) "See [io].")
(READ-RUN-TIME
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Read elapsed runtime
By default, (read-run-time state) returns (mv runtime state), where
runtime is the elapsed runtime in seconds since the start of the
current ACL2 session and state is the resulting ACL2 [state]. But
read-run-time can be made to return elapsed realtime (wall clock
time) instead; see [get-internal-time].
The logical definition probably won't concern many users, but for
completeness, we say a word about it here. That definition uses the
function [read-ACL2-oracle], which modifies state by popping the
value to return from its acl2-oracle field.
Function: <read-run-time>
(defun
read-run-time (state-state)
(declare (xargs :guard (state-p1 state-state)))
(mv (cond ((or (null (acl2-oracle state-state))
(not (rationalp (car (acl2-oracle state-state)))))
0)
(t (car (acl2-oracle state-state))))
(update-acl2-oracle (cdr (acl2-oracle state-state))
state-state)))")
(READER
(MISCELLANEOUS)
"Reading expressions in the ACL2 read-eval-print loop
The ACL2 read-eval-print loop reads expressions much like they are
read in any Common Lisp read-eval-print loop. For example, you may
use the single tick symbol (') for quote and also the backquote
symbol (`) with its escapes, comma (,) and comma-atsign (,@). See
any Common Lisp reference or tutorial.
ACL2-specific reader macros include its reading of expressions in a
specified package (using #! --- see [sharp-bang-reader]), its
restriction of read-time evaluation to constants introduced by
[defconst] (using #. --- see [sharp-dot-reader]), and the ability
to put underscores in numeric constants (using #u --- see
[sharp-u-reader]).
See [set-iprint] for how to make ACL2 print expressions like #@2#
that can be read back in.
Strictly speaking, there is nothing special about how the reader
handles [keyword]s in the input. But see [keyword-commands] for how
ACL2 may interpret a top-level keyword command.
We conclude this topic with a log that illustrates features discussed
above. Comments of the form {{..}} have been inserted manually.
ACL2 !>(defconst *c* (+ 3 4))
Summary
Form: ( DEFCONST *C* ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
*C*
ACL2 !>'(a #.*c* 17)
;{{See :doc sharp-dot-reader.
; Notice that #.*c* is read as the value of *c*, thus,
; as 7 rather than as (+ 3 4).}}
(A 7 17)
ACL2 !>'(a #.(+ 5 6) 17)
;{{But this is not legal in ACL2, as #. must be followed by
; a known constant symbol.}}
***********************************************
************ ABORTING from raw Lisp ***********
Error: ACL2 supports #. syntax only for #.*a*, where *a* has been
defined by DEFCONST. Thus the form #.(+ 5 6) is illegal.
***********************************************
;{{Additional output here has been omitted in this log.}}
ACL2 !>(defpkg \"FOO\" nil)
Summary
Form: ( DEFPKG \"FOO\" ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
\"FOO\"
ACL2 !>#!foo'(a b c)
;{{See :doc sharp-bang-reader. The prefix \"#!foo\" causes
; the s-expression after it to be read into the \"FOO\" package.}}
(FOO::A FOO::B FOO::C)
ACL2 !>#x100a
;{{As in Common Lisp, \"#x\" causes the digits after it to be read in hex.}}
4106
ACL2 !>#ux10_0a
;{{The \"#u\" prefix allows underscores in the numeral after it. Those
; underscores are ignored, but can improve readability.}}
4106
ACL2 !>(set-iprint t)
;{{See :DOC set-print. This causes \"#@1#\" below to be printed.}}
ACL2 Observation in SET-IPRINT: Iprinting has been enabled.
ACL2 !>(set-evisc-tuple (evisc-tuple 3 ; print-level
4 ; print-length
nil ; alist
nil ; hiding-cars
)
:sites :ld)
;{{Abbreviate the printing of top-level evaluation results.
; See :doc set-evisc-tuple.}}
(:LD)
ACL2 !>(make-list 10)
(NIL NIL NIL NIL . #@1#)
ACL2 !>'#@1#
;{{Note that the reader replaces #@1# with the value that was stored there.}}
(NIL NIL NIL NIL . #@2#)
ACL2 !>(without-evisc '(NIL NIL NIL NIL . #@1#))
;{{See :doc without-evisc.}}
(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
ACL2 !>(set-evisc-tuple nil :sites :ld)
(:LD)
ACL2 !>(let ((x '(3 4)))
`(a b ,x c))
;{{As in Common Lisp, backquote can be escaped by comma.}}
(A B (3 4) C)
ACL2 !>(let ((x '(3 4)))
`(a b ,@x c))
;{{As in Common Lisp, backquote can be escaped by comma-atsign, which
; splices its value into the list.}}
(A B 3 4 C)
ACL2 !>
Subtopics
[Fancy-string-reader]
A friendly syntax for strings literals that have backslashes and
quotes.
[Sharp-bang-reader]
Package prefix that is not restricted to symbols
[Sharp-dot-reader]
Read-time evaluation of constants
[Sharp-u-reader]
Allow underscore characters in numbers")
(REAL
(ACL2)
"ACL2(r) support for real numbers
ACL2 supports rational numbers but not real numbers. However,
starting with Version 2.5, a variant of ACL2 called ``ACL2(r)''
supports the real numbers by way of non-standard analysis. ACL2(r)
was conceived and first implemented by Ruben Gamboa in his Ph.D.
dissertation work, supervised by Bob Boyer with active
participation by Matt Kaufmann.
ACL2(r) has the same source files as ACL2. After you download ACL2,
you can build ACL2(r) by executing the following command on the
command line in your acl2-sources directory, replacing <your_lisp>
with a path to your Lisp executable:
make large-acl2r LISP=<your_lisp>
This will create an executable in your acl2-sources directory named
saved_acl2r.
Note that if you download [community-books] as tarfiles, then you
will automatically be obtaining the books to be certified with
ACL2(r). They can be certified from your acl2-sources directory,
shown here as <DIR>:
make regression ACL2=<DIR>/saved_acl2r
To check that you are running ACL2(r), see if the prompt includes the
string ``(r)'', e.g.:
ACL2(r) !>
Or, look at (@ acl2-version) and see if ``(r)'' is a substring.
In ACL2 (as opposed to ACL2(r)), when we say ``real'' we mean
``rational.''
Caution: ACL2(r) should be considered experimental: although we
(Kaufmann and Moore) have carefully completed Gamboa's integration
of the reals into the ACL2 source code, our primary concern has
been to ensure unchanged behavior when ACL2 is compiled in the
default manner, i.e., without the non-standard extensions. As for
every release of ACL2, at the time of a release we are unaware of
soundness bugs in ACL2 or ACL2(r).
There is only limited documentation on the non-standard features of
ACL2(r). We hope to provide more documentation for such features in
future releases. Please feel free to query the authors if you are
interested in learning more about ACL2(r). Gamboa's dissertation
may also be helpful.
Subtopics
[I-close]
ACL2(r) test for whether two numbers are infinitesimally close
[I-large]
ACL2(r) recognizer for infinitely large numbers
[I-limited]
ACL2(r) recognizer for limited numbers
[I-small]
ACL2(r) recognizer for infinitesimal numbers
[Real-listp]
ACL2(r) recognizer for a true list of real numbers
[Standard-part]
ACL2(r) function mapping limited numbers to standard numbers
[Standardp]
ACL2(r) recognizer for standard objects")
(REAL-LISTP
(REAL LISTS ACL2-BUILT-INS)
"ACL2(r) recognizer for a true list of real numbers
The predicate real-listp tests whether its argument is a true list of
real numbers. This predicate is only defined in ACL2(r) (see
[real]).")
(REAL/RATIONALP
(NUMBERS ACL2-BUILT-INS)
"Recognizer for rational numbers (including real number in ACL2(r))
For most ACL2 users, this is a macro abbreviating [rationalp]. In
ACL2(r) (see [real]), this macro abbreviates the predicate realp,
which holds for real numbers as well (including rationals). Most
ACL2 users can ignore this macro and use [rationalp] instead, but
many community books use real/rationalp so that these books will be
suitable for ACL2(r) as well.")
(REALFIX
(NUMBERS ACL2-BUILT-INS)
"Coerce to a real number
Realfix simply returns any real number argument unchanged, returning
0 on a non-real argument. Also see [nfix], see [ifix], see [rfix],
and see [fix] for analogous functions that coerce to a natural
number, an integer, a rational, and a number, respectively.
Realfix has a [guard] of t.
Function: <realfix>
(defun realfix (x)
(declare (xargs :guard t))
(if (real/rationalp x) x 0))")
(REALPART
(NUMBERS ACL2-BUILT-INS)
"Real part of a complex number
Completion Axiom (completion-of-realpart):
(equal (realpart x)
(if (acl2-numberp x)
(realpart x)
0))
[Guard] for (realpart x):
(acl2-numberp x)")
(REBUILD
(LD)
"A convenient way to reconstruct your old [state]
Examples:
ACL2 !>(rebuild \"project.lisp\")
ACL2 !>(rebuild \"project.lisp\" t)
ACL2 !>(rebuild \"project.lisp\" t :dir :system)
ACL2 !>(rebuild \"project.lisp\" :all)
ACL2 !>(rebuild \"project.lisp\" :query)
ACL2 !>(rebuild \"project.lisp\" 'lemma-22)
Rebuild allows you to assume all the [command]s in a given file or
list, supplied in the first argument. Because rebuild processes an
arbitrary sequence of [command]s with [ld-skip-proofsp] t, it is
unsound! However, if each of these [command]s is in fact
admissible, then processing them with rebuild will construct the
same logical [state] that you would be in if you typed each
[command] and waited through the proofs again. Thus, rebuild is a
way to reconstruct a [state] previously obtained by proving your
way through the [command]s.
The second, optional argument to rebuild is a ``filter'' (see
[ld-pre-eval-filter]) that lets you specify which [command]s to
process. You may specify t, :all, :query, or a new logical name. t
and :all both mean that you expect the entire file or list to be
processed. :query means that you will be asked about each [command]
in turn. A new name means that all [command]s will be processed as
long as the name is new, i.e., rebuild will stop processing
[command]s immediately after executing a [command] that introduces
name. Rebuild will also stop if any [command] causes an error. You
may therefore wish to plant an erroneous form in the file, e.g.,
(mv t nil state), (see [ld-error-triples]), to cause rebuild to
stop there. The form (i-am-here) is such a pre-defined form. If you
do not specify a filter, rebuild will query you for one.
Inspection of the definition of rebuild, e.g., via :[pc] rebuild-fn,
will reveal that it is just a glorified call to the function [ld].
See [ld] if you find yourself wishing that rebuild had additional
functionality.
If you supply the above ``filter'' argument, then you may also supply
the keyword argument :dir, which is then passed to ld; see [ld].")
(REDEF
(LD)
"A common way to set [ld-redefinition-action]
Example and General Form:
ACL2 !>:redef
This command sets [ld-redefinition-action] to '(:query . :overwrite).
This command allows redefinition of functions and other [events]
without undoing, but with a query that requires the user to
acknowledge that the redefinition is intentional. To avoid that
query, see [redef!] or for more options, see
[ld-redefinition-action].")
(REDEF!
(LD)
"A common way to set [ld-redefinition-action]
Example and General Form:
ACL2 !>:redef!
This command sets [ld-redefinition-action] to '(:warn! . :overwrite).
This command allows redefinition of functions and other [events]
without undoing, but with a warning. The command :[redef] is
similar, but queries the user first before doing the redefinition.
For more related options, see [ld-redefinition-action].")
(REDEF+
(LD)
"System hacker's redefinition [command]
Example and General Form:
ACL2 !>:redef+
ACL2 p!>
This [command] is intended only for system hackers, not typical
users. It sets [ld-redefinition-action] to '(:warn! . :overwrite),
sets the default [defun-mode] to :[program], and invokes
[set-state-ok] with value t. It also introduces (defttag :redef+),
so that redefinition of system functions will be permitted; see
[defttag]. Finally, it removes as untouchable (see
[push-untouchable]) all variables and functions.
WARNING: If the form (redef+) is used in a book, then including the
book can leave you in a state in which dangerous actions are
allowed, specifically: redefinition, and access to functions and
variables normally prohibited because they are untouchable. To
avoid this problem, insert the form ([redef-]) into your book after
(redef+).
To see the code for redef+, evaluate :trans1 (redef+). This [command]
is intended for those who are modifying ACL2 source code
definitions. Thus, note that even system functions can be redefined
with a mere warning. Be careful!")
(REDEF-
(LD)
"Turn off system hacker's redefinition [command]
Example and General Form:
ACL2 !>:redef-
ACL2 p!>
This macro, for system hackers only, is a convenient way to reverse
the effects of :redef+. See [redef+]. We do not guarantee that
:redef- will restore everything one might expect to its state
before the earlier :redef+. To see exactly what :redef- does, look
at its code, for example by evaluating :trans1 (redef-)")
(REDEFINED-NAMES
(WORLD)
"To collect the names that have been redefined
Example and General Forms:
(redefined-names state)
This function collects names that have been redefined in the current
ACL2 [state]. :[Program] mode functions that were reclassified to
:[logic] functions are not collected, since such reclassification
cannot imperil soundness because it is allowed only when the new
and old definitions are identical.
Thus, if (redefined-names state) returns nil then no unsafe
definitions have been made, regardless of [ld-redefinition-action].
See [ld-redefinition-action].
WARNING: This function does not report names that are not explicitly
redefined in the current logical [world]. Consider for example:
(encapsulate
()
(defun foo () t)
(local (defun foo () nil))
(defthm foo-prop
(equal (foo) nil)
:rule-classes nil))
If you attempt to call [certify-book] in the resulting world, ACL2
will appropriately refuse to do the certification:
ACL2 Error in (CERTIFY-BOOK \"foo\" ...): At least one command in the
current ACL2 world was executed while the value of state global variable
'LD-REDEFINITION-ACTION was not nil:
(DEFUN FOO NIL T)
Certification is therefore not allowed in this world. You can use
:ubt to undo back through this command; see :DOC ubt.
However, since the local redefinition of foo is gone in the
certification world, (redefined-names state) will return nil.
(Technical aside, to be ignored except for those interested in
implementation details: ACL2 inhibits certify-book in this example
because the definition of foo is the value of (global-val
'redef-seen (w state)).)")
(REDEFINING-PROGRAMS
(PROGRAMMING)
"An explanation of why we restrict redefinitions
ACL2 does not in general allow the redefinition of functions because
logical inconsistency can result: previously stored theorems can be
rendered invalid if the axioms defining the functions involved are
changed. However, to permit prototyping of both :[program] and
:[logic] mode systems, ACL2 permits redefinition if the user has
accepted logical responsibility for the consequences by setting
[ld-redefinition-action] to an appropriate non-nil value. The
refusal of ACL2 to support the unrestricted redefinition of
:[program] mode functions may appear somewhat capricious. After
all, what are the logical consequences of changing a definition if
no axioms are involved?
Three important points should be made before we discuss redefinition
further.
The first is that ACL2 does support redefinition (of both :[program]
and :[logic] functions) when [ld-redefinition-action] is non-nil.
The second is that a ``redefinition'' that does not change the mode,
formals, guards, type declarations, stobjs, or body of a function
is considered redundant and is permitted even when
[ld-redefinition-action] is nil. We recognize and permit redundant
definitions because it is not uncommon for two distinct [books] to
share identical function definitions. When determining whether the
body of a function is changed by a proposed redefinition, we
actually compare the untranslated versions of the two bodies. See
[term]. For example, redundancy is not recognized if the old body
is (list a b) and the new body is (cons a (cons b nil)). We use the
untranslated bodies because of the difficulty of translating the
new body in the presence of the old syntactic information, given
the possibility that the redefinition might attempt to change the
[signature] of the function, i.e., the number of formals, the
number of results, or the position of single-threaded objects in
either.
The third important point is that a ``redefinition'' that preserves
the formals, guard, types, stobjs, and body but changes the mode
from :[program] to :[logic] is permitted even when
[ld-redefinition-action] is nil. That is what [verify-termination]
does.
This note addresses the temptation to allow redefinition of
:[program] functions in situations other than the three described
above. Therefore, suppose [ld-redefinition-action] is nil and
consider the cases.
Case 1. Suppose the new definition attempts to change the formals or
more generally the [signature] of the function. Accepting such a
redefinition would render ill-formed other :[program] functions
which call the redefined function. Subsequent attempts to evaluate
those callers could arbitrarily damage the Common Lisp image. Thus,
redefinition of :[program] functions under these circumstances
requires the user's active approval, as would be sought with
[ld-redefinition-action] '(:query . :overwrite).
Case 2. Suppose the new definition attempts to change the body (even
though it preserves the [signature]). At one time we believed this
was acceptable and ACL2 supported the quiet redefinition of
:[program] mode functions in this circumstance. However, because
such functions can be used in macros and redundancy checking is
based on untranslated bodies, this turns out to be unsound! (Aside:
Perhaps this is not an issue if the function takes [state] or a
user-defined [stobj] argument; but we do not further consider this
distinction.) Such redefinition is therefore now prohibited. We
illustrate such an unsoundness below. Let foo-thm1.lisp be a book
with the following contents.
(in-package \"ACL2\")
(defun p1 (x) (declare (xargs :mode :program)) (list 'if x 't 'nil))
(defmacro p (x) (p1 x))
(defun foo (x) (p x))
(defthm foo-thm1 (iff (foo x) x) :rule-classes nil)
Note that the macro form (p x) translates to (if x t nil). The
:[program] function p1 is used to generate this translation. The
function foo is defined so that (foo x) is (p x) and a theorem
about foo is proved, namely, that (foo x) is true iff x is true.
Now let foo-thm2.lisp be a book with the following contents.
(in-package \"ACL2\")
(defun p1 (x) (declare (xargs :mode :program)) (list 'if x 'nil 't))
(defmacro p (x) (p1 x))
(defun foo (x) (p x))
(defthm foo-thm2 (iff (foo x) (not x)) :rule-classes nil)
In this book, the :[program] function p1 is defined so that (p x)
means just the negation of what it meant in the first book, namely,
(if x nil t). The function foo is defined identically --- more
precisely, the untranslated body of foo is identical in the two
[books], but because of the difference between the two versions of
the :[program] function p1 the axioms defining the two foos are
different. In the second book we prove the theorem that (foo x) is
true iff x is nil.
Now consider what would happen if the [signature]-preserving
redefinition of :[program] functions were permitted and these two
[books] were included. When the second book is included the
redefinition of p1 would be permitted since the [signature] is
preserved and p1 is just a :[program]. But then when the
redefinition of foo is processed it would be considered redundant
and thus be permitted. The result would be a logic in which it was
possible to prove that (foo x) is equivalent to both x and (not x).
In particular, the following sequence leads to a proof of nil:
(include-book \"foo-thm1\")
(include-book \"foo-thm2\")
(thm nil :hints ((\"Goal\" :use (foo-thm1 foo-thm2))))
It might be possible to loosen the restrictions on the redefinition
of :[program] functions by allowing [signature]-preserving
redefinition of :[program] functions not involved in macro
definitions. Alternatively, we could implement definition
redundancy checking based on the translated bodies of functions
(though that is quite problematic). Barring those two changes, we
believe it is necessary simply to impose the same restrictions on
the redefinition of :[program] mode functions as we do on :[logic]
mode functions.")
(REDO-FLAT
(DEBUGGING)
"Redo on failure of a [progn], [encapsulate], or [certify-book]
When one submits an [encapsulate], [progn], or [certify-book] command
and there is a failure, ACL2 restores its logical [world] as though
the command had not been run. But sometimes one would like to debug
the failure by re-executing all sub-events that succeeded up to the
point of failure, and then re-executing the failed sub-event. Said
differently, imagine that the [events] under an encapsulate, progn,
or certify-book form were flattened into a list of events that were
then submitted to ACL2 up to the point of failure. This would put
us in the state in which the original failed event had failed, so
we could now replay that failed event and try modifying it, or
first proving additional events, in order to get it admitted.
Redo-flat is provided for this purpose. Consider the following
(rather nonsensical) example, in which the [defun] of f3 fails (the
body is y but the formal parameter list is (x)).
(encapsulate
()
(defun f1 (x) x)
(encapsulate ()
(local (defthm hack (equal (car (cons x y)) x))))
(encapsulate ()
(local (defthm hack (equal (+ x y) (+ y x)))))
(encapsulate ()
(make-event '(defun f2 (x) x))
(progn (defthm foo (equal x x) :rule-classes nil)
(defun f3 (x) y)))
(defun f4 (x) x)
(defun f5 (x) y))
After this attempt fails, you can evaluate the following form.
(redo-flat)
This will first lay down a [deflabel] event, (deflabel r), so that
you can eventually remove your debugging work with (:ubt! r). Then
the successful sub-events that preceded the failure will be
executed with proofs skipped (so that this execution is fast).
Then, the failed event will be executed. Finally, a :[pbt] command
is executed so that you can see a summary of the events that
executed successfully.
You can eliminate some of the steps above by supplying keyword
values, as follows.
(redo-flat
:succ succ ; Skip the successful sub-events if val is nil.
:fail fail ; Skip the failed sub-event if val is nil.
:label lab ; Skip deflabel if lab or succ is nil, else use (deflabel lab).
:pbt val ; Skip the final :pbt if val, lab, or succ is nil.
)
Also, you can avoid skipping proofs for the successful sub-events by
supplying keyword :succ-ld-skip-proofsp with a valid value for
ld-skip-proofsp; see [ld-skip-proofsp]. For example, you might want
to execute (redo-flat :succ-ld-skip-proofsp nil) if you use the
must-fail utility from community book make-event/eval.lisp, since
for example (must-fail (thm (equal x y))) normally succeeds but
would cause an error if proofs are skipped. For another example:
you may wish to do proofs when re-running certain [make-event]
forms, for example, when the expansion is (:OR expr1 expr2) and the
proof initially succeeds for expr2 rather than expr1 (see
[make-event]).
If you prefer only to see the successful and failed sub-events,
without any events being re-executed, you may evaluate the
following form instead.
(redo-flat :show t)
For the example above, this command produces the following output.
List of events preceding the failure:
((DEFUN F1 (X) X)
(ENCAPSULATE NIL
(LOCAL (DEFTHM HACK (EQUAL (CAR (CONS X Y)) X))))
(ENCAPSULATE NIL
(LOCAL (DEFTHM HACK (EQUAL (+ X Y) (+ Y X)))))
(MAKE-EVENT '(DEFUN F2 (X) X))
(DEFTHM FOO (EQUAL X X)
:RULE-CLASSES NIL))
Failed event:
(DEFUN F3 (X) Y)
ACL2 !>
Redo-flat uses a scheme that should not cause spurious name conflicts
for [local] events. Above, it is mentioned that events are
``flattened''; now we clarify this notion. Each sub-event that
succeeds and is an [encapsulate] or [progn] is left intact. Only
such events that fail are replaced by their component events. Thus,
in the example above, there is no conflict between the two [local]
sub-events named ``hack,'' because these are contained in
successful encapsulate sub-events, which are therefore not
flattened. The [progn] and two [encapsulate] events surrounding the
definition of f3 are, however, flattened, because that definition
failed to be admitted.
Normally, redo-flat will have the desired effect even if you
interrupted a proof (with control-c). However, redo-flat will not
produce the desired result after an interrupt if you have enabled
the debugger using (set-debugger-enable t),")
(REDUNDANT-ENCAPSULATE
(ENCAPSULATE)
"Redundancy of [encapsulate] [events]
For this [documentation] topic we assume familiarity with encapsulate
events and the notion of redundancy for [events]; see [encapsulate]
and see [redundant-events].
The typical way for an encapsulate event to be redundant is when a
syntactically identical encapsulate has already been executed under
the same [default-defun-mode], [default-ruler-extenders], and
[default-verify-guards-eagerness]. But more generally, the
encapsulate events need not be syntactically identical; for
example, it suffices that they agree when the contents of [local]
sub-events are ignored. Detailed criteria for redundancy are given
below, but let us first look at a consequence of the point just
made about ignoring the contents of [local] sub-events. Consider
the following sequence of two events.
(encapsulate
()
(defun f (x) x)
(local (defthm f-identity
(equal (f x) x))))
(encapsulate
()
(defun f (x) x)
(local (defthm false-claim
(equal (f x) (not x)))))
You might be surprised to learn that the second is actually
redundant, even though false-claim is clearly not a theorem;
indeed, its negation is a theorem! The following two points may
soften the blow. First, this behavior is as specified above (and is
specified more precisely below): the contents of [local] events are
ignored when checking redundancy of [encapsulate] events. Second,
this behavior is sound, because the logical meaning of an
[encapsulate] event is taken from the events that it exports, which
do not include events that are [local] to the encapsulate event.
Some users, however, want to use [encapsulate] events for testing in
a way that is thwarted by this ignoring of [local] sub-events.
Consider the following sort of example.
(encapsulate ()
(local (defthm test1 ...)))
(encapsulate ()
(local (defthm test2 ...)))
Fortunately, in this case both test1 and test2 will be evaluated. To
see why, first note that when a completed [encapsulate] event with
empty [signature] has introduced no sub-[events], then it has no
effect at all on the logical [world]. Thus, the first encapsulate
event is not stored in the world; so, the second encapsulate event
is not redundant, since it is executed in a world that contains no
trace of the first encapsulate event.
Also see community books misc/eval.lisp, make-event/eval-check.lisp,
and make-event/eval-tests.lisp for more ways to test in books.
Here are detailed criteria for redundancy of [encapsulate] [events].
First, based on a heuristic (but rather thorough) check, the
proposed (new) encapsulate event must be seen as possibly
introducing a new name, for example because one of its sub-events,
perhaps after some macroexpansion, is an invocation of [defun],
[defthm], or of certain other events that could introduce a name,
including [make-event]. Second, the two [world]s in which each
encapsulate event is evaluated must have the same
[default-defun-mode]s, the same [default-ruler-extenders], and the
same [default-verify-guards-eagerness]. Third, the existing and
proposed encapsulate [events] must contain the same [signature]s
and the same number of top-level sub-events; let k be that number.
Finally: for each i < k, the ith top-level events E1 and E2 from
the earlier and proposed encapsulates must be related in one of the
following ways.
* E1 and E2 are equal; or
* E1 is of the form (record-expansion E2 ...); or else
* E1 and E2 are equal after replacing each sub-event of E1 with its
[make-event] expansion and replacing each [local] sub-event of
E1 or E2 by (local (value-triple :elided)). Here, a sub-event
of an event E is defined to be either E itself, or a sub-event
of a constituent event of E in the case that E is a call of
[skip-proofs], [with-output], [with-prover-time-limit],
[with-prover-step-limit], record-expansion, [time$], [progn],
[progn!], or [encapsulate] itself.")
(REDUNDANT-EVENTS
(EVENTS)
"Allowing a name to be introduced ``twice''
Sometimes an event will announce that it is ``redundant'', meaning
that the the form is not evaluated because ACL2 determines that its
effect is already incorporated into the logical [world]. Thus, when
this happens, no change to the logical [world] takes place. This
feature permits two independent [books], each of which defines some
name, to be included sequentially provided they use exactly the
same definition.
Note that by the definition above, a form can have no effect on the
logical [world] yet not be considered to be redundant. Here is an
example of such a form.
(value-triple (cw \"Hello world.~%\"))
When are two [logical-name] definitions considered ``the same''? It
depends upon the kind of name being defined. We consider these
below in alphabetical order. See also the Notes below.
A [defabsstobj] is redundant if there is already an identical
defabsstobj event in the logical [world].
A [defattach] event is never redundant. Note that it doesn't define
any name.
A [defaxiom] or [defthm] event is redundant if there is already an
axiom or theorem of the given name and either the two [events] are
syntactically identical, or both the formula (after macroexpansion)
and the resulting [rule-classes] are syntactically identical. Note
that because of the second of these two criteria, a [defaxiom] can
make a subsequent [defthm] redundant, and a [defthm] can make a
subsequent [defaxiom] redundant as well.
A [defconst] is redundant if the name is already defined either with
a syntactically identical defconst event or one that defines it to
have the same value.
A [deflabel] event is never redundant. This means that if you have a
[deflabel] in a book and that book has been included (without
error), then references to that label denote the point in [history]
at which the book introduced the label. See the note about shifting
logical names, below.
A [defmacro] event is redundant if there is already a macro defined
with the same name and syntactically identical arguments, [guard],
and body.
A [defpkg] event is redundant if a package of the same name with
exactly the same imports has been defined.
A [defstobj] event is redundant if there is already a defstobj event
with the same name that has exactly the same field descriptors (see
[defstobj]), in the same order, and with the same :renaming value
if :renaming is supplied for either event.
A [defthm] event is redundant according to the criteria given above
in the discussion of defaxiom.
A [deftheory] is never redundant. The ``natural'' notion of
equivalent [deftheory] forms is that the names and values of the
two theory expressions are the same. But since most theory
expressions are sensitive to the context in which they occur, it
seems unlikely to us that two [deftheory]s coming from two
sequentially included [books] will ever have the same values. So we
prohibit redundant theory definitions. If you try to define the
same theory name twice, you will get a ``name in use'' error.
A [defun], [defuns], or [mutual-recursion] event is redundant if for
each function to be introduced, there has already been introduced a
function with the same name, formals, and body (before
macroexpansion), and with the same values [declare]d for the
:[guard], :[measure], types, :[ruler-extenders], :non-executable,
:[stobj]s, and :[split-types], provided that the [defun-mode]s are
appropriate (see the ``Note About Appropriate Modes'' below).
Moreover, the order of the combined :[guard] and type declarations
must be the same in both cases. Exceptions and clarifications:
1. The ruler-extenders are checked with respect to the appropriate
[default-ruler-extenders].
2. It is permissible for one definition to have a :[guard] of t and the
other to have no explicit guard (hence, the guard is implicitly
t).
3. The :measure check is avoided if the old definition is non-recursive
(and not defined within a [mutual-recursion]) or we are
skipping proofs (for example, during [include-book]).
Otherwise, the new definition may have a :measure of (:? v1 ...
vk), where (v1 ... vk) enumerates the variables occurring in
the measure stored for the old definition.
4. If either the old or new event is a [mutual-recursion] event, then
redundancy requires that both are [mutual-recursion] events
that define the same set of function symbols.
An [encapsulate] event is most commonly redundant when a
syntactically identical [encapsulate] has already been executed
under the same [default-defun-mode], [default-ruler-extenders], and
[default-verify-guards-eagerness]. The full criterion for
redundancy of encapsulate events is more complex, for example
ignoring contents of [local] [events]; see [redundant-encapsulate].
An [in-theory] event is never redundant. Note that it doesn't define
any name.
An [include-book] event is redundant if the book has already been
included.
A call of [make-event] is never redundant, as its argument is always
evaluated to obtain the make-event expansion. However, that
expansion may of course be redundant.
A [mutual-recursion] event is redundant according to the criteria in
the discussion above for the case of a defun event.
A [progn] event is never redundant: its subsidiary [events] are
always considered. Of course, its sub-events may themselves be
redundant. If all of its sub-events are redundant --- or more
generally, if none of the sub-events changes the logical [world]
--- then the progn event also won't change the world.
A [push-untouchable] event is redundant if every name supplied is
already a member of the corresponding list of untouchable symbols.
A [regenerate-tau-database] event is never redundant. Note that it
doesn't define any name.
A [remove-untouchable] event is redundant if no name supplied is a
member of the corresponding list of untouchable symbols.
A [reset-prehistory] event is redundant if it does not cause any
change.
A [set-body] event is redundant if the indicated body is already the
current body.
A [table] event not define any name. It is redundant when it sets the
value already associated with a key of the table, or when it sets
an entire table (using keyword :clear) to its existing value; see
[table].
A [verify-guards] event is redundant if the function has already had
its [guard]s verified.
Note About Built-in (Predefined) Functions and Macros:
Redundancy is restricted for built-in macros and functions that have
special raw Lisp code. Such redundancy is only legal in the context
of [local]. This restriction is needed for soundness, for technical
reasons omitted here (details may be found in a long comment about
redundant-events in source function
chk-acceptable-defuns-redundancy).
Note About Appropriate Modes:
Suppose a function is being redefined and that the formals, guards,
types, stobjs, and bodies are identical. When are the modes
(:[program] or :[logic]) ``appropriate?'' Identical modes are
appropriate. But what if the old mode was :program and the new mode
is :logic? This is appropriate, provided the definition meets the
requirements of the logical definitional principle. That is, you
may redefine ``redundantly'' a :program mode function as a :logic
mode function provide the measure conjectures can be proved. This
is what [verify-termination] does. Now consider the reverse style
of redefinition. Suppose the function was defined in :logic mode
and is being identically redefined in :program mode. ACL2 will
treat the redefinition as redundant, provided the appropriate
criteria are met (as though it were in :logic mode).
Note About Shifting Logical Names:
Suppose a book defines a function fn and later uses fn as a logical
name in a theory expression. Consider the value of that theory
expression in two different sessions. In session A, the book is
included in a [world] in which fn is not already defined, i.e., in
a [world] in which the book's definition of fn is not redundant. In
session B, the book is included in a [world] in which fn is already
identically defined. In session B, the book's definition of fn is
redundant. When fn is used as a logical name in a theory
expression, it denotes the point in [history] at which fn was
introduced. Observe that those points are different in the two
sessions. Hence, it is likely that theory expressions involving fn
will have different values in session A than in session B.
This may adversely affect the user of your book. For example, suppose
your book creates a theory via [deftheory] that is advertised just
to contain the names generated by the book. But suppose you compute
the theory as the very last event in the book using:
(set-difference-theories (universal-theory :here)
(universal-theory fn))
where fn is the very first event in the book and happens to be a
[defun] event. This expression returns the advertised set if fn is
not already defined when the book is included. But if fn were
previously (identically) defined, the theory is larger than
advertised.
The moral of this is simple: when building [books] that other people
will use, it is best to describe your [theories] in terms of
logical names that will not shift around when the [books] are
included. The best such names are those created by [deflabel].
Note About Unfortunate Redundancies.
Notice that our syntactic criterion for redundancy of [defun]
[events] may not allow redefinition to take effect unless there is
a syntactic change in the definition. The following example shows
how an attempt to redefine a function can fail to make any change.
(set-ld-redefinition-action '(:warn . :overwrite) state)
(defmacro mac (x) x)
(defun foo (x) (mac x))
(defmacro mac (x) (list 'car x))
(set-ld-redefinition-action nil state)
(defun foo (x) (mac x)) ; redundant, unfortunately; foo does not change
(thm (equal (foo 3) 3)) ; succeeds, showing that redef of foo didn't happen
The call of macro mac was expanded away before storing the first
definition of foo for the theorem prover. Therefore, the new
definition of mac does not affect the expansion of foo by the
theorem prover, because the new definition of foo is ignored.
One workaround is first to supply a different definition of foo, just
before the last definition of foo above. Then that final definition
will no longer be redundant. However, as a courtesy to users, we
strengthen the redundancy check for function definitions when
redefinition is active. If in the example above we remove the form
(set-ld-redefinition-action nil state), then the problem goes away:
(set-ld-redefinition-action '(:warn . :overwrite) state)
(defmacro mac (x) x)
(defun foo (x) (mac x))
(defmacro mac (x) (list 'car x))
(defun foo (x) (mac x)) ; no longer redundant
(thm (equal (foo 3) 3)) ; fails, as we would like
To summarize: If a [defun] form is submitted that meets the usual
redundancy criteria, then it may be considered redundant even if a
macro called in the definition has since been redefined. The
analogous problem applie to constants, i.e., symbols defined by
[defconst] that occur in the definition body. However, if
redefinition is currently active the problem goes away: that is,
the redundancy check is strengthened to check the ``translated''
body, in which macro calls and constants defined by [defconst] are
expanded away.
The above discussion for [defun] forms applies to [defconst] forms as
well. However, for [defmacro] forms ACL2 always checks translated
bodies, so such bogus redundancy does not occur.
Here is more complex example illustrating the limits of redefinition,
based on one supplied by Grant Passmore.
(defun n3 () 0)
(defun n4 () 1)
(defun n5 () (> (n3) (n4))) ; body is normalized to nil
(thm (equal (n5) nil)) ; succeeds, trivially
(set-ld-redefinition-action '(:warn . :overwrite) state)
(defun n3 () 2)
(thm (equal (n5) nil)) ; still succeeds, sadly
We may expect the final [thm] call to fail because of the following
reasoning: (n5) = (> (n3) (n4)) = (> 2 1) = t. Unfortunatly, the
body of n5 was simplified (``normalized'') to nil when n5 was
admitted, so the redefinition of n3 is ignored during the final thm
call. (Such normalization can be avoided; see the brief discussion
of :normalize in the documentation for [defun].) So, given this
unfortunate situation, one might expect at this point simply to
redefine n5 using the same definition as before, in order to pick
up the new definition of n3. Such ``redefinition'' would, however,
be redundant, for the same reason as in the previous example: no
syntactic change was made to the definition. Even with redefinition
active, there is no change in the body of n5, even with macros and
constants (defined by [defconst]) expanded; there are none such!
The same workaround applies as before: redefine n5 to be something
different, and then redefine n5 again to be as desired.
A related phenomenon can occur for [encapsulate]. As explained above,
an encapsulate event is redundant if it is identical to one already
in the database. (But a weaker condition applies in general; see
[redundant-encapsulate].) Consider then the following contrived
example.
(defmacro mac (x) x)
(encapsulate () (defun foo (x) (mac x)))
(set-ld-redefinition-action '(:warn . :overwrite) state)
(defmacro mac (x) (list 'car x))
(encapsulate () (defun foo (x) (mac x)))
The last encapsulate event is redundant because it meets the
criterion for redundancy: it is identical to the earlier
encapsulate event. Even though redefinition is active, and hence
ACL2 ``should'' be able to see that the new [defun] of foo is not
truly redundant, nevertheless the criterion for redundancy of
[encapsulate] allows the new encapsulate form to be redundant.
A workaround can be to add something trivial to the encapsulate, for
example:
(encapsulate ()
(deflabel try2) ; ``Increment'' to try3 next time, and so on.
(defun foo (x) x))
Subtopics
[Set-enforce-redundancy]
Require most events to be redundant")
(REFINEMENT
(RULE-CLASSES)
"Record that one equivalence relation refines another
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Example:
(defthm bag-equal-refines-set-equal
(implies (bag-equal x y)
(set-equal y x))
:rule-classes :refinement)
Also see [defrefinement].
General Form:
(implies (equiv1 x y) (equiv2 x y))
Equiv1 and equiv2 must be known equivalence relations. The effect of
such a rule is to record that equiv1 is a refinement of equiv2.
This means that equiv1 :[rewrite] rules may be used while trying to
maintain equiv2. See [equivalence] for a general discussion of the
issues.
The macro form (defrefinement equiv1 equiv2) is an abbreviation for a
[defthm] of rule-class :refinement that establishes that equiv1 is
a refinement of equiv2. See [defrefinement].
Suppose we have the :[rewrite] rule
(bag-equal (append a b) (append b a))
which states that [append] is commutative modulo bag-equality.
Suppose further we have established that bag-equality refines
set-equality. Then when we are simplifying [append] expressions
while maintaining set-equality we use [append]'s commutativity
property, even though it was proved for bag-equality.
Equality is known to be a refinement of all equivalence relations.
The transitive closure of the refinement relation is maintained, so
if set-equality, say, is shown to be a refinement of some third
sense of equivalence, then bag-equality will automatially be known
as a refinement of that third equivalence.
:refinement lemmas cannot be disabled. That is, once one equivalence
relation has been shown to be a refinement of another, there is no
way to prevent the system from using that information. Of course,
individual :[rewrite] rules can be disabled.
More will be written about this as we develop the techniques.")
(REGENERATE-TAU-DATABASE
(EVENTS INTRODUCTION-TO-THE-TAU-SYSTEM)
"Regenerate the tau database relative to the current enabled theory
General Form:
(regenerate-tau-database)
The tau database is regenerated by scanning the current logical world
and re-processing every rule-generating event in it relative to the
current enabled theory and current tau auto mode settings. See
[introduction-to-the-tau-system] for background details.
This command was intended to allow the user to remove a fact from the
tau database, by regenerating the database without the fact. But as
the following discussion highlights, regenerate-tau-database does
not really solve the problem. We regard it as a placeholder for a
more sophisticated mechanism. However, we have trouble
understanding why a user might wish to remove a fact from the
database and are awaiting further user experiences before designing
the more sophisticated mechanism.
Suppose, for example, that you wanted to remove a signature rule
provided by some rule with name rune. You could disable rune and
regenerate the database. We discuss why you might --- or might not
--- want to do this later. But suppose you did it. Unfortunately,
the database you get will not be just like the one you started with
minus the signature rule. The reason is that the database you
started with was generated incrementally and the current theory
might have evolved. To take a simple example, your starting
database might have included a rule that has been disabled since it
was first added. Thus, the part of your starting database built
before the disabling was constructed with the rule enabled and the
part built afterwards has the rule disabled. You are unlikely to
get the same database whether you enable or disable that rule now.
You might hope that the avoidance of in-theory events would eliminate
the problem but it does not because even the [ground-zero] theory
is constructed incrementally from the ``pre-history'' commands used
to boot up ACL2. Those pre-history commands include some global
in-theory commands. Since every session starts from the ground-zero
state, the starting database is already ``infected'' with global
in-theory commands.
The reason we hope that it will not be necessary to remove tau facts
is that the tau system is designed merely to be fast and benign
(see Design Philosophy in [introduction-to-the-tau-system]). The
tau system's coverage should grows monotonically with the addition
of rules. According to this understanding of tau, adding a
signature rule, for example, may allow tau to prove some additional
goals but will not prevent it from proving goals it could prove
previously. If this is understanding of tau is accurate, we see no
fundamental reason to support the removal of a fact. This, of
course, ignores the possibility that the user wishes to explore
alternative proof strategies or measure performance.
We welcome user observations and experience on this issue.")
(REGRESSION (POINTERS)
"See [books-certification].")
(RELEASE-NOTES
(ABOUT-ACL2)
"Pointers to what has changed
This section of the online [documentation] contains notes on the
changes that distinguish successive released versions of ACL2.
The current version of ACL2 is the value of the constant (@
acl2-version).
Subtopics
[Note-2-0]
ACL2 Version 2.0 (July, 1997) Notes
[Note-2-1]
ACL2 Version 2.1 (December, 1997) Notes
[Note-2-2]
ACL2 Version 2.2 (August, 1998) Notes
[Note-2-3]
ACL2 Version 2.3 (October, 1998) Notes
[Note-2-4]
ACL2 Version 2.4 (August, 1999) Notes
[Note-2-5]
ACL2 Version 2.5 (June, 2000) Notes
[Note-2-5{r}]
ACL2 Version 2.5(r) (June, 2000) Notes
[Note-2-6]
ACL2 Version 2.6 (November, 2001) Notes
[Note-2-6{r}]
ACL2 Version 2.6(r) (November, 2001) Notes
[Note-2-7]
ACL2 Version 2.7 (November, 2002) Notes
[Note-2-7{r}]
ACL2 Version 2.7(r) (November, 2002) Notes
[Note-2-8]
ACL2 Version 2.8 (March, 2004) Notes
[Note-2-8{r}]
ACL2 Version 2.8(r) (March, 2003) Notes
[Note-2-9]
ACL2 Version 2.9 (October, 2004) Notes
[Note-2-9{r}]
ACL2 Version 2.9(r) (October, 2004) Notes
[Note-2-9-1]
ACL2 Version 2.9.1 (December, 2004) Notes
[Note-2-9-2]
ACL2 Version 2.9.2 (April, 2005) Notes
[Note-2-9-3]
ACL2 Version 2.9.3 (August, 2005) Notes
[Note-2-9-4]
ACL2 Version 2.9.4 (February, 2006) Notes
[Note-2-9-5]
Changes in Version 3.0 since Version 2.9.4
[Note-3-0]
ACL2 Version 3.0 (June, 2006) Notes
[Note-3-0{r}]
ACL2 Version 3.0(r) (June, 2006) Notes
[Note-3-0-1]
ACL2 Version 3.0.1 (August, 2006) Notes
[Note-3-0-1{r}]
ACL2 Version 3.0.1(r) (August, 2006) Notes
[Note-3-0-2]
ACL2 Version 3.0.2 (December, 2006) Notes
[Note-3-1]
ACL2 Version 3.1 (December, 2006) Notes
[Note-3-1{r}]
ACL2 Version 3.1(r) (December, 2006) Notes
[Note-3-2]
ACL2 Version 3.2 (April, 2007) Notes
[Note-3-2{r}]
ACL2 Version 3.2(r) (April, 2007) Notes
[Note-3-2-1]
ACL2 Version 3.2.1 (June, 2007) Notes
[Note-3-2-1{r}]
ACL2 Version 3.2.1(r) (June, 2007) Notes
[Note-3-3]
ACL2 Version 3.3 (November, 2007) Notes
[Note-3-3{r}]
ACL2 Version 3.3(r) (November, 2007) Notes
[Note-3-4]
ACL2 Version 3.4 (August, 2008) Notes
[Note-3-4{r}]
ACL2 Version 3.4(r) (August, 2008) Notes
[Note-3-5]
ACL2 Version 3.5 (May, 2009) Notes
[Note-3-5{r}]
ACL2 Version 3.5(r) (May, 2009) Notes
[Note-3-6]
ACL2 Version 3.6 (August, 2009) Notes
[Note-3-6{r}]
ACL2 Version 3.6(r) (August, 2009) Notes
[Note-3-6-1]
ACL2 Version 3.6.1 (September, 2009) Notes
[Note-4-0]
ACL2 Version 4.0 (July, 2010) Notes
[Note-4-0{r}]
ACL2 Version 4.0(r) (July, 2010) Notes
[Note-4-1]
ACL2 Version 4.1 (September, 2010) Notes
[Note-4-1{r}]
ACL2 Version 4.1(r) (September, 2010) Notes
[Note-4-2]
ACL2 Version 4.2 (January, 2011) Notes
[Note-4-2{r}]
ACL2 Version 4.2(r) (January, 2011) Notes
[Note-4-3]
ACL2 Version 4.3 (July, 2011) Notes
[Note-4-3{r}]
ACL2 Version 4.3(r) (July, 2011) Notes
[Note-5-0]
ACL2 Version 5.0 (August, 2012) Notes
[Note-6-0]
ACL2 Version 6.0 (December, 2012) Notes
[Note-6-1]
ACL2 Version 6.1 (February, 2013) Notes
[Note-6-2]
ACL2 Version 6.2 (June, 2013) Notes
[Note-6-3]
ACL2 Version 6.3 (October, 2013) Notes
[Note-6-4]
ACL2 Version 6.4 (January, 2014) Notes
[Note-6-5]
ACL2 Version 6.5 (August, 2014) Notes
[Note-7-0]
ACL2 Version 7.0 (January, 2015) Notes
[Note-7-1]
ACL2 Version 7.1 (May, 2015) Notes
[Note-7-2]
ACL2 Version 7.2 (January, 2016) Notes
[Note1]
Acl2 Version 1.1 Notes
[Note2]
Acl2 Version 1.2 Notes
[Note3]
Acl2 Version 1.3 Notes
[Note4]
Acl2 Version 1.4 Notes
[Note5]
Acl2 Version 1.5 Notes
[Note6]
Acl2 Version 1.6 Notes
[Note7]
ACL2 Version 1.7 (released October 1994) Notes
[Note8]
ACL2 Version 1.8 (May, 1995) Notes
[Note8-update]
ACL2 Version 1.8 (Summer, 1995) Notes
[Note9]
ACL2 Version 1.9 (Fall, 1996) Notes")
(REM
(NUMBERS ACL2-BUILT-INS)
"Remainder using [truncate]
ACL2 !>(rem 14 3)
2
ACL2 !>(rem -14 3)
-2
ACL2 !>(rem 14 -3)
2
ACL2 !>(rem -14 -3)
-2
ACL2 !>(rem -15 -3)
0
ACL2 !>
(Rem i j) is that number k for which (* j (truncate i j)) added to k
equals i.
The [guard] for (rem i j) requires that i and j are rational ([real],
in ACL2(r)) numbers and j is non-zero.
Rem is a Common Lisp function. See any Common Lisp documentation for
more information.
Function: <rem>
(defun rem (x y)
(declare (xargs :guard (and (real/rationalp x)
(real/rationalp y)
(not (eql y 0)))))
(- x (* (truncate x y) y)))")
(REMOVE
(LISTS ACL2-BUILT-INS)
"Remove all occurrences
General Forms:
(remove x lst)
(remove x lst :test 'eql) ; same as above (eql as equality test)
(remove x lst :test 'eq) ; same, but eq is equality test
(remove x lst :test 'equal) ; same, but equal is equality test
(Remove x lst) is equal to lst if x is not a member of lst, else is
the result of removing all occurrences of x from lst. The optional
keyword, :TEST, has no effect logically, but provides the test
(default [eql]) used for comparing x with successive elements of
lst.
Also see [remove1].
The [guard] for a call of remove depends on the test. In all cases,
the second argument must satisfy [true-listp]. If the test is
[eql], then either the first argument must be suitable for [eql]
(see [eqlablep]) or the second argument must satisfy
[eqlable-listp]. If the test is [eq], then either the first
argument must be a symbol or the second argument must satisfy
[symbol-listp].
See [equality-variants] for a discussion of the relation between
remove and its variants:
(remove-eq x lst) is equivalent to (remove x lst :test 'eq);
(remove-equal x lst) is equivalent to (remove x lst :test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function remove-equal.
Function: <remove-equal>
(defun remove-equal (x l)
(declare (xargs :guard (true-listp l)))
(cond ((endp l) nil)
((equal x (car l))
(remove-equal x (cdr l)))
(t (cons (car l)
(remove-equal x (cdr l))))))
Remove is defined by Common Lisp. See any Common Lisp documentation
for more information.")
(REMOVE-BINOP
(MACROS)
"Remove the association of a function name with a macro name
The form (remove-binop macro-fn) is an abbreviation for the form
(remove-macro-fn macro-fn). See [remove-macro-fn].")
(REMOVE-CUSTOM-KEYWORD-HINT
(EVENTS)
"Remove a custom keyword hint
Example Forms:
(remove-custom-keyword-hint :my-hint)
General Form:
(remove-custom-keyword-hint keyword)
where keyword is a [keywordp].
For an explanation of how custom keyword hints are processed, see
[custom-keyword-hints]; also see [add-custom-keyword-hint].
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.")
(REMOVE-DEFAULT-HINTS
(DEFAULT-HINTS)
"Remove from the default hints
Examples:
(remove-default-hints '((computed-hint-1 clause)
(computed-hint-2 clause
stable-under-simplificationp)))
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It is [local] to the book or [encapsulate] form in which it occurs
(see [remove-default-hints!] for a corresponding non-[local]
event).
General Form:
(remove-default-hints lst)
where lst is a list. Generally speaking, the elements of lst should
be suitable for use as [computed-hints]. Also see
[add-default-hints].
If some elements of the given list do not belong to the existing
default hints, they will simply be ignored by this event.
Also See [set-default-hints], see [add-default-hints], and see
[default-hints].
Finally, note that the effects of set-default-hints,
[add-default-hints], and [remove-default-hints] are [local] to the
book in which they appear. Thus, users who include a book with such
forms will not have their default hints affected by such forms. In
order to export the effect of setting the default hints, use
[set-default-hints!], [add-default-hints!], or
[remove-default-hints!].")
(REMOVE-DEFAULT-HINTS!
(DEFAULT-HINTS)
"Remove from the default hints non-[local]ly
Please see [remove-default-hints], which is the same as
remove-default-hints! except that the latter is not [local] to the
[encapsulate] or the book in which it occurs. Probably
[remove-default-hints] is to be preferred unless you have a good
reason for wanting to export the effect of this event outside the
enclosing [encapsulate] or book.")
(REMOVE-DIVE-INTO-MACRO
(DIVE-INTO-MACROS-TABLE)
"Removes association of [proof-checker] diving function with macro
name
Example:
(remove-dive-into-macro logand)
This feature undoes the effect of [add-dive-into-macro], which is
used so that the [proof-checker]'s DV command and numeric diving
commands (e.g., 3) will dive properly into subterms. Please see
[add-dive-into-macro] and especially see [dive-into-macros-table].")
(REMOVE-DUPLICATES
(LISTS STRINGS ACL2-BUILT-INS)
"Remove duplicates from a string or a list
General Forms:
(remove-duplicates x)
(remove-duplicates x :test 'eql) ; same as above (eql as equality test)
(remove-duplicates x :test 'eq) ; same, but eq is equality test
(remove-duplicates x :test 'equal) ; same, but equal is equality test
(Remove-duplicates x) returns the result of deleting duplicate
elements from the beginning of the list or string x. For example,
(remove-duplicates '(1 2 3 2 4)) is equal to '(1 3 2 4). The
optional keyword, :TEST, has no effect logically, but provides the
test (default [eql]) used for comparing x with successive elements
of lst.
The [guard] for a call of remove-duplicates depends on the test. In
all cases, the argument must satisfy [stringp] or [true-listp]. If
the test is [eql], then the argument must satisfy either [stringp]
or [eqlable-listp]. If the test is [eq], then the argument must
satisfy [symbol-listp].
The relation between remove-duplicates and its variants is related to
the usual pattern for equality variants; see [equality-variants].
However, the possibility of a string argument changes the usual
pattern a bit. As one might expect:
(remove-duplicates-eq lst) is equivalent to (remove-duplicates lst
:test 'eq).
However, remove-duplicates-equal is defined without consideration of
strings, for backward compatibility with versions of ACL2 through
Version_4.2. The macro remove-duplicates-logic has been introduced
to model the behavior of remove-duplicates even on strings; use
:[pe] if you wish to see its definition. So we can say the
following.
(remove-duplicates-logic lst) is equivalent to (remove-duplicates lst
:test 'equal); and
(remove-duplicates-logic lst) is equal to (remove-duplicates-equal
lst) when lst is not a string.
In particular, when the argument is not a string, reasoning about any
of these primitives reduces to reasoning about the function
remove-duplicates-equal.
Function: <remove-duplicates-equal>
(defun remove-duplicates-equal (l)
(declare (xargs :guard (true-listp l)))
(cond ((endp l) nil)
((member-equal (car l) (cdr l))
(remove-duplicates-equal (cdr l)))
(t (cons (car l)
(remove-duplicates-equal (cdr l))))))
Remove-duplicates is defined by Common Lisp. See any Common Lisp
documentation for more information.")
(REMOVE-DUPLICATES-EQ (POINTERS)
"See [remove-duplicates].")
(REMOVE-DUPLICATES-EQUAL (POINTERS)
"See [remove-duplicates].")
(REMOVE-EQ (POINTERS) "See [remove].")
(REMOVE-EQUAL (POINTERS)
"See [remove].")
(REMOVE-INVISIBLE-FNS
(LOOP-STOPPER)
"Make some unary functions no longer invisible
Examples:
(remove-invisible-fns (binary-+ unary-- foo)
(remove-invisible-fns (+ unary-- foo)
The setting above has makes unary functions [unary--] and foo no
longer ``invisible'' for the purposes of applying permutative
:[rewrite] rules to [binary-+] trees.
General Form:
(remove-invisible-fns top-fn unary-fn1 ... unary-fnk)
where top-fn is a function symbol and the unary-fni are unary
function symbols, or more generally, these are all macro aliases
for function symbols (see [macro-aliases-table]).
See [add-invisible-fns] and also see [invisible-fns-table] and see
[set-invisible-fns-table].")
(REMOVE-MACRO-ALIAS
(MACROS)
"Remove the association of a function name with a macro name
Example:
(remove-macro-alias append)
General Form:
(remove-macro-alias macro-name)
See [macro-aliases-table] for a discussion of macro aliases; also see
[add-macro-alias]. This form sets [macro-aliases-table] to the
result of deleting the key macro-name from that [table]. If the
name does not occur in the [table], then this form still generates
an event, but the event has no real effect.")
(REMOVE-MACRO-FN
(MACROS)
"Remove the association of a function name with a macro name
Example:
(remove-macro-fn binary-append)
General Form:
(remove-macro-fn macro-fn)
See [add-macro-fn] for a discussion of how to associate a macro name
with a function name. This form sets [untrans-table] to the result
of deleting the association of a macro name with the given binary
function name. If the function name has no such association, then
this form still generates an event, but the event has no real
effect.")
(REMOVE-NTH-ALIAS
(NTH-ALIASES-TABLE)
"Remove a symbol alias for printing of [nth]/[update-nth] terms
Example:
(remove-nth-alias append)
General Form:
(remove-nth-alias alias-name)
See [nth-aliases-table] for further discussion; also see
[add-nth-alias]. This form sets [nth-aliases-table] to the result
of deleting the key alias-name from that [table]. If the name does
not occur in the [table], then this form still generates an event,
but the event has no real effect.")
(REMOVE-OVERRIDE-HINTS
(OVERRIDE-HINTS)
"Delete from the list of [override-hints]
See [override-hints] for a discussion of override-hints. Here we
describe how to delete from the list of override-hints. Note that
the effects of remove-override-hints [events] are [local] to the
[books] or encapsulate [events] in which they reside; see
[remove-override-hints!] to avoid that restriction. Also see
[add-override-hints] and see [set-override-hints].
General Form:
(remove-override-hints form)
where form should evaluate to a list of computed hint forms. The
effect of this event is to set the list of [override-hints] to the
result of deleting each element of the evaluation result from the
[override-hints], if that element indeed belongs to the
override-hints; no check is made that these elements are actually
elements of the existing override-hints.")
(REMOVE-OVERRIDE-HINTS!
(OVERRIDE-HINTS)
"Delete non-[local]ly from the list of [override-hints]
Remove-override-hints! is the same as [remove-override-hints], except
that the former is not [local] to [books] or [encapsulate] [events]
in which it occurs. See [remove-override-hints]; also see
[add-override-hints] and see [set-override-hints].")
(REMOVE-RAW-ARITY
(SET-RAW-MODE)
"Remove arity information for raw mode
Technical note: This macro is a no-op, and is not necessary, when
ACL2 is built with #-acl2-mv-as-values.
The form (remove-raw-arity fn) undoes the effect of an earlier
(remove-raw-arity fn val). See [add-raw-arity].")
(REMOVE-UNTOUCHABLE
(DEFTTAG)
"Remove names from lists of untouchable symbols
Example Forms:
(remove-untouchable my-var nil) ; then state global my-var is not untouchable
(remove-untouchable set-mem t) ; then function set-mem is not untouchable
Also see [push-untouchable].
This documentation topic is directed at those who build systems on
top of ACL2. We first describe a means for removing restrictions
related to so-called ``untouchables'': functions (or macros) that
cannot be called, or state global variables that cannot be modified
or unbound, without intervention that requires an active trust tag
(see [defttag]). Then we describe the remove-untouchable event.
We begin by discussing untouchable state global variables
temp-touchable-vars and temp-touchable-fns, which initially have
value nil. These can often be used in place of remove-untouchable.
When the value is t, no variable (respectively, no function or
macro) is treated as untouchable, regardless of the set of initial
untouchables or the remove-untouchable or [push-untouchable]
[events] that have been admitted. Otherwise the value of each of
these two variables is a [symbol-listp], and no member of this list
is treated as an untouchable variable (in the case of
temp-touchable-vars) or as an untouchable function or macro (in the
case of temp-touchable-fns). These two state global variables can
be set by set-temp-touchable-vars and set-temp-touchable-fns,
respectively, provided there is an active trust tag (see
[defttag]). Here is an illustrative example. This macro executes
the indicated forms in a context where there are no untouchable
variables, but requires an active trust tag when invoked.
(defmacro with-all-touchable (&rest forms)
`(progn!
:state-global-bindings
((temp-touchable-vars t set-temp-touchable-vars))
(progn! ,@forms)))
An equivalent version, which however is not recommended since
[state-global-let*] may have surprising behavior in raw Lisp, is as
follows.
(defmacro with-all-touchable (&rest forms)
`(progn!
(state-global-let*
((temp-touchable-vars t set-temp-touchable-vars))
(progn! ,@forms))))
Finally, the value t for temp-touchable-vars removes the requirement
that built-in state globals cannot be made unbound (with
makunbound-global).
We now turn to the remove-untouchable event, in case the approach
above is for some reason not adequate. This event is illegal by
default, since it can be used to provide access to ACL2 internal
functions and data structures that are intentionally made
untouchable for the user. If you want to call it, you must first
create an active trust tag; see [defttag].
General Form:
(remove-untouchable name{s} fn-p)
where name{s} is a non-nil symbol or a non-nil true list of symbols,
and fn-p is any value (but generally nil or t). If name{s} is a
symbol it is treated as the singleton list containing that symbol.
The effect of this event is to remove the given symbols from the
list of ``untouchable variables'' in the current world if fn-p is
nil, else to remove the symbols into the list of ``untouchable
functions''. This event is redundant if no symbol listed is a
member of the appropriate untouchables list (variables or
functions).")
(REMOVE1
(LISTS ACL2-BUILT-INS)
"Remove first occurrences, testing using [eql]
General Forms:
(remove1 x lst)
(remove1 x lst :test 'eql) ; same as above (eql as equality test)
(remove1 x lst :test 'eq) ; same, but eq is equality test
(remove1 x lst :test 'equal) ; same, but equal is equality test
(Remove1 x lst) is equal to lst if x is not a member of lst, else is
the result of removing the first occurrences of x from lst. The
optional keyword, :TEST, has no effect logically, but provides the
test (default [eql]) used for comparing x with successive elements
of lst.
Also see [remove].
The [guard] for a call of remove1 depends on the test. In all cases,
the second argument must satisfy [true-listp]. If the test is
[eql], then either the first argument must be suitable for [eql]
(see [eqlablep]) or the second argument must satisfy
[eqlable-listp]. If the test is [eq], then either the first
argument must be a symbol or the second argument must satisfy
[symbol-listp].
See [equality-variants] for a discussion of the relation between
remove1 and its variants:
(remove1-eq x lst) is equivalent to (remove1 x lst :test 'eq);
(remove1-equal x lst) is equivalent to (remove1 x lst :test 'equal).
Function: <remove1-equal>
(defun remove1-equal (x l)
(declare (xargs :guard (true-listp l)))
(cond ((endp l) nil)
((equal x (car l)) (cdr l))
(t (cons (car l)
(remove1-equal x (cdr l))))))
In particular, reasoning about any of these primitives reduces to
reasoning about the function remove1-equal.")
(REMOVE1-EQ (POINTERS) "See [remove1].")
(REMOVE1-EQUAL (POINTERS)
"See [remove1].")
(REORDER (POINTERS)
"See [hints] for keyword :reorder.")
(RESET-FC-REPORTING
(FORWARD-CHAINING-REPORTS)
"Reset the forward-chaining tracking state to its initial
configuration
Example: (reset-fc-reporting)
This function erases all forward chaining tracking criteria and sets
the on-the-fly reporting flag to nil. The next time you set the
criteria (see [set-fc-criteria]) the short form of reports, in
which only the caller and the fc-report number is printed, will
appear in your proof logs.
See [forward-chaining-reports] for details.")
(RESET-KILL-RING
(HISTORY)
"Save memory by resetting and perhaps resizing the kill ring used by
[oops]
By default, ACL2 holds on to old logical [world]s when you undo
[command]s (see [ubt]), as documented elswhere; see [oops]. You can
free up memory by deleting those old worlds using reset-kill-ring.
Examples:
(reset-kill-ring t state) ; replace each element of the kill ring by nil
(reset-kill-ring 2 state) ; create a new kill ring of '(nil nil)
(reset-kill-ring 0 state) ; create a new kill ring that is empty
(reset-kill-ring nil state) ; just return the length of the kill ring
General form:
(reset-kill-ring n state)
where n evaluates either to t, to nil, or to a nonnegative integer (a
[natp]). If n evaluates to t, it is treated as the length of the
current kill ring. If n is nil, then the length k of the current
kill ring is returned as a value triple (mv nil k state). If n is a
[natp], then the kill ring is replaced with a list of n nils.
In particular, use (reset-kill-ring 0 state) to avoid saving any old
logical [world]s, at the cost of disabling the effect of the [oops]
[command].")
(RESET-LD-SPECIALS
(LD)
"Restores initial settings of the [ld] specials
Examples:
(reset-ld-specials t)
(reset-ld-specials nil)
Roughly speaking, the [ld] specials are certain [state] global
variables, such as [current-package], [ld-prompt], and
[ld-pre-eval-filter], which are managed by [ld] as though they were
local variables. These variables determine the channels on which
[ld] reads and prints and control many options of [ld]. See [ld]
for the details on what the [ld] specials are.
This function, reset-ld-specials, takes one Boolean argument, flg.
The function resets all of the [ld] specials to their initial,
top-level values, except for the three channel variables,
[standard-oi], [standard-co], and [proofs-co], which are reset to
their initial values only if flg is non-nil. Of course, if you are
in a recursive call of [ld], then when you exit that call, the [ld]
specials will be restored to the values they had at the time [ld]
was called recursively. To see what the initial values are, inspect
the value of the constant *initial-ld-special-bindings*.")
(RESET-PREHISTORY
(HISTORY)
"Reset the prehistory
Examples:
(reset-prehistory) ; restart command numbering at 0
(reset-prehistory nil) ; same as above
(reset-prehistory t) ; as above except also disable ubt-prehistory
General Forms:
(reset-prehistory)
(reset-prehistory permanent-p)
where permanent-p is t or nil. After execution of this command, ACL2
will change the numbering provided by its [history] utilities so
that this reset-prehistory command (or the top-level compound
[command] containing it, which for example might be an
[include-book]) is assigned the number 0. The only way to undo this
command is with command [ubt-prehistory]. However, even that is
disallowed if permanent-p is t.
Note that the second argument of [certify-book], which specifies the
number of commands in the certification world (i.e., since
ground-zero), is not sensitive to reset-prehistory; rather, it
expects the number of commands since ground-zero. To see such
commands, :[pbt] :start.
A reset-prehistory event for which parameter permanent-p has the
default value of nil is always skipped when any of the following
conditions holds: during [certify-book]; during [include-book] or
the second pass of [encapsulate] (indeed, whenever [ld] special
'[ld-skip-proofsp] has value 'include-book); or when state global
'skip-reset-prehistory has a non-nil value. Thus, we avoid
resetting the history numbering to 0 when including or certifying a
book, since that would probably not be what was intended.
See [ubt-prehistory] for how to undo a reset-prehistory command that
does not have a permanent-p of t.")
(RESET-PRINT-CONTROL (POINTERS)
"See [print-control].")
(RESIZE-LIST
(STOBJ ACL2-BUILT-INS)
"List resizer in support of stobjs
(Resize-list lst n default-value) takes a list, lst, and a desired
length, n, for the result list, as well as a default-value to use
for the extra elements if n is greater than the length of lst.
Resize-list has a guard of t. This function is called in the body of
function, resize-<a> where <a> is an array field of a [stobj]. See
[stobj] and see [defstobj].
Function: <resize-list>
(defun resize-list (lst n default-value)
(declare (xargs :guard t))
(if (and (integerp n) (> n 0))
(cons (if (atom lst) default-value (car lst))
(resize-list (if (atom lst) lst (cdr lst))
(1- n)
default-value))
nil))")
(REST
(NTH ACL2-BUILT-INS)
"Rest ([cdr]) of the list
In the logic, rest is just a macro for [cdr].
Rest is a Common Lisp function. See any Common Lisp documentation for
more information.
Macro: <rest>
(defmacro rest (x) (list 'cdr x))")
(RESTORE-MEMOIZATION-SETTINGS
(MEMOIZE)
"Restore the saved memoization settings
For background on memoization, see [memoize].
General Form:
(restore-memoization-settings)
Calls of this macro restore the memoization settings saved by
[save-and-clear-memoization-settings].")
(RESTRICT (POINTERS)
"See [hints] for keyword :restrict.")
(RETRIEVE
(PROOF-CHECKER)
"Re-enter a (specified) [proof-checker] state
Examples:
(retrieve associativity-of-permutationp)
retrieve
General Form:
(retrieve &optional name)
See [ACL2-pc::retrieve], or use (help retrieve) inside the
interactive [proof-checker] loop. Also see [unsave].")
(RETURN-LAST
(BASICS ACL2-BUILT-INS)
"Return the last argument, perhaps with side effects
Return-last is an ACL2 function that returns its last argument. It is
used to implement common utilities such as [prog2$] and [time$].
For most users, this may already be more than one needs to know
about return-last; for example, ACL2 tends to avoid printing calls
of return-last in its output, printing calls of [prog2$] or [time$]
(or other such utilities) instead.
If you encounter a call of return-last during a proof, then you may
find it most useful to consider return-last simply as a function
defined by the following equation.
(equal (return-last x y z) z)
It may also be useful to know that unlike other ACL2 functions,
return-last can take a multiple value as its last argument, in
which case this multiple value is returned. The following contrived
definition illustrates this point.
ACL2 !>(defun foo (fn x y z)
(return-last fn x (mv y z)))
Since FOO is non-recursive, its admission is trivial. We observe that
the type of FOO is described by the theorem
(AND (CONSP (FOO FN X Y Z)) (TRUE-LISTP (FOO FN X Y Z))). We used
primitive type reasoning.
(FOO * * * *) => (MV * *).
Summary
Form: ( DEFUN FOO ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
FOO
ACL2 !>(foo 'bar 3 4 5)
(4 5)
ACL2 !>(mv-let (a b)
(foo 'bar 3 4 5)
(cons b a))
(5 . 4)
ACL2 !>
Most readers would be well served to avoid reading the rest of this
documentation of return-last. For reference, however, below we
document it in some detail. We include some discussion of its
evaluation, in particular its behavior in raw Lisp, because we
expect that most who read further are working with raw Lisp code
(and trust tags).
Return-last is an ACL2 function that can arise from macroexpansion of
certain utilities that return their last argument, which may be a
multiple value. Consider for example the simplest of these,
[prog2$]:
ACL2 !>:trans1 (prog2$ (cw \"Some CW printing...~%\") (+ 3 4))
(RETURN-LAST 'PROGN
(CW \"Some CW printing...~%\")
(+ 3 4))
ACL2 !>
Notice that a call of prog2$ macroexpands to a call of return-last in
which the first argument is (quote progn). Although return-last is
a function in the ACL2 world, it is implemented ``under the hood''
as a macro in raw Lisp, as the following log (continuing the
example above) illustrates.
ACL2 !>:q
Exiting the ACL2 read-eval-print loop. To re-enter, execute (LP).
? (macroexpand-1 '(RETURN-LAST 'PROGN
(CW \"Some CW printing...~%\")
(+ 3 4)))
(PROGN (LET ((*AOKP* T)) (CW \"Some CW printing...~%\")) (+ 3 4))
T
?
Thus, the original prog2$ call generates a corresponding call of
progn in raw Lisp, which in turn causes evaluation of each argument
and returns whatever is returned by evaluation of the last (second)
argument.
Remark for those who use [defattach]. The binding of *aokp* to t is
always included for the second argument as shown except when the
first argument is of the form (QUOTE M) where M is a macro, or
(less important) when the first argument is a symbol or a cons
whose car is QUOTE. This binding allows ACL2 to use attachments in
the second argument of return-last (hence, in the first argument of
[prog2$]), even in contexts such as proofs in which attachments are
normally not allowed.
In general, a form (return-last (quote F) X Y) macroexpands to (F X
Y), where F is defined in raw Lisp to return its last argument. The
case that F is progn is a bit misleading, because it is so simple.
More commonly, macroexpansion produces a call of a macro defined in
raw Lisp that may produce side effects. Consider for example the
ACL2 utility [with-guard-checking], which is intended to change the
[guard]-checking mode to the indicated value (see
[with-guard-checking]).
ACL2 !>(with-guard-checking :none (car 3)) ; no guard violation
NIL
ACL2 !>:trans1 (with-guard-checking :none (car 3))
(WITH-GUARD-CHECKING1 (CHK-WITH-GUARD-CHECKING-ARG :NONE)
(CAR 3))
ACL2 !>:trans1 (WITH-GUARD-CHECKING1 (CHK-WITH-GUARD-CHECKING-ARG :NONE)
(CAR 3))
(RETURN-LAST 'WITH-GUARD-CHECKING1-RAW
(CHK-WITH-GUARD-CHECKING-ARG :NONE)
(CAR 3))
ACL2 !>:q
Exiting the ACL2 read-eval-print loop. To re-enter, execute (LP).
? [RAW LISP] (macroexpand-1
'(RETURN-LAST 'WITH-GUARD-CHECKING1-RAW
(CHK-WITH-GUARD-CHECKING-ARG :NONE)
(CAR 3)))
(WITH-GUARD-CHECKING1-RAW (CHK-WITH-GUARD-CHECKING-ARG :NONE) (CAR 3))
T
? [RAW LISP] (pprint
(macroexpand-1
'(WITH-GUARD-CHECKING1-RAW
(CHK-WITH-GUARD-CHECKING-ARG :NONE)
(CAR 3))))
(LET ((ACL2_GLOBAL_ACL2::GUARD-CHECKING-ON
(CHK-WITH-GUARD-CHECKING-ARG :NONE)))
(DECLARE (SPECIAL ACL2_GLOBAL_ACL2::GUARD-CHECKING-ON))
(CAR 3))
? [RAW LISP]
The above raw Lisp code binds the state global variable
guard-checking-on to :none, as chk-with-guard-checking-arg is just
the identity function except for causing a hard error for an
illegal input.
The intended use of return-last is that the second argument is
evaluated first in a normal manner, and then the third argument is
evaluated in an environment that may depend on the value of the
second argument. (For example, the macro [with-prover-time-limit]
macroexpands to a call of return-last with a first argument of
'WITH-PROVER-TIME-LIMIT1-RAW, a second argument that evaluates to a
numeric time limit, and a third argument that is evaluated in an
environment where the theorem prover is restricted to avoid running
longer than that time limit.) Although this intended usage model is
not strictly enforced, it is useful to keep in mind in the
following description of how calls of return-last are handled by
the ACL2 evaluator.
When a form is submitted in the top-level loop, it is handled by
ACL2's custom evaluator. That evaluator is specified to respect the
semantics of the expression supplied to it: briefly put, if an
expression E evaluates to a value V, then the equality (equal E
(quote V)) should be a theorem. Notice that this specification does
not discuss the side-effects that may occur when evaluating a call
of return-last, so we discuss that now. Suppose that the ACL2
evaluator encounters the call (return-last 'fn expr1 expr2). First
it evaluates expr1. If this evaluation succeeds without error, then
it constructs an expression of the form (fn *x* ev-form), where *x*
is a Lisp variable bound to the result of evaluating expr1 and
ev-form is a call of the evaluator for expr2. (Those who want
implementation details are invited to look at function
ev-rec-return-last in ACL2 source file translate.lisp.) There are
exceptions if fn is progn, ec-call1-raw, with-guard-checking1-raw,
or mbe1-raw, but the main idea is the same: do a reasonable job
emulating the behavior of a raw-Lisp call of return-last.
The following log shows how a [time$] call can generate a call of the
evaluator for the last argument of return-last (arguent expr2,
above). We use :[trans1] to show single-step macroexpansions, which
indicate how a call of [time$] expands to a call of return-last.
The implementation actually binds the Lisp variable
*RETURN-LAST-ARG3* to expr2 before calling the ACL2 evaluator,
ev-rec.
ACL2 !>:trans1 (time$ (+ 3 4))
(TIME$1 (LIST 0 NIL NIL NIL NIL)
(+ 3 4))
ACL2 !>:trans1 (TIME$1 (LIST 0 NIL NIL NIL NIL)
(+ 3 4))
(RETURN-LAST 'TIME$1-RAW
(LIST 0 NIL NIL NIL NIL)
(+ 3 4))
ACL2 !>(time$ (+ 3 4))
; (EV-REC *RETURN-LAST-ARG3* ...) took
; 0.00 seconds realtime, 0.00 seconds runtime
; (1,120 bytes allocated).
7
ACL2 !>
We now show how things can go wrong in other than the ``intended
use'' case described above. In the example below, the macro mac-raw
is operating directly on the syntactic representation of its first
argument, which it obtains of course as the second argument of a
return-last call. Again this ``intended use'' of return-last
requires that argument to be evaluated and then only its result is
relevant; its syntax is not supposed to matter. We emphasize that
only top-level evaluation depends on this ``intended use''; once
evaluation is passed to Lisp, the issue disappears. We illustrate
below how to use the [top-level] utility to avoid this issue; see
[top-level]. The example uses the utility defmacro-last to
``install'' special handling of the raw-Lisp macro mac-raw by
return-last; later below we discuss defmacro-last.
ACL2 !>(defttag t)
TTAG NOTE: Adding ttag :T from the top level loop.
T
ACL2 !>(progn!
(set-raw-mode t)
(defmacro mac-raw (x y)
`(progn (print (quote ,(cadr x)))
(terpri) ; newline
,y)))
Summary
Form: ( PROGN! (SET-RAW-MODE T) ...)
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
NIL
ACL2 !>(defmacro-last mac)
[[ ... output omitted ... ]]
RETURN-LAST-TABLE
ACL2 !>(return-last 'mac-raw '3 nil)
***********************************************
************ ABORTING from raw Lisp ***********
Error: Fault during read of memory address #x120000300006
***********************************************
If you didn't cause an explicit interrupt (Control-C),
then the root cause may be call of a :program mode
function that has the wrong guard specified, or even no
guard specified (i.e., an implicit guard of t).
See :DOC guards.
To enable breaks into the debugger (also see :DOC acl2-customization):
(SET-DEBUGGER-ENABLE T)
ACL2 !>(top-level (return-last 'mac-raw '3 nil))
3
NIL
ACL2 !>
We next describe how to extend the behavior of return-last. This
requires an active trust tag (see [defttag]), and is accomplished
by extending a [table] provided by ACL2, see [return-last-table].
Rather than using [table] [events] directly for this purpose, it is
probably more convenient to use a macro, defmacro-last. We describe
the community book books/misc/profiling.lisp in order to illustrate
how this works. The events in that book include the following,
which are described below.
(defttag :profiling)
(progn!
(set-raw-mode t)
(load (concatenate 'string (cbd) \"profiling-raw.lsp\")))
(defmacro-last with-profiling)
The first event introduces a trust tag. The second loads a file into
raw Lisp that defines a macro, with-profiling-raw, which can do
profiling for the form to be evaluated. The third introduces an
ACL2 macro with-profiling, whose calls expand into calls of the
form (return-last (quote with-profiling-raw) & &). The third event
also extends [return-last-table] so that these calls will expand in
raw Lisp to calls of with-profiling-raw.
The example above illustrates the following methodology for
introducing a macro that returns its last argument but produces
useful side-effects with raw Lisp code.
(1) Introduce a trust tag (see [defttag]).
(2) Using [progn!], load into raw Lisp a file defining a macro,
RAW-NAME, that takes two arguments, returning its last (second)
argument but using the first argument to produce desired side
effects during evaluation of that last argument.
(3) Evaluate the form (defmacro-last NAME :raw RAW-NAME). This will
introduce NAME as an ACL2 macro that expands to a corresponding
call of RAW-NAME (see (2) above) in raw Lisp. The specification
of keyword value of :raw as RAW-NAME may be omitted if RAW-NAME
is the result of modifying the symbol NAME by suffixing the
string \"-RAW\" to the [symbol-name] of NAME.
WARNING: Not every use of return-last can be soundly evaluated
outside a function body. The reason is that ACL2's evaluator,
ev-rec, recurs through terms that are presented in the top-level
loop, and handles return-last calls in a special manner: basically,
the call of ev-rec on the form (return-last 'mac-raw x y) leads to
evaluation of a macro call of the form (mac-raw *return-last-arg2*
(ev-rec ...)), where *return-last-arg2* is a global variable bound
to the result of evaluating x with ev-rec. Consider the following
example.
(defttag t)
(set-raw-mode-on state)
(defmacro mac-raw (str y) ; print message is an atom
`(let ((result (consp ,y))
(str ,str))
(or result
(prog2$ (fmx ,str ',y)
nil))))
(set-raw-mode-off state)
(defmacro-last mac)
; Horrible error:
(mac \"Not a cons: ~x0~%\" 17)
; Works, but probably many would consider it awkward to use top-level:
(top-level (mac \"Not a cons: ~x0~%\" 17))
In such cases we suggest supplying keyword :top-level-ok nil to the
call of defmacro-last, for example:
(defmacro-last mac :top-level-ok nil)
Then any attempt to call mac at the top level, as opposed to inside a
function body, will cause a clean error before evaluation begins.
It is useful to explore what is done by defmacro-last.
ACL2 !>:trans1 (defmacro-last with-profiling)
(PROGN (DEFMACRO WITH-PROFILING (X Y)
(LIST 'RETURN-LAST
(LIST 'QUOTE 'WITH-PROFILING-RAW)
X Y))
(TABLE RETURN-LAST-TABLE 'WITH-PROFILING-RAW
'WITH-PROFILING))
ACL2 !>:trans1 (with-profiling '(assoc-eq fgetprop rewrite) (mini-proveall))
(RETURN-LAST 'WITH-PROFILING-RAW
'(ASSOC-EQ FGETPROP REWRITE)
(MINI-PROVEALL))
ACL2 !>:q
Exiting the ACL2 read-eval-print loop. To re-enter, execute (LP).
? [RAW LISP] (macroexpand-1
'(RETURN-LAST 'WITH-PROFILING-RAW
'(ASSOC-EQ FGETPROP REWRITE)
(MINI-PROVEALL)))
(WITH-PROFILING-RAW '(ASSOC-EQ FGETPROP REWRITE) (MINI-PROVEALL))
T
? [RAW LISP]
To understand the macro with-profiling-raw you could look at the
community book loaded above: books/misc/profiling-raw.lsp.
We mentioned above that ACL2 tends to print calls of [prog2$] or
[time$] (or other such utilities) instead of calls of return-last.
Here we elaborate that point. ACL2's `untranslate' utility treats
(return-last (quote F) X Y) as (G X Y) if F corresponds to the
symbol G in return-last-table. However, it is generally rare to
encounter such a term during a proof, since calls of return-last
are generally expanded away early during a proof.
Calls of return-last that occur in code --- forms submitted in the
top-level ACL2 loop, and definition bodies other than those marked
as [non-executable] (see [defun-nx]) --- have the following
restriction: if the first argument is of the form (quote F), then F
must be an entry in return-last-table. There are however four
exceptions: the following symbols are considered to be keys of
return-last-table even if they are no longer associated with
non-nil values, say because of a [table] event with keyword :clear.
* progn, associated with [prog2$]
* mbe1-raw, associated with mbe1, a version of mbe
* ec-call1-raw, associated with ec-call1 (a variant of [ec-call])
* with-guard-checking1-raw, associated with with-guard-checking1 (a
variant of [with-guard-checking])
Note that because of its special status, it is illegal to trace
return-last.
We conclude by warning that as a user, you take responsibility for
not compromising the soundness or error handling of ACL2 when you
define a macro in raw Lisp and especially when you install it as a
key of [return-last-table], either directly or (more likely) using
defmacro-last. In particular, be sure that you are defining a macro
of two arguments that always returns the value of its last
argument, returning the complete multiple value if that last
argument evaluates to a multiple value.
The following is correct, and illustrates care taken to return
multiple values.
:q
(defmacro my-time1-raw (val form)
(declare (ignore val))
`(let ((start-time (get-internal-run-time))
(result (multiple-value-list ,form))
(end-time (get-internal-run-time)))
(format t \"Total time: ~s~%\"
(float (/ (- end-time start-time)
internal-time-units-per-second)))
(values-list result)))
(lp)
(defttag t)
(defmacro-last my-time1)
(defmacro my-time (form)
`(my-time1 nil ,form))
Then for example:
ACL2 !>(my-time (equal (make-list 1000000) (make-list 1000000)))
Total time: 0.12
T
ACL2 !>
But if instead we provide the following more naive implementation, of
the above raw Lisp macro, the above evaluation can produce an
error, for example if the host Lisp is CCL.
(defmacro my-time1-raw (val form)
(declare (ignore val))
`(let ((start-time (get-internal-run-time))
(result ,form)
(end-time (get-internal-run-time)))
(format t \"Total time: ~s~%\"
(float (/ (- end-time start-time)
internal-time-units-per-second)))
result)) ; WRONG -- need multiple values returned!
Here is a second, similar example. This time we'll start with the
error; can you spot it?
(defttag t)
(progn!
(set-raw-mode t)
(defmacro foo-raw (x y)
`(prog1
,y
(cw \"Message showing argument 1: ~x0~%\" ,x))))
(defmacro-last foo)
We then can wind up with a hard Lisp error:
ACL2 !>(foo 3 (mv 4 5))
Message showing argument 1: 3
***********************************************
************ ABORTING from raw Lisp ***********
Error: value NIL is not of the expected type REAL.
***********************************************
If you didn't cause an explicit interrupt (Control-C),
then the root cause may be call of a :program mode
function that has the wrong guard specified, or even no
guard specified (i.e., an implicit guard of t).
See :DOC guards.
To enable breaks into the debugger (also see :DOC acl2-customization):
(SET-DEBUGGER-ENABLE T)
ACL2 !>
Here is a corrected version of the above macro. The point here is
that prog1 returns a single value, while our-multiple-value-prog1
returns all the values that are returned by its first argument.
(progn!
(set-raw-mode t)
(defmacro foo-raw (x y)
`(our-multiple-value-prog1 ;; better
,y
(cw \"Message showing argument 1: ~x0~%\" ,x))))
Function: <return-last>
(defun return-last (fn eager-arg last-arg)
(declare (ignore fn eager-arg)
(xargs :guard (if (equal fn 'mbe1-raw)
(equal last-arg eager-arg)
t)))
last-arg)
Subtopics
[Return-last-table]
Install special raw Lisp behavior")
(RETURN-LAST-TABLE
(RETURN-LAST)
"Install special raw Lisp behavior
Please first see [return-last] for relevant background.
This [table] is for advanced users only, and requires an active trust
tag (see [defttag]). We recommend that you do not modify this table
directly, but instead use the macro defmacro-last. Here we augment
that discussion with some highly technical observations that can
probably be ignored if you use defmacro-last.
This [table] has a :guard requiring that each key be a symbol defined
in raw Lisp, generally as a macro, and requiring that each non-nil
value be associated either with a symbol that names a macro defined
in ACL2, or else with a list of one element containing such a
symbol. The table can only be modified when there is an active
trust tag; see [defttag]. If a key is associated with the value
nil, then that key is treated as though it were not in the table.
Note that keys of this table are not eligible to be bound by [flet].
The current value of this table may be obtained by evaluating the
form (table-alist 'return-last-table (w state)). The built-in
constant *initial-return-last-table* holds the initial value of
this table.")
(REVAPPEND
(LISTS ACL2-BUILT-INS)
"Concatentate the [reverse] of one list to another
(Revappend x y) [concatenate]s the [reverse] of the list x to y,
which is also typically a list.
The following theorem characterizes this English description.
(equal (revappend x y)
(append (reverse x) y))
Hint: This lemma follows immediately from the definition of [reverse]
and the following lemma.
(defthm revappend-append
(equal (append (revappend x y) z)
(revappend x (append y z))))
The [guard] for (revappend x y) requires that x is a true list.
Revappend is defined in Common Lisp. See any Common Lisp
documentation for more information.
Function: <revappend>
(defun revappend (x y)
(declare (xargs :guard (true-listp x)))
(if (endp x)
y (revappend (cdr x) (cons (car x) y))))")
(REVERSE
(LISTS STRINGS ACL2-BUILT-INS)
"Reverse a list or string
(Reverse x) is the result of reversing the order of the elements of
the list or string x.
The [guard] for reverse requires that its argument is a true list or
a string.
Reverse is defined in Common Lisp. See any Common Lisp documentation
for more information.
Function: <reverse>
(defun reverse (x)
(declare (xargs :guard (or (true-listp x) (stringp x))))
(cond ((stringp x)
(coerce (revappend (coerce x 'list) nil)
'string))
(t (revappend x nil))))")
(REVISITING_THE_ADMISSION_OF_APP
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Revisiting the Admission of App
[{IMAGE}]
Here is the definition of app again with certain parts highlighted.
If you are taking the Walking Tour, please read the text carefully
and click on each of the links below, except those marked [{ICON}].
Then come back here.
{IMAGE}
[ACL2 !>](defun app (x y)
(cond ((endp x) y)
(t (cons (car x)
(app (cdr x) y)))))
The [admission] of APP is trivial, using the
relation [o<] [{ICON}] (which is known to be well-founded on
the domain recognized by [o-p] [{ICON}]) and the measure
([ACL2-count] [{ICON}] X). We [observe] that the
[type] of APP is described by the theorem (OR
(CONSP (APP X Y)) (EQUAL (APP X Y) Y)). We used primitive type
reasoning.
[Summary]
Form: ( DEFUN APP ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: None
Time: 0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
APP
{IMAGE}
[{IMAGE}]")
(REWRITE
(RULE-CLASSES)
"Make some :rewrite rules (possibly conditional ones)
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
This doc topic discusses the rule-class :rewrite. If you want a
general discussion of how rewriting works in ACL2 and some guidance
on how to construct effective rewrite rules, see
[introduction-to-rewrite-rules-part-1] and then see
[introduction-to-rewrite-rules-part-2].
Examples:
(defthm plus-commutes ; Replace (+ a b) by (+ b a) provided
(equal (+ x y) (+ y x))) ; certain heuristics approve the
; permutation.
(defthm plus-commutes ; equivalent to the above
(equal (+ x y) (+ y x))
:rule-classes ((:rewrite :corollary (equal (+ x y) (+ y x))
:loop-stopper ((x y binary-+))
:match-free :all)))
(defthm append-nil ; Replace (append a nil) by a, if
(implies (true-listp x) ; (true-listp a) rewrites to t.
(equal (append x nil) x)))
(defthm append-nil ; as above, but with defaults and
(implies (true-listp x) ; a backchain limit
(equal (append x nil) x))
:rule-classes ((:rewrite :corollary (implies (true-listp x)
(equal (append x nil) x))
:backchain-limit-lst (3) ; or equivalently, 3
:match-free :all)))
(defthm member-append ; Replace (member e (append b c)) by
(implies ; (or (member e b) (member e c) in
(and ; contexts in which propositional
(true-listp x) ; equivalence is sufficient, provided
(true-listp y)) ; b and c are true-lists.
(iff (member e (append x y))
(or (member e x) (member e y)))))
General Form:
(and ...
(implies (and ...hi...)
(implies (and ...hk...)
(and ...
(equiv lhs rhs)
...)))
...)
Note: One :rewrite rule class object might create many rewrite rules
from the :[corollary] formula. To create the rules, we first
translate the formula, expanding all macros (see [trans]) and also
removing [guard-holders]. Next, we eliminate all lambdas; one may
think of this step as simply substituting away every [let], [let*],
and [mv-let] in the formula. We then flatten the [and] and
[implies] structure of the formula; for example, if the hypothesis
or conclusion is of the form (and (and term1 term2) term3), then we
replace that by the ``flat'' term (and term1 term2 term3). (The
latter is actually an abbreviation for the right-associated term
(and term1 (and term2 term3)).) The result is a conjunction of
formulas, each of the form
(implies (and h1 ... hn) concl)
where no hypothesis is a conjunction and concl is neither a
conjunction nor an implication. If necessary, the hypothesis of
such a conjunct may be vacuous. We then further coerce each concl
into the form (equiv lhs rhs), where equiv is a known [equivalence]
relation, by replacing any concl not of that form by (iff concl t).
A concl of the form (not term) is considered to be of the form (iff
term nil). By these steps we reduce the given :[corollary] to a
sequence of conjuncts, each of which is of the form
(implies (and h1 ... hn)
(equiv lhs rhs))
where equiv is a known [equivalence] relation. See [equivalence] for
a general discussion of the introduction of new [equivalence]
relations. At this point, we check whether lhs and rhs are the same
term; if so, we cause an error, since this rule will loop. (But
this is just a basic check; the rule could loop in other cases, for
example if rhs is an instance of lhs; see [loop-stopper].)
We create a :rewrite rule for each such conjunct, if possible, and
otherwise cause an error. It is possible to create a rewrite rule
from such a conjunct provided lhs is not a variable, a quoted
constant, a [let]-expression, a lambda application, or an
[if]-expression.
A :rewrite rule is used when any instance of the lhs occurs in a
context in which the [equivalence] relation is an admissible
[congruence] relation. First, we find a substitution that makes lhs
equal to the target term. Then we attempt to relieve the
instantiated hypotheses of the rule. Hypotheses that are fully
instantiated are relieved by recursive rewriting. Hypotheses that
contain ``free variables'' (variables not assigned by the unifying
substitution) are relieved by attempting to guess a suitable
instance so as to make the hypothesis equal to some known
assumption in the context of the target. If the hypotheses are
relieved, and certain restrictions that prevent some forms of
infinite regress are met (see [loop-stopper]), the target is
replaced by the instantiated rhs, which is then recursively
rewritten.
ACL2's rewriting process has undergone some optimization. In
particular, when a term t1 is rewritten to a new term t2, the
rewriter is then immediately applied to t2. On rare occasions you
may find that you do not want this behavior, in which case you may
wish to use a trick involving [hide]; see [meta], near the end of
that documentation.
In another optimization, when the hypotheses and right-hand side are
rewritten, ACL2 does not really first apply the substitution and
then rewrite; instead, it as it rewrites those terms it looks up
the already rewritten values of the bound variables. Sometimes you
may want those bindings rewritten again, e.g., because the
variables occur in slots that admit additional equivalence
relations. See double-rewrite.
See [introduction-to-rewrite-rules-part-1] and see
[introduction-to-rewrite-rules-part-2] for an extended discussion
of how to create effective rewrite rules.
Subtopics
[Backchain-limit]
Limiting the effort expended on relieving hypotheses
[Bind-free]
To bind free variables of a rewrite, definition, or linear rule
[Case-split]
Like force but immediately splits the top-level goal on the
hypothesis
[Double-rewrite]
Cause a term to be rewritten twice
[Force]
Identity function used to force a hypothesis
[Free-variables]
Free variables in rules
[Hide]
Hide a term from the rewriter
[Loop-stopper]
Limit application of permutative rewrite rules
[Rewrite-stack-limit]
Limiting the stack depth of the ACL2 rewriter
[Set-rw-cache-state]
Set the default rw-cache-state
[Set-rw-cache-state!]
Set the default rw-cache-state non-[local]ly
[Simple]
:[definition] and :[rewrite] rules used in preprocessing
[Syntaxp]
Attach a heuristic filter on a rule")
(REWRITE-STACK-LIMIT
(REWRITE)
"Limiting the stack depth of the ACL2 rewriter
ACL2 users can create rules of class :[rewrite] (see [rule-classes])
that have the potential of causing an infinite loop in the ACL2
rewriter. This could lead to Lisp stack overflows and even
segmentation faults. For this reason, the depth of certain calls of
functions in the ACL2 rewriter is limited by default using the
value of the form (rewrite-stack-limit (w state)). To see the limit
in action, execute the following forms.
(defthm app-assoc-1
(equal (append (append x y) z)
(append x y z)))
(defthm app-assoc-2
(equal (append x y z)
(append (append x y) z)))
(thm (equal (append a b c) xxx)
; try without these hints to see a slightly different error message
:hints ((\"Goal\" :do-not '(preprocess))))
The ensuing error message shows a stack of one greater than the value
of (rewrite-stack-limit (w state)), which by default is the value
of the constant *default-rewrite-stack-limit*. The error message
also explains how to use :[brr] t and ([cw-gstack]) to find looping
rewrite rules.
This limit can be changed; see [set-rewrite-stack-limit].
For a related limit, see [backchain-limit].
Subtopics
[Set-rewrite-stack-limit]
Sets the rewrite stack depth used by the rewriter")
(REWRITE_RULES_ARE_GENERATED_FROM_DEFTHM_EVENTS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Rewrite Rules are Generated from DEFTHM Events
[{IMAGE}]
By reading the documentation of [defthm] [{ICON}] (and especially of
its :[rule-classes] [{ICON}] argument) you would learn that when we
submitted the command
(defthm associativity-of-app
(equal (app (app a b) c)
(app a (app b c))))
we not only command the system to prove that app is an associative
function but
* we commanded it to use that fact as a rewrite rule.
That means that every time the system encounters a term of the form
(app (app x y) z)
it will replace it with
(app x (app y z))!
[{IMAGE}]")
(RFIX
(NUMBERS ACL2-BUILT-INS)
"Coerce to a rational number
Rfix simply returns any rational number argument unchanged, returning
0 on a non-rational argument. Also see [nfix], see [ifix], see
[realfix], and see [fix] for analogous functions that coerce to a
natural number, an integer, a real, and a number, respectively.
Rfix has a [guard] of t.
Function: <rfix>
(defun rfix (x)
(declare (xargs :guard t))
(if (rationalp x) x 0))")
(ROUND
(NUMBERS ACL2-BUILT-INS)
"Division returning an integer by rounding off
Example Forms:
ACL2 !>(round 14 3)
5
ACL2 !>(round -14 3)
-5
ACL2 !>(round 14 -3)
-5
ACL2 !>(round -14 -3)
5
ACL2 !>(round 13 3)
4
ACL2 !>(round -13 3)
-4
ACL2 !>(round 13 -3)
-4
ACL2 !>(round -13 -3)
4
ACL2 !>(round -15 -3)
5
ACL2 !>(round 15 -2)
-8
(Round i j) is the result of taking the quotient of i and j and
rounding off to the nearest integer. When the quotient is exactly
halfway between consecutive integers, it rounds to the even one.
The [guard] for (round i j) requires that i and j are rational
([real], in ACL2(r)) numbers and j is non-zero.
Round is a Common Lisp function. See any Common Lisp documentation
for more information. However, note that unlike Common Lisp, the
ACL2 round function returns only a single value,
Function: <round>
(defun
round (i j)
(declare (xargs :guard (and (real/rationalp i)
(real/rationalp j)
(not (eql j 0)))))
(let ((q (* i (/ j))))
(cond ((integerp q) q)
((>= q 0)
(let* ((fl (floor q 1)) (remainder (- q fl)))
(cond ((> remainder 1/2) (+ fl 1))
((< remainder 1/2) fl)
(t (cond ((integerp (* fl (/ 2))) fl)
(t (+ fl 1)))))))
(t (let* ((cl (ceiling q 1))
(remainder (- q cl)))
(cond ((< (- 1/2) remainder) cl)
((> (- 1/2) remainder) (+ cl -1))
(t (cond ((integerp (* cl (/ 2))) cl)
(t (+ cl -1))))))))))")
(RULE-CLASSES
(ACL2)
"Adding rules to the database
Example Form (from community book finite-set-theory/total-ordering.lisp):
(defthm <<-trichotomy
(implies (and (ordinaryp x)
(ordinaryp y))
(or (<< x y)
(equal x y)
(<< y x)))
:rule-classes
((:rewrite :corollary
(implies (and (ordinaryp x)
(ordinaryp y)
(not (<< x y))
(not (equal x y)))
(<< y x)))))
General Form:
a true list of rule class objects as defined below
Special Cases:
a symbol abbreviating a single rule class object
When [defthm] is used to prove a named theorem, rules may be derived
from the proved formula and stored in the database. The user
specifies which kinds of rules are to be built, by providing a list
of rule class names or, more generally, rule class objects, which
name the kind of rule to build and optionally specify various
attributes of the desired rule. The rule class names are
:[rewrite], :[built-in-clause], :[clause-processor],
:[compound-recognizer], :[congruence], :[definition], :[elim],
:[equivalence], :[forward-chaining], :[generalize], :[induction],
:[linear], :[meta], :[refinement], :[tau-system],
:[type-prescription], :[type-set-inverter], and
:[well-founded-relation]. Some classes require the
user-specification of certain class-specific attributes. Each class
of rule affects the theorem prover's behavior in a different way,
as discussed in the corresponding documentation topic. In this
topic we discuss the various attributes that may be attached to
rule classes.
Note that not all [events] generate rules. For example, a [defthm]
event that specifies :rule-classes nil does not generate a rule.
Similarly, a [defchoose] event generates an axiom that can be
referenced by name in :use [hints], but it does not generate a
rule.
A rule class object is either one of the :class keywords or else is a
list of the form shown below. Those fields marked with ``(!)'' are
required when the :class is as indicated.
(:class
:COROLLARY term
:TRIGGER-FNS (fn1 ... fnk) ; provided :class = :META (!)
:WELL-FORMEDNESS-GUARANTEE x ; provided :class = :META
or :class = :CLAUSE-PROCESSOR
:TRIGGER-TERMS (t1 ... tk) ; provided :class = :FORWARD-CHAINING
; or :class = :LINEAR
:TYPE-SET n ; provided :class = :TYPE-SET-INVERTER
:TYPED-TERM term ; provided :class = :TYPE-PRESCRIPTION
:CLIQUE (fn1 ... fnk) ; provided :class = :DEFINITION
:CONTROLLER-ALIST alist ; provided :class = :DEFINITION
:INSTALL-BODY directive ; provided :class = :DEFINITION
:LOOP-STOPPER alist ; provided :class = :REWRITE
:PATTERN term ; provided :class = :INDUCTION (!)
:CONDITION term ; provided :class = :INDUCTION
:SCHEME term ; provided :class = :INDUCTION (!)
:MATCH-FREE all-or-once ; provided :class = :REWRITE
; or :class = :LINEAR
; or :class = :FORWARD-CHAINING
:BACKCHAIN-LIMIT-LST limit ; provided :class = :REWRITE
; or :class = :META
; or :class = :LINEAR
; or :class = :TYPE-PRESCRIPTION
:HINTS hints ; provided instrs = nil
:INSTRUCTIONS instrs ; provided hints = nil
:OTF-FLG flg)
When rule class objects are provided by the user, most of the fields
are optional and their values are computed in a context sensitive
way. When a :class keyword is used as a rule class object, all
relevant fields are determined contextually. Each rule class object
in :rule-classes causes one or more rules to be added to the
database. The :class keywords are documented individually under the
following names. Note that when one of these names is used as a
:class, it is expected to be in the keyword package (i.e., the
names below should be preceded by a colon but the ACL2
[documentation] facilities do not permit us to use keywords below).
See also [force], [case-split], [syntaxp], and [bind-free] for
``pragmas'' one can wrap around individual hypotheses of certain
classes of rules to affect how the hypothesis is relieved.
Before we get into the discussion of rule classes, let us return to
an important point. In spite of the large variety of rule classes
available, at present we recommend that new ACL2 users rely almost
exclusively on (conditional) rewrite rules. A reasonable but
slightly bolder approach is to use :[type-prescription] and
:[forward-chaining] rules for ``type-theoretic'' rules, especially
ones whose top-level function symbol is a common one like
[true-listp] or [consp]; see [type-prescription] and see
[forward-chaining]. However, the rest of the rule classes are
really not intended for widespread use, but rather are mainly for
experts.
We expect that we will write more about the question of which kind of
rule to use. For now: when in doubt, use a :[rewrite] rule.
:Rule-classes is an optional keyword argument of the [defthm] (and
[defaxiom]) event. In the following, let name be the name of the
event and let thm be the formula to be proved or added as an axiom.
If :rule-classes is not specified in a [defthm] (or [defaxiom])
event, it is as though what was specified was to make one or more
:[rewrite] rules, i.e., as though :rule-classes ((:rewrite)) had
been used. Use :rule-classes nil to specify that no rules are to be
generated.
If :rule-classes class is specified, where class is a non-nil symbol,
it is as though :rule-classes ((class)) had been used. Thus,
:rule-classes :[forward-chaining] is equivalent to :rule-classes
((:forward-chaining)).
We therefore now consider :rule-classes as a true list. If any
element of that list is a keyword, replace it by the singleton list
containing that keyword. Thus, :rule-classes (:rewrite :elim) is
the same as :rule-classes ((:rewrite) (:elim)).
Each element of the expanded value of :rule-classes must be a true
list whose [car] is one of the rule class keyword tokens listed
above, e.g., :[rewrite], :[elim], etc., and whose [cdr] is a
``keyword alist'' alternately listing keywords and values. The
keywords in this alist must be taken from those shown below. They
may be listed in any order and most may be omitted, as specified
below.
:[Corollary] --- its value, term, must be a term. If omitted, this
field defaults to thm. The :[corollary] of a rule class object
is the formula actually used to justify the rule created and
thus determines the form of the rule. Nqthm provided no similar
capability: each rule was determined by thm, the theorem or
axiom added. ACL2 permits thm to be stated ``elegantly'' and
then allows the :[corollary] of a rule class object to specify
how that elegant statement is to be interpreted as a rule. For
the rule class object to be well-formed, its (defaulted)
:[corollary], term, must follow from thm. Unless term follows
trivially from thm using little more than propositional logic,
the formula (implies thm term) is submitted to the theorem
prover and the proof attempt must be successful. During that
proof attempt the values of :[hints], :[instructions], and
:[otf-flg], as provided in the rule class object, are provided
as arguments to the prover. Such auxiliary proofs give the sort
of output that one expects from the prover. However, as noted
above, corollaries that follow trivially are not submitted to
the prover; thus, such corollaries cause no prover output.
Note that before term is stored, all calls of macros in it are
expanded away. See [trans].
:[Hints], :[instructions], :[otf-flg] --- the values of these fields
must satisfy the same restrictions placed on the fields of the
same names in [defthm]. These values are passed to the
recursive call of the prover used to establish that the
:[corollary] of the rule class object follows from the theorem
or axiom thm.
:[Type-set] --- this field may be supplied only if the :class is
:[type-set-inverter]. When provided, the value must be a
type-set, an integer in a certain range. If not provided, an
attempt is made to compute it from the corollary. See
[type-set-inverter].
:Typed-term --- this field may be supplied only if the :class is
:[type-prescription]. When provided, the value is the term for
which the :[corollary] is a type-prescription lemma. If no
:typed-term is provided in a :[type-prescription] rule class
object, we try to compute heuristically an acceptable term. See
[type-prescription].
:Trigger-terms --- this field may be supplied only if the :class is
:[forward-chaining] or :[linear]. When provided, the value is a
list of terms, each of which is to trigger the attempted
application of the rule. If no :trigger-terms is provided, we
attempt to compute heuristically an appropriate set of
triggers. See [forward-chaining] or see [linear].
:Trigger-fns --- this field must (and may only) be supplied if the
:class is :[meta]. Its value must be a list of function symbols
(except that a macro alias can stand in for a function symbol;
see [add-macro-alias]). Terms with these symbols trigger the
application of the rule. See [meta].
:Well-formedness-guarantee --- this field may be supplied only if the
:class is :[meta] or :[clause-processor]. Its value must be of
one of the following forms:
[1] thm-name1 ; :META or :CLAUSE-PROCESSOR rules
[2] (thm-name1) ; :META rules
[3] (thm-name1 thm-name2) ; :META rules
where thm-name1 and thm-name2 are the names of previously proved
theorems establishing that the results of applying the
metafunction(s) or clause-processor will be syntactically
well-formed. See :[meta] and :[clause-processor] for details of
the required forms of these well-formedness theorems. Forms [1]
and [2] may be used for :meta rules where no hypothesis
metafunction is involved. Form [3] must be used for :meta rules
with hypothesis metafunctions; that is, if you provide a
well-formedness guarantee for a metatheorem with a hypothesis
metafunction you must guarantee the well-formedness of both the
metafunction (with thm-name1) and the hypothesis metafunction
(with thm-name2). Form [1] must be used for :clause-processor
rules. In the absence of a proper :well-formedness-guarantee
the well-formedness of the output of a both kinds of rules is
checked every time the rule is fired. These checks are skipped
when a proper :well-formedness-guarantee is provided or when
overridden as described in [set-skip-meta-termp-checks].
:Clique and :controller-alist --- these two fields may only be
supplied if the :class is :[definition]. If they are omitted,
then ACL2 will attempt to guess them. Suppose the :[corollary]
of the rule is (implies hyp (equiv (fn a1 ... an) body)). The
value of the :clique field should be a true list of function
symbols, and if non-nil must include fn. These symbols are all
the members of the mutually recursive clique containing this
definition of fn. That is, a call of any function in :clique is
considered a ``recursive call'' for purposes of the expansion
heuristics. The value of the :controller-alist field should be
an alist that maps each function symbol in the :clique to a
list of t's and nil's of length equal to the arity of the
function. For example, if :clique consists of just two symbols,
fn1 and fn2, of arities 2 and 3 respectively, then ((fn1 t nil)
(fn2 nil t t)) is a legal value of :controller-alist. The value
associated with a function symbol in this alist is a ``mask''
specifying which argument slots of the function ``control'' the
recursion for heuristic purposes. Sloppy choice of :clique or
:controller-alist can result in infinite expansion and stack
overflow.
:Install-body --- this field may only be supplied if the :class is
:[definition]. Its value must be t, nil, or the default,
:normalize. A value of t or :normalize will cause ACL2 to
install this rule as the new body of the function being
``defined'' (fn in the paragraph just above); hence this
definition will be installed for future :expand [hints].
Furthermore, if this field is omitted or the value is
:normalize, then this definition will be simplified using the
so-called ``normalization'' procedure that is used when
processing definitions made with [defun]. You must explicitly
specify :install-body nil in the following cases: fn (as above)
is a member of the value of constant
*definition-minimal-theory*, the arguments are not a list of
distinct variables, equiv (as above) is not [equal], or there
are free variables in the hypotheses or right-hand side (see
[free-variables]). However, supplying :install-body nil will
not affect the rewriter's application of the :definition rule,
other than to avoid using the rule to apply :expand hints. If a
definition rule equates (f a1 ... ak) with body but there are
hypotheses, hyps, then :expand [hints] will replace terms (f
term1 ... termk) by corresponding terms (if hyps body (hide (f
term1 ... termk))).
:[Loop-stopper] --- this field may only be supplied if the class is
:[rewrite]. Its value must be a list of entries each consisting
of two variables followed by a (possibly empty) list of
function symbols, for example ((x y binary-+) (u v foo bar)).
It will be used to restrict application of rewrite rules by
requiring that the list of instances of the second variables
must be ``smaller'' than the list of instances of the first
variables in a sense related to the corresponding functions
listed; see [loop-stopper]. The list as a whole is allowed to
be nil, indicating that no such restriction shall be made. Note
that any such entry that contains a variable not being
instantiated, i.e., not occurring on the left side of the
rewrite rule, will be ignored. However, for simplicity we
merely require that every variable mentioned should appear
somewhere in the corresponding :[corollary] formula.
:Pattern, :Condition, :Scheme --- the first and last of these fields
must (and may only) be supplied if the class is :[induction].
:Condition is optional but may only be supplied if the class is
:[induction]. The values must all be terms and indicate,
respectively, the pattern to which a new induction scheme is to
be attached, the condition under which the suggestion is to be
made, and a term which suggests the new scheme. See
[induction].
:Match-free --- this field must be :all or :once and may be supplied
only if the :class is either :[rewrite], :[linear], or
:[forward-chaining]. (This field is not implemented for other
rule classes, including the :[type-prescription] rule class.)
See [free-variables] for a description of this field. Note:
Although this field is intended to be used for controlling
retries of matching free variables in hypotheses, it is legal
to supply it even if there are no such free variables. This can
simplify the automated generation of rules, but note that when
:match-free is supplied, the warning otherwise provided for the
presence of free variables in hypotheses will be suppressed.
:Backchain-limit-lst --- this field may be supplied only if the
:class is either :[rewrite], :[meta], :[linear], or
:[type-prescription]. It is further required either only one
rule is generated from the formula or, at least, every such
rule has the same list of hypotheses. The value for
:backchain-limit-lst must be nil; a non-negative integer; or,
except in the case of :[meta] rules, a true list each element
of which is either nil or a non-negative integer. If it is a
list, its length must be equal to the number of hypotheses of
the rule and each item in the list is the ``backchain limit''
associated with the corresponding hypothesis. If
backchain-limit-lst is a non-negative integer, it is defaulted
to a list of the appropriate number of repetitions of that
integer. The backchain limit of a hypothesis is used to limit
the effort that ACL2 will expend when relieving the hypothesis.
If it is NIL, no new limits are imposed; if it is an integer,
the hypothesis will be limited to backchaining at most that
many times. Note that backchaining may be further limited by a
global backchain-limit; see [backchain-limit] for details. For
different ways to reign in the rewriter, see
[rewrite-stack-limit] and see [set-prover-step-limit]. Jared
Davis has pointed out that you can set the :backchain-limit-lst
to 0 to avoid any attempt to relieve [force]d hypotheses, which
can lead to a significant speed-up in some cases.
Once thm has been proved (in the case of [defthm]) and each rule
class object has been checked for well-formedness (which might
require additional proofs), we consider each rule class object in
turn to generate and add rules. Let :class be the class keyword
token of the ith class object (counting from left to right).
Generate the [rune] (:class name . x), where x is nil if there is
only one class and otherwise x is i. Then, from the :[corollary] of
that object, generate one or more rules, each of which has the name
(:class name . x). See the :[doc] entry for each rule class to see
how formulas determine rules. Note that it is in principle possible
for several rules to share the same name; it happens whenever a
:[corollary] determines more than one rule. This in fact only
occurs for :[rewrite], :[linear], and :[forward-chaining] class
rules and only then if the :[corollary] is essentially a
conjunction. (See the documentation for [rewrite], [linear], or
[forward-chaining] for details.)
Subtopics
[Backchaining]
Attempting to relieve the hypotheses of a rule
[Built-in-clause]
To build a clause into the simplifier
[Clause-processor]
Make or apply a :clause-processor rule (goal-level simplifier)
[Compound-recognizer]
Make a rule used by the typing mechanism
[Congruence]
The relations to maintain while simplifying arguments
[Corollary]
The corollary formula of a [rune]
[Default-backchain-limit]
Specifying the backchain limit for a rule
[Definition]
Make a rule that acts like a function definition
[Elim]
Make a destructor elimination rule
[Equivalence]
Mark a relation as an equivalence relation
[Executable-counterpart]
A rule for computing the value of a function
[Forward-chaining]
Make a rule to forward chain when a certain trigger arises
[Free-variables]
Free variables in rules
[Generalize]
Make a rule to restrict generalizations
[Guard-holders]
Remove trivial calls from a [term]
[Induction]
Make a rule that suggests a certain induction
[Linear]
Make some arithmetic inequality rules
[Meta]
Make a :meta rule (a hand-written simplifier)
[Patterned-congruence]
Removing restrictions on classic [congruence] rules
[Refinement]
Record that one equivalence relation refines another
[Rewrite]
Make some :rewrite rules (possibly conditional ones)
[Tau-system]
Make a rule for the ACL2 ``type checker''
[Type-prescription]
Make a rule that specifies the type of a term
[Type-set-inverter]
Exhibit a new decoding for an ACL2 type-set
[Well-formedness-guarantee]
Guarantee that a metafunction or clause-processor returns a
well-formed answer
[Well-founded-relation]
Show that a relation is well-founded on a set")
(RULE-NAMES
(THEORIES)
"How rules are named.
Examples:
(:rewrite assoc-of-app)
(:linear delta-aref . 2)
(:definition length)
(:executable-counterpart length)
See [rune].")
(RULER-EXTENDERS
(DEFUN)
"Control for ACL2's termination and induction analyses
Introduction
Consider the following recursive definition, which returns a list of
threes of length one more than the length of x.
(defun f (x)
(cons 3
(if (consp x)
(f (cdr x))
nil)))
One might expect ACL2's termination analysis to admit this function,
since we know that (cdr x) is ``smaller'' than x if (consp x) is
true. (By default, ACL2's notion of ``smaller'' is ordinary
natural-number <, and the argument x is measured by applying
function acl2-count to x.) However, that termination analysis does
not consider [if] tests, like (consp x) above, when they occur
under calls of functions other than IF, such as CONS in the case
above.
One way to overcome this problem is to ``lift'' the IF test to the
top level, as follows.
(defun f (x)
(if (consp x)
(cons 3 (f (cdr x)))
(cons 3 nil)))
But another way to overcome the problem is to tell ACL2 to extend its
termination (and induction) analysis through calls of cons, as
follows.
(defun f (x)
(declare (xargs :ruler-extenders (cons)))
(cons 3
(if (consp x)
(f (cdr x))
nil)))
You may even wish to provide value :all instead of an explicit list
of ruler-extenders, so that no function call blocks the termination
analysis:
(defun f (x)
(declare (xargs :ruler-extenders :all))
(cons 3
(if (consp x)
(f (cdr x))
nil)))
Alternatively, you can omit the XARGS :RULER-EXTENDERS form, instead
modifying the global default set of ruler-extenders:
(set-ruler-extenders :all)
; or, for example:
(set-ruler-extenders '(cons return-last))
You can call the function [default-ruler-extenders] as follows to see
the current global default set of ruler-extenders:
(default-ruler-extenders (w state))
We conclude this introduction by considering the handling of LET
expressions by termination analysis. Consider the following
example.
(defun fact (n)
(the (integer 1 *)
(if (posp n)
(* n (fact (1- n)))
1)))
ACL2 treats the call of [the] in the body of this definition as
follows.
(let ((var (if (posp n)
(* n (fact (1- n)))
1)))
(if (and (integerp var) (<= 1 var))
var
<some_error>))
A [let] expression, in turn, is treated as a [lambda] application:
((lambda (var)
(if (if (integerp var)
(not (< var 1))
nil)
var
<some_error>))
(if (posp n)
(* n (fact (1- n)))
1))
Notice that the [posp] test, which governs the recursive call of
fact, is inside an argument of a function application, namely the
application of the LAMBDA expression. So by default, ACL2 will not
consider this [posp] test in its termination analysis. The keyword
:LAMBDAS in the list of ruler-extenders denotes all calls of lambda
expressions, much as the inclusion of CONS in the ruler-extenders
denotes all calls of CONS. The following definition is thus
accepted by ACL2.
(defun fact (n)
(declare (xargs :ruler-extenders (:lambdas)))
(the (integer 1 *)
(if (posp n)
(* n (fact (1- n)))
1)))
As a convenience, ACL2 allows the symbol :lambdas in place of
(:lambdas), and in fact the former will also include the default
ruler-extenders: [return-last] (which comes from macroexpansion of
calls of [prog2$], [ec-call], and others) and [mv-list].
IMPORTANT REMARKS. (1) Notice that the argument to
set-ruler-extenders is evaluated, but the argument to
:RULER-EXTENDERS in XARGS is not evaluated. (2) Do not put macro
names in your list of ruler-extenders. For example, if you intend
that + should not block the termination analysis, in analogy to
cons in the example above, then the list of ruler-extenders should
include binary-+, not +. Of course, if you use :all then this is
not an issue, but see the next remark. (3) Also please note that by
taking advantage of the ruler-extenders, you may be complicating
the induction scheme stored for the function, whose computation
takes similar advantage of the additional IF structure that you are
specifying.
Below we describe the notion of ruler-extenders in detail, as well as
how to set its default using set-ruler-extenders.
Details
We begin by discussing how to set the ruler-extenders by using the
macro set-ruler-extenders; below we will discuss the use of keyword
:ruler-extenders in [xargs] [declare] forms.
Examples:
(set-ruler-extenders :basic) ; return to default
(set-ruler-extenders *basic-ruler-extenders*) ; same as immediately above
(set-ruler-extenders :all) ; every governing IF test rules a recursive call
(set-ruler-extenders :lambdas) ; LET does not block termination analysis
(set-ruler-extenders (cons :lambdas *basic-ruler-extenders*))
; same as immediately above
(set-ruler-extenders '(f g)) ; termination analysis goes past calls of f, g
General Form:
(set-ruler-extenders val)
where val evaluates to one of :basic, :all, :lambdas, or a true list
of symbols containing no keyword other than, optionally, :lambdas.
When a recursive definition is submitted to ACL2 (in :[logic] mode),
the recursion must be proved to terminate; see [defun]. More
precisely, ACL2 explores the [if] structure of the body of the
definition to accumulate the tests that ``rule'' any given
recursive call. The following example reviews how this works.
Suppose that f has already been defined.
(defun g (x y)
(declare (xargs :measure (+ (acl2-count x) (acl2-count y))))
(if (consp x)
(g (cdr x) y)
(if (consp y)
(f (g x (cdr y)))
(f (list x y)))))
ACL2 makes the following response to this proposed definition. Notice
that the :measure proposed above must be proved to be an ACL2
ordinal --- that is, to satisfy O-P --- and that the arguments to
each recursive call must be smaller (in the sense of that measure
and O<, which here reduces to the ordinary < relation) than the
formals under the assumption of the ruling IF tests. The first
IMPLIES term below thus corresponds to the recursive call (g (cdr
x) y), while the second corresponds to the recursive call (g x (cdr
y)).
For the admission of G we will use the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(+ (ACL2-COUNT X) (ACL2-COUNT Y)). The non-trivial part of the measure
conjecture is
Goal
(AND (O-P (+ (ACL2-COUNT X) (ACL2-COUNT Y)))
(IMPLIES (CONSP X)
(O< (+ (ACL2-COUNT (CDR X)) (ACL2-COUNT Y))
(+ (ACL2-COUNT X) (ACL2-COUNT Y))))
(IMPLIES (AND (NOT (CONSP X)) (CONSP Y))
(O< (+ (ACL2-COUNT X) (ACL2-COUNT (CDR Y)))
(+ (ACL2-COUNT X) (ACL2-COUNT Y))))).
Now consider the following alternate version of the above definition.
(defun g (x y)
(declare (xargs :measure (+ (acl2-count x) (acl2-count y))))
(if (consp x)
(g (cdr x) y)
(f (if (consp y)
(g x (cdr y))
(list x y)))))
The first test, (consp x), still rules the first recursive call, (g
(cdr x) y). And the negation of that test, namely (not (consp x)),
still rules the second recursive call (g x (cdr y)). But the call
of f blocks the top-down exploration of the IF structure of the
body of g, so (consp y) does not rule that second recursive call,
which (again) is (g x (cdr y)). As a result, ACL2 fails to admit
the above definition.
Set-ruler-extenders is provided to overcome the sort of blocking
described above. Suppose for example that the following event is
submitted:
(set-ruler-extenders '(f))
Then the alternate definition of g above is admissible, because the
call of f no longer blocks the top-down exploration of the IF
structure of the body of g: that is, (consp y) becomes a ruler of
the recursive call (g x (cdr y)). In this case, we say that f is a
``ruler-extender''. The same result obtains if we first submit
(set-ruler-extenders :all)
as this removes all function calls as blockers of the top-down
analysis. In other words, with :all it is the case that for every
recursive call, every test argument of a superior call of IF
contributes a ruler of that recursive call.
ACL2 handles [let] (and [let*]) expressions by translating them to
LAMBDA expressions (see [term]). The next examples illustrates
termination analysis involving such expressions. First consider the
following (admittedly inefficient) definition.
(defun fact (n)
(let ((k (if (natp n) n 0)))
(if (equal k 0)
1
(* k (fact (+ -1 k))))))
ACL2 translates the body of this definition to a LAMBDA application,
essentially:
((lambda (k)
(if (equal k 0)
1
(* k (fact (+ -1 k)))))
(if (natp n) n 0))
As with the application of any function other than IF, the top-down
termination analysis does not dive into arguments: the LAMBDA
blocks the continuation of the analysis into its argument. But
here, the argument of the LAMBDA is (if (natp n) n 0), which has no
recursive calls to consider anyhow. What is more interesting: ACL2
does continue its termination analysis into the body of the LAMBDA,
in an environment binding the LAMBDA formals to its actuals. In
this case, the termination analysis thus continues into the term
(if (equal k 0)
1
(* k (fact (+ -1 k))))
in the environment that binds k to the term (if (natp n) n 0). Thus,
the proof obligation is successfully discharged, as reported by
ACL2:
For the admission of FACT we will use the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT N). The non-trivial part of the measure conjecture is
Goal
(IMPLIES (NOT (EQUAL (IF (NATP N) N 0) 0))
(O< (ACL2-COUNT (+ -1 (IF (NATP N) N 0)))
(ACL2-COUNT N))).
.....
Q.E.D.
That completes the proof of the measure theorem for FACT.
But now consider the following definition, in which the recursion
takes place inside the argument of the LAMBDA rather than inside
the LAMBDA body.
(defun app (x y)
(let ((result (if (endp x)
y
(cons (car x)
(app (cdr x) y)))))
(if (our-test result)
result
0)))
Writing the body in LAMBDA notation:
((lambda (result)
(if (our-test result)
result
0))
(if (endp x)
y
(cons (car x)
(app (cdr x) y))))
By default, the LAMBDA call blocks the top-down termination analysis
from proceeding into the term (if (endp x) ...). To solve this, one
can submit the event:
(set-ruler-extenders :lambdas)
The above definition of app is then admitted by ACL2, because the
termination analysis is no longer blocked by the LAMBDA call.
The example just above illustrates that the heuristically-chosen
measure is suitably sensitive to the ruler-extenders. Specifically:
that measure is the application of acl2-count to the first formal
parameter of the function that is tested along every branch of the
relevant IF structure (as determined by the rulers) and occurs as a
proper subterm at the same argument position in every recursive
call. The heuristics for choosing the controller-alist for a
[definition] rule are similarly sensitive to the ruler-extenders
(see [definition]).
The remarks above for [defun] [events] are equally applicable when a
definition sits inside a [mutual-recursion] event, except of course
that in this case, a ``recursive call'' is a call of any function
being defined by that [mutual-recursion] event.
Rules of class :[definition] are sensitive to set-ruler-extenders in
analogy to the case of defun [events].
This macro generates a call (table acl2-defaults-table
:ruler-extenders val) and hence is [local] to any [books] and
[encapsulate] [events] in which it occurs. See
[ACL2-defaults-table]. The current list of ruler-extenders may be
obtained as
(cdr (assoc-eq :ruler-extenders
(table-alist 'acl2-defaults-table (w state))))
or more conveniently, as:
(default-ruler-extenders (w state))
Note that evaluation of (set-ruler-extenders lst), where lst
evaluates to a list, does not necessarily include the default
ruler-extenders --- i.e., those included for the argument, :basic
--- which are the elements of the list constant
*basic-ruler-extenders*, namely [return-last] and [mv-list]. You
may, of course, include these explicitly in your list argument.
We conclude our discussion by noting that the set of ruler-extenders
can affect the induction scheme that is stored with a recursive
definition. The community book
books/misc/misc2/ruler-extenders-tests.lisp explains how induction
schemes are derived in this case. Consider the following example.
(defun tree-of-nils-p (x)
(if (consp x)
(and (tree-of-nils-p (car x))
(tree-of-nils-p (cdr x)))
(null x)))
The above definition generates the following induction scheme. Note
that (and u v) expands to (if u v nil), which explains why the term
(tree-of-nils-p (car x)) rules the recursive call (tree-of-nils-p
(cdr x)), resulting in the hypothesis (tree-of-nils-p (car x)) in
the final conjunct below.
(AND (IMPLIES (NOT (CONSP X)) (:P X))
(IMPLIES (AND (CONSP X)
(NOT (TREE-OF-NILS-P (CAR X)))
(:P (CAR X)))
(:P X))
(IMPLIES (AND (CONSP X)
(TREE-OF-NILS-P (CAR X))
(:P (CAR X))
(:P (CDR X)))
(:P X)))
Now consider the following variant of the above definition, in which
a call of the function identity blocks the termination analysis.
(defun tree-of-nils-p (x)
(if (consp x)
(identity (and (tree-of-nils-p (car x))
(tree-of-nils-p (cdr x))))
(null x)))
This time the induction scheme is as follows, since only the
top-level IF test contributes rulers to the termination analysis.
(AND (IMPLIES (NOT (CONSP X)) (:P X))
(IMPLIES (AND (CONSP X)
(:P (CAR X))
(:P (CDR X)))
(:P X)))
But now suppose we first designate identity as a ruler-extender.
(set-ruler-extenders '(identity))
Then the induction scheme generated for the both of the above
variants of tree-of-nils-p is the one shown for the first variant,
which is reasonable because both definitions now produce
essentially the same termination analysis.
Subtopics
[Default-ruler-extenders]
The default [ruler-extenders] for [defun]'d functions")
(RUNE
(THEORIES)
"A rule name
Examples:
(:rewrite assoc-of-app)
(:linear delta-aref . 2)
(:definition length)
(:executable-counterpart length)
Note: This topic discusses a basic notion of ``rule name'', or
``rune'' for short. Users often use abbrevitions for runes; for
example, a [theory] expression (DISABLE APPEND) abbreviates the
following set of runes: {(:DEFINITION BINARY-APPEND), (:INDUCTION
BINARY-APPEND)}. See [theories] for a discussion of so-called
``runic designators'', which include expressions like APPEND (as
above) as well as (APPEND) (for the executable-counterpart of
BINARY-APPEND. Runic designators can also be ``runic
abbreviations'' such as (:d APPEND), (:e APPEND), (:i APPEND), and
(:t APPEND), which designate the definition,
executable-counterpart, induction, and type-prescription rules for
BINARY-APPEND. For a complete description of runic designators, see
[theories]; we return now to the more basic notion of a rune.
Background: The theorem prover is driven from a database of rules.
The most common rules are :[rewrite] rules, which cause the
simplifier to replace one term with another. [Events] introduce
rules into the database. For example, a [defun] event may introduce
runes for symbolically replacing a function call by its
instantiated body, for evaluating the function on constants, for
determining the type of a call of the function, and for the
induction scheme introduced upon defining the function. [Defthm]
may introduce several rules, one for each of the :[rule-classes]
specified (where one rule class is specified if :[rule-classes] is
omitted, namely, :rewrite).
Every rule in the system has a name. Each name is a structured object
called a ``rune,'' which is short for ``rule name''. Runes are
always of the form (:token symbol . x), where :token is some
keyword symbol indicating what kind of rule is named, symbol is the
event name that created the rule (and is called the ``base symbol''
of the rune), and x is either nil or a natural number that makes
the rule name distinct from that of rules generated by other
[events] or by other :[rule-classes] within the same event.
For example, an event of the form
(defthm name thm
:rule-classes ((:REWRITE :COROLLARY term1)
(:REWRITE :COROLLARY term2)
(:ELIM :COROLLARY term3)))
typically creates three rules, each with a unique rune. The runes are
(:REWRITE name . 1), (:REWRITE name . 2), and (:ELIM name).
However, a given formula may create more than one rule, and all rules
generated by the same :corollary formula will share the same rune.
Consider the following example.
(defthm my-thm
(and (equal (foo (bar x)) x)
(equal (bar (foo x)) x)))
This is treated identically to the following.
(defthm my-thm
(and (equal (foo (bar x)) x)
(equal (bar (foo x)) x))
:rule-classes ((:rewrite
:corollary
(and (equal (foo (bar x)) x)
(equal (bar (foo x)) x)))))
In either case, two rules are created: one rewriting (foo (bar x)) to
x, and one rewriting (bar (foo x)) to x. However, only a single
rune is created, (:REWRITE MY-THM), because there is only one rule
class. But now consider the following example.
(defthm my-thm2
(and (equal (foo (bar x)) x)
(equal (bar (foo x)) x))
:rule-classes ((:rewrite
:corollary
(and (equal (foo (bar x)) x)
(equal (bar (foo x)) x)))
(:rewrite
:corollary
(and (equal (foo (bar (foo x))) (foo x))
(equal (bar (foo (bar x))) (bar x))))))
This time there are four rules created. The first two rules are as
before, and are assigned the rune (:REWRITE MY-THM . 1). The other
two rules are similarly generated for the second :corollary, and
are assigned the rune (:REWRITE MY-THM . 2).
The function [corollary] will return the [corollary] term associated
with a given rune in a given [world]. Example:
(corollary '(:TYPE-PRESCRIPTION DIGIT-TO-CHAR) (w state))
However, the preferred way to see the corollary term associated with
a rune or a name is to use :pf; see [pf].
The [defun] event creates as many as four rules. (:definition fn) is
the rune given to the equality axiom defining the function, fn.
(:executable-counterpart fn) is the rune given to the rule for
computing fn on known arguments. A type prescription rule may be
created under the name (:type-prescription fn), and an [induction]
rule may be created under the name (:induction fn).
Runes may be individually [enable]d and [disable]d, according to
whether they are included in the current theory. See [theories].
Thus, it is permitted to [disable] (:elim name), say, while
enabling the other rules derived from name. Similarly, (:definition
fn) may be [disable]d while (:executable-counterpart fn) and the
type prescriptions for fn are [enable]d.
Associated with most runes is the formula justifying the rule named.
This is called the ``[corollary] formula'' of the rune and may be
obtained via the function [corollary], which takes as its argument
a rune and a property list [world]. Also see [pf]. The [corollary]
formula for (:rewrite name . 1) after the [defthm] event above is
term1. The corollary formulas for (:definition fn) and
(:executable-counterpart fn) are always identical: the defining
axiom. Some runes, e.g., (:definition car), do not have corollary
formulas. [Corollary] returns nil on such runes. In any case, the
corollary formula of a rune, when it is non-nil, is a theorem and
may be used in the :use and :by [hints].
Note: The system has built-in rules that, for regularity, ought to
have names but don't because they can never be [disable]d. One such
rule is that implemented by the [linear] arithmetic package.
Because many of our subroutines are required by their calling
conventions to return the justifying rune, we have invented the
notion of ``fake runes.'' Fake runes always have the base symbol
nil, use a keyword token that includes the phrase ``fake-rune'',
and are always [enable]d. Here is the list of fake runes.
((:fake-rune-for-linear nil)
(:fake-rune-for-type-set nil))
Occasionally the system will print a fake rune where a rune is
expected. For example, when (:FAKE-RUNE-FOR-LINEAR NIL) is reported
among the rules used in a proof, it is an indication that the
linear arithmetic package was used. However, fake runes are not
allowed in [theories], they cannot be [enable]d or [disable]d, and
they do not have associated [corollary] formulas. In short, despite
the fact that the user may sometimes see fake runes printed, they
should never be typed.
Subtopics
[Find-rules-of-rune]
Find the rules named rune")
(RUNNING_MODELS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Running Models
[{IMAGE}]
Suppose the machine being modeled is some kind of arithmetic unit.
Suppose the model can be initialized so as to multiply x times y
and leave the answer in z. Then if we initialize s to multiply with
x=5 and y=7 and run the machine long enough, we can read the answer
35 in the final state. {IMAGE}
Because ACL2 is a programming language, our model can be run or
executed.
If you defined the model in ACL2 and then typed
(lookup 'z (mc (s 'mult 5 7) 29))
then ACL2 would compute 35. (Here we assume that the function s
creates a state ready to run a given application on given inputs x
and y.) You can emulate or test the model of your machine.
This is obvious because ACL2 is Common Lisp; and Common Lisp is a
programming language.
[{IMAGE}]")
(RW-CACHE (POINTERS)
"See [set-rw-cache-state].")
(SAVE-AND-CLEAR-MEMOIZATION-SETTINGS
(MEMOIZE)
"Save and remove the current memoization settings
For background on memoization, see [memoize].
General Form:
(save-and-clear-memoization-settings)
Calls of this macro achieve two changes. The first copies the current
memoization settings into an ACL2 [table], and the second
unmemoizes all functions that were memoized by calls of [memoize].
Also see [restore-memoization-settings].")
(SAVE-EXEC
(INTERFACING-TOOLS COMMAND-LINE)
"Save an executable image and a wrapper script
Save-exec saves your ACL2 state so that you can immediately re-start
later in that same state. This utility can be useful for a project
with [books] to be included every time ACL2 is started (see
[build::using-extended-ACL2-images]), to avoid time taken to run
[include-book]. Another use of save-exec is to save an executable
that takes command-line arguments beyond those normally passed to
the host Lisp executable. All arguments of a call of save-exec are
evaluated.
Examples:
; Save an executable script named my-saved_acl2, with the indicated message
; added to the start-up banner:
(save-exec \"my-saved_acl2\"
\"This saved image includes Version 7 of Project Foo.\")
; Same as above, but instead with a generic comment in the start-up banner:
(save-exec \"my-saved_acl2\" nil)
; Arrange that the generated script passes the indicated arguments to be
; processed by the Lisp (ACL2) executable (where this example is specific to
; the case that CCL is the host Lisp):
(save-exec \"my-saved_acl2\" nil
:host-lisp-args \"--no-init -Z 256M\")
; Arrange that the generated script passes along the indicated arguments
; to Lisp (ACL2), but that they are not processed by Lisp other than to
; record the additional arguments (see (6) below).
(save-exec \"my-saved_acl2\" nil
:inert-args \"abc xyz -i foo\")
; Combining the preceding two examples:
(save-exec \"my-saved_acl2\" nil
:host-lisp-args \"--no-init -Z 256M\"
:inert-args \"abc xyz -i foo\")
; Arrange that ACL2 evaluates (with LD) the three forms shown.
; In this example, the THM form fails, but that does not stop the definition
; of BAR from being evaluated: LD continues on, just as the top-level loop
; lets you continue after a failure.
(save-exec \"my-acl2\" \"test\"
:init-forms
'((defun foo (x) (reverse x))
(thm (equal (foo x) x))
(defun bar (x) x)))
; Essentially as just above, except that the call of LD returns after the THM
; failure, so BAR does not get defined.
(save-exec \"my-acl2\" \"test\"
:init-forms
'((ld '((defun foo (x) (reverse x))
(thm (equal (foo x) x))
(defun bar (x) x))
:ld-pre-eval-print t :ld-verbose nil)))
; Immediately exit the ACL2 read-eval-print loop after starting up.
(save-exec \"my-acl2\" nil
:return-from-lp t)
; Immediately exit the ACL2 read-eval-print loop after starting up and
; defining function FOO in the logic.
(save-exec \"my-acl2\" \"Start with foo defined.\"
:return-from-lp '(with-output
:off :all
(defun foo (x) x)))
; Immediately exit the ACL2 read-eval-print loop after starting up and
; defining variable xxx in raw Lisp.
(save-exec \"my-acl2\" \"Start with xxx defined.\"
:return-from-lp '(with-output
:off :all
(ld '((set-raw-mode-on!)
(defvar xxx (make-list 10))
(set-raw-mode nil)
(u)))))
Each example above generates a file named \"my-saved_acl2\". That file
is quite similar in form to the script generated when building ACL2
directly from source code; details are below. For example, here are
the contents of that generated file if the host Lisp is CCL (but
where dates and pathnames are specific to one's environment). Here,
we break lines using `\\', but the exec command is actually on a
single line.
#!/bin/sh
# Saved August 16, 2013 23:06:49
# then August 17, 2013 11:01:56
export CCL_DEFAULT_DIRECTORY=\"/projects/acl2/lisps/ccl/15542/ccl\"
exec \"/projects/ccl/lx86cl64\" -I \"/u/smith/my-saved_acl2.lx86cl64\" \\
-Z 64M -K ISO-8859-1 -e \"(acl2::acl2-default-restart)\" \\
--no-init -Z 256M \\
-- \\
abc xyz -i foo \\
\"$@\"
General Form:
(save-exec exec-filename extra-startup-string
:host-lisp-args host-lisp-args
:inert-args inert-args
:return-from-lp return-from-lp
:init-forms init-forms)
where the keyword arguments are optional, and arguments are as
follows.
Exec-filename is the filename of the proposed executable.
Extra-startup-string is a non-empty string to be printed after the
normal ACL2 startup message when you start up the saved image.
However, extra-startup-string is allowed to be nil, in which
case a generic string will be printed instead.
Host-lisp-args can be nil (the default), but if it is a non-nil
value, then it is a string to be inserted into the command line
in the saved script, specifying additional arguments that are
to be processed by the host Lisp executable. (Note for SBCL
only: these are runtime options; for toplevel options, see (8)
below.)
Inert-args can be nil (the default), but if it is a non-nil value,
then it is a string to be inserted into the command line in the
saved script, specifying additional arguments that are not to
be processed by the host Lisp executable.
Return-from-lp and init-forms are nil by default. Regardless of their
value, ACL2 starts up and enters its read-eval-print loop in the
usual way; see [lp]. Normally you'll stay inside that loop, but if
return-from-lp or init-forms is not nil, then the indicated forms
are evaluated in the ACL2 read-eval-print loop: a single form in
the case of return-from-lp, and a list of forms in the case of
init-forms. (Essentially, the [ld] special [standard-oi] is
provided to a call of [ld] as a list with the indicated forms on
the front.) Moreover, if the case of return-from-lp, the loop is
exited after evaluation of the form, leaving you in raw Lisp.
Evaluation of return-from-lp is done with [ld] options that
minimize output (also see [with-output] to minimize output).
Suggestion: let return-from-lp be t if you simply want to exit the
read-eval-print loop at startup, without evaluating any
(nontrivial) form.
NOTE: It is illegal to supply non-nil values for both :return-from-lp
and :init-forms. But if you add (value :q) to the end of your list
of :init-forms, and your other forms do not result in an error,
then you will be left in raw Lisp (as was presumably intended if
you were planning to use :return-from-lp).
The remainder of this documentation focuses on the options other than
return-from-lp and init-forms.
Details:
(1) You must first exit the ACL2 read-eval-print loop, typically by
executing :q, before evaluating a save-exec call; otherwise an
error occurs.
(2) The image will be saved so that in the new image, the raw Lisp
package and the package in the ACL2 read-eval-print loop (see [lp])
will be the same as their respective values at the time save-exec
is called.
(3) Save-exec generates a small script file (e.g., \"my-saved_acl2\" in
the examples above), similar in form (see (4) below) to the script
generated when building ACL2 directly from source code, but with a
comment line indicating the time at which the new script is
written. Save-exec also saves an associated binary file. The binary
file's name is obtained by putting a suffix on the script filename;
for example, if the host Lisp is GCL running on a Linux or Darwin
(MacOS) system, then that binary file has the name
my-saved_acl2.gcl in the examples above.
(4) If inert-args is nil (for example if keyword :inert-args is
omitted), then when the generated ACL2 script is invoked with
command line arguments, those arguments will be passed to the host
Lisp; otherwise they will not. Thus for the example above, suppose
we invoke the generated script as follows.
my-saved_acl2 -a bcd -e fgh
If my-saved_acl2 was generated using a save-exec command with a
non-nil value specified for keyword :inert-args, then the arguments
``-a bcd -e fgh'' will not be passed to the host Lisp; otherwise,
they will be. Note that for ACL2 executable scripts generated by an
ordinary ACL2 build from sources, the latter case (i.e., without
inert-args) takes place.
(5) The generated script, which specifies execution with /bin/sh,
will generally contain a line of one of the following forms. (But
for SBCL, see (8) below.) In the examples that follow, ACL2_options
is a suitable list of command-line arguments given to the ACL2
executable. The quoted string \"$@\" is intended to allow the user to
pass additional command-line arguments to that executable.
If host-lisp-args and inert-args are omitted (or nil):
exec <lisp_executable> <ACL2_options> \"$@\"
More generally, host-lisp-args is inserted immediately after
<ACL2_options>, but only if it is non-nil (hence a string). If
inert-args is nil, we thus get:
exec <lisp_executable> <ACL2_options> host-lisp-args \"$@\"
If host-lisp-args redefines a value from <ACL2_options>, then it is
up to the host lisp which value to use. For example,
experiments show that in CCL, if -Z appears twice, each with a
legal value, then the second value is the one that is used
(i.e. it does indeed override the original value written out by
ACL2 in <ACL2_options>. But experiments also show that in
LispWorks, where ``-init -'' is included in <ACL2_options>,
then inclusion of ``-init foo.lisp'' in host-lisp-args is
ignored.
The remaining cases below are for a non-nil value of inert-args. In
each case, if host-lisp-args is nil then it should be omitted
from the displayed command.
If inert-args is t then an additional argument, `--', indicates that
when ACL2 is given command line arguments, these should not be
processed by the host Lisp (other than recording them; see (6)
below):
exec <lisp_executable> <ACL2_options> host-lisp-args -- \"$@\"
If inert-args is a string then the result is similar to the above,
except that inert-args is added immediately after `--':
exec <lisp_executable> <ACL2_options> host-lisp-args -- inert-args \"$@\"
(6) See [oslib::argv] for a utility that returns a list of all
inert-args from an invocation of ACL2. See also [getopt] for a
convenient way to parse these arguments.
(7) Suppose that you invoke an ACL2 script, say \"my-saved_acl2\", that
was generated by save-exec, and then optionally evaluate some
forms. Then you may save a new ACL2 script with save-exec. The new
script will contain comment lines that extend comment lines in
\"my-saved_acl2\" with a new write date, but otherwise will be
identical to the script that would have been generated by executing
the new save-exec call after invoking the original ACL2 executable
(built directly from ACL2 sources) instead of \"my-saved_acl2\". In
other words, the options added by the earlier save-exec call that
created \"my-saved_acl2\" are discarded by the new save-exec call.
However, the .core file will built on top of the .core file that
was consulted when \"my-saved_acl2\" was invoked.
(8) The following note pertains only to the case that the host Lisp
is SBCL. For SBCL, the scripts written are analogous to, but
slightly different from, those shown above. Please note that for
SBCL, the host-lisp-args are what the SBCL manual calls ``runtime
options''. For SBCL only, an extra keyword argument,
:toplevel-args, may be used for specifying what the SBCL manual
calls ``toplevel options. As with :host-lisp-args, this value,
toplevel-args, should be nil (the default) or a string. Here is an
example.
(save-exec \"my-saved_acl2\" nil
:host-lisp-args \"--dynamic-space-size 12000\"
:toplevel-args \"--eval '(print \\\"HELLO\\\")'\"
:inert-args \"--my-option my-value\")
The script generated by this example call of save-exec contains a
line such as the following (with the same convention for `\\' as
before)
exec \"/projects/sbcl-1.1.7-x86-64-linux/src/runtime/sbcl\" \\
--dynamic-space-size 2000 --control-stack-size 8 \\
--core \"/u/smith/my-saved_acl2.core\" --dynamic-space-size 12000 \\
--end-runtime-options \\
--no-userinit --eval '(acl2::sbcl-restart)' \\
--eval '(print \"HELLO\")' \\
--end-toplevel-options \\
--my-option my-value \\
\"$@\"
In general, the generated script is of one of the following forms
(with the same convention for `\\' as before).
For the case that inert-args is nil:
exec <lisp_executable> \\
<ACL2_runtime_options> host-lisp-args --end-runtime-options \\
<ACL2_toplevel_options> host-lisp-args \\
\"$@\"
For the case that inert-args is non-nil:
exec <lisp_executable> \\
<ACL2_runtime_options> host-lisp-args --end-runtime-options \\
<ACL2_toplevel_options> host-lisp-args --end-toplevel-options \\
inert-args \"$@\"
Notice that as before, when the generated script is invoked (for
example, at the shell), additional command-line arguments provided
at that time are passed to Lisp if and only if inert-args is nil.
For SBCL, when they are passed to Lisp they are passed as toplevel
options, not as runtime options.")
(SAVING-AND-RESTORING (POINTERS)
"See [save-exec].")
(SEARCH
(LISTS STRINGS ACL2-BUILT-INS)
"Search for a string or list in another string or list
Example Forms:
(search \"cd\" \"Cdabcdefcde\") ; = 4, index of first match
(search \"cd\" \"Cdabcdefcde\" :test 'equal) ; same as above
(search \"cd\" \"Cdabcdefcde\" :from-end t) ; = 8, index of last match
(search \"cd\" \"Cdabcdefcde\" :start1 1) ; = 1
(search \"cd\" \"Cdabcdefcde\" :start2 5) ; = 8
(search \"cd\" \"Cdabcdefcde\" :test 'char-equal) ; = 0 (case-insensitive)
(search \"ac\" \"Cdabcdefcde\") ; = nil
(search '(a b) '(9 8 a b 7 6)) ; = 2
General Form:
(search seq1 seq2 &key from-end test start1 start2 end1 end2)
Search indicates whether one string or list occurs as a (contiguous)
subsequence of another string or list, respectively. It returns nil
if no such match is found; otherwise it returns the (zero-based)
index of the first match by default, but a non-nil value of keyword
argument :from-end causes it to return the last match. The :test is
equal by default. The other legal value for :test is char-equal,
which can be given only for two strings, in which case the match is
case-insensitive. Finally, values of :start1 and :end1 for the
first sequence, and of :start2 and :end2 for the second sequence,
bound the portion of the respective sequence used for deciding on a
match, though the index returned is always an index into the second
sequence as a whole.
The [guard] for calls of search is given by a function,
search-fn-guard, which has the following requirements.
* The two arguments much both satisfy [true-listp] or else must both be
strings, which must consist of standard characters (see
[standard-char-p]) if the :test is [char-equal].
* The :test must evaluate to one of the symbols [equal] or
[char-equal], where the latter is only allowed if the (first)
two arguments are strings.
* The values of :start1, :start2, :end1, and :end2 must all be natural
numbers, where if omitted they default to 0, 0, the length len1
of the first argument, and the length len2 of the second
argument, respectively.
* If start1 is the value of :start1, defaulting as described just
above, and similarly for the other start and end keywords and
for lengths len1 and len2 as described just above, then: start1
<= end1 <= len1 and start2 <= end2 <= len2.
Search is a Common Lisp function (actually, a macro in ACL2). See any
Common Lisp documentation for more information.
Definition
Macro: <search>
(defmacro
search
(seq1 seq2 &key from-end (test ''equal)
(start1 '0)
(start2 '0)
(end1 'nil end1p)
(end2 'nil end2p))
(cons
'search-fn
(cons
seq1
(cons
seq2
(cons
from-end
(cons
test
(cons
start1
(cons start2
(cons end1
(cons end2
(cons end1p (cons end2p 'nil))))))))))))
Function: <search-fn>
(defun
search-fn
(seq1 seq2 from-end test
start1 start2 end1 end2 end1p end2p)
(declare
(xargs
:guard (search-fn-guard seq1 seq2 from-end test
start1 start2 end1 end2 end1p end2p)))
(let*
((end1 (if end1p end1 (length seq1)))
(end2 (if end2p end2 (length seq2)))
(seq1 (subseq seq1 start1 end1)))
(mv-let
(seq1 seq2)
(cond ((eq test 'char-equal)
(mv (string-downcase seq1)
(string-downcase seq2)))
(t (mv seq1 seq2)))
(and (<= (- end1 start1) (- end2 start2))
(cond (from-end (search-from-end seq1 seq2 start2 end2 nil))
(t (search-from-start seq1 seq2 start2 end2)))))))
Function: <search-from-end>
(defun
search-from-end
(seq1 seq2 start2 end2 acc)
(declare (xargs :guard (and (or (true-listp seq1) (stringp seq1))
(or (true-listp seq2) (stringp seq2))
(integerp start2)
(<= 0 start2)
(integerp end2)
(<= end2 (length seq2))
(<= (+ start2 (length seq1)) end2))))
(cond ((or (not (integerp end2))
(not (integerp start2)))
nil)
(t (let* ((bound2 (+ start2 (length seq1)))
(matchp (equal seq1 (subseq seq2 start2 bound2)))
(new-acc (if matchp start2 acc)))
(cond ((>= bound2 end2) new-acc)
(t (search-from-end seq1 seq2 (1+ start2)
end2 new-acc)))))))
Function: <search-from-start>
(defun
search-from-start
(seq1 seq2 start2 end2)
(declare (xargs :guard (and (or (true-listp seq1) (stringp seq1))
(or (true-listp seq2) (stringp seq2))
(integerp start2)
(<= 0 start2)
(integerp end2)
(<= end2 (length seq2))
(<= (+ start2 (length seq1)) end2))))
(let ((bound2 (+ start2 (length seq1))))
(cond ((or (not (integerp end2))
(not (integerp start2)))
nil)
((equal seq1 (subseq seq2 start2 bound2))
start2)
((>= bound2 end2) nil)
(t (search-from-start seq1 seq2 (1+ start2)
end2)))))")
(SECOND
(NTH ACL2-BUILT-INS)
"Second member of the list
See any Common Lisp documentation for details.")
(SERIALIZE
(IO)
"Routines for saving ACL2 objects to files, and later restoring them
We thank Jared Davis for contributing the ``serialization'' routines
for saving ACL2 objects in files for later loading.
We implement some routines for writing arbitrary ACL2 objects to
files, and for loading those files later. We usually call these
\".sao\" files, which stands for (S)erialized (A)CL2 (O)bject.
Our serialization scheme uses a compact, binary format that preserves
structure sharing in the original object. We optimize for read
performance.
Subtopics
[Serialize-alternatives]
Historic alternatives to the [serialize] routines.
[Serialize-in-books]
Using serialization efficiently in books
[Serialize-read]
Read a serialized ACL2 object from a file
[Serialize-write]
Write an ACL2 object into a file
[With-serialize-character]
Control output mode for print-object$")
(SERIALIZE-ALTERNATIVES
(SERIALIZE)
"Historic alternatives to the [serialize] routines.
Routines compact-print-file and compact-read-file were previously
built into ACL2. Another option was to use the hons-archive
library. These tools were deprecated and ultimately removed from
ACL2. If for some reason you need to use them, see
[community-books] SVN revisions prior to 1314.")
(SERIALIZE-IN-BOOKS
(SERIALIZE)
"Using serialization efficiently in books
Our serialize scheme was developed in order to allow very large ACL2
objects to be loaded into books. Ordinarily this is carried out
using [serialize-read] within a [make-event], e.g.,
(make-event (mv-let (obj state)
(serialize-read \"my-file\")
(value `(defconst *my-file* ',obj))))
But this scheme is not particularly efficient.
During [certify-book], the actual call of serialize-read is carried
out, and this is typically pretty fast. But then a number of
possibly inefficient things occur.
- The ACL2 function bad-lisp-object is run on the resulting object.
This is memoized for efficiency, but may still take
considerable time when the file is very large.
- The checksum of the resulting object is computed. This is also
memoized, but as before may still take some time.
- The object that was just read is then written into book.cert,
essentially with [serialize-write]. This can take some time,
and results in large certifiate files.
Then, during [include-book], the make-event expansion of is loaded.
This is now basically just a serialize-read.
The moral of the story is that using serialize will only help your
certify-book time, and it only impacts a portion of the overall
time.
To avoid this overhead, we have developed an UNSOUND alternative to
serialize-read, which is available only by loading an additional
book. So, if the above scheme is not performing well for you, you
may wish to see [unsound-read].")
(SERIALIZE-READ
(SERIALIZE ACL2-BUILT-INS)
"Read a serialized ACL2 object from a file
General form:
(serialize-read filename
[:hons-mode {:always, :never, :smart}] ; :smart by default
[:verbosep {t, nil}]) ; nil by default
-->
(mv obj state)
In the logic this is an oracle read.
Under the hood, we try to read and return a serialized object from a
file that was presumably created by [serialize-write]. On success
we return the contents of the file. Any failures (e.g., file not
found, bad file contents, etc.) will result in a hard Lisp error.
The filename should be a string that gives the path to the file.
The hons-mode controls how whether to use [hons] or [cons] to restore
the object. The default mode is :smart, which means that conses
that were [normed] at the time of the file's creation should be
restored with hons. But you can override this and insist that hons
is to :always or :never be used, instead.
Why would you use :never? If your object previously had a lot of
honses, but you no longer have any need for them to be normed, then
using :never may sometimes be a lot faster since it can avoid hons
calls. On the other hand, if you are going to [hons-copy] some part
of the file's contents, then it is likely faster to use :smart or
:always instead of first creating normal conses and then copying
them to build honses.
The :verbosep flag just controls whether to print some low-level
details related to timing and memory usage as the file is being
read.")
(SERIALIZE-WRITE
(SERIALIZE ACL2-BUILT-INS)
"Write an ACL2 object into a file
General form:
(serialize-write filename obj
[:verbosep {t, nil}]) ; nil by default
-->
state
In the logic this carries out an oracle read.
Under the hood, we try to save obj into the file indicated by
filename, which must be a string. The object can later be recovered
with [serialize-read]. We just return state, and any failures
(e.g., file not openable) will result in a hard Lisp error.
Writing objects to disk is generally slower than reading them back in
since some analysis is required to convert an object into our
[serialize]d object format.
The verbosep flag just says whether to print some low-level details
related to timing and memory usage as the file is being written.")
(SET-ABSSTOBJ-DEBUG
(DEFABSSTOBJ)
"Obtain debugging information upon atomicity violation for an abstract
stobj
This [documentation] topic assumes familiarity with abstract stobjs.
See [defabsstobj].
Below we explain what is meant by an error message such as the
following.
ACL2 Error in CHK-ABSSTOBJ-INVARIANTS: Possible invariance violation
for an abstract stobj! See :DOC set-absstobj-debug, and PROCEED AT
YOUR OWN RISK.
The use of (set-absstobj-debug t) will make this error message more
informative, as follows, at the cost of slower execution --- but in
practice, the slowdown may be negligible (more on that below).
ACL2 Error in CHK-ABSSTOBJ-INVARIANTS: Possible invariance violation
for an abstract stobj! See :DOC set-absstobj-debug, and PROCEED AT
YOUR OWN RISK. Evaluation was aborted under a call of abstract stobj
export UPDATE-FLD-NIL-BAD.
You may be best off starting a new ACL2 session if you see one of the
errors above. But you can continue at your own risk. With a trust
tag (see [defttag]), you can even fool ACL2 into thinking nothing
is wrong, and perhaps you can fix up the abstract stobj so that
indeed, nothing really is wrong. See the community book
books/misc/defabsstobj-example-4.lisp for how to do that. That book
also documents the :always keyword and a special value for the
first argument, :RESET.
Examples:
(set-absstobj-debug t) ; obtain extra debug info, as above
(set-absstobj-debug t :event-p t) ; same as above
(set-absstobj-debug t
:on-skip-proofs t) ; as above, but even in include-book
(set-absstobj-debug t :event-p nil) ; returns one value, not error triple
(set-absstobj-debug nil) ; avoid extra debug info (default)
General Form:
(set-absstobj-debug val
:event-p event-p ; default t
:always always ; default nil
:on-skip-proofs on-skip-proofs ; default nil
)
where the keyword arguments are optional with defaults as indicated
above, and all supplied arguments are evaluated except for
on-skip-proofsp, which must be Boolean (if supplied). Keyword
arguments are discussed at the end of this topic.
Recall (see [defabsstobj]) that for any exported function whose :EXEC
function might (according to ACL2's heuristics) modify the concrete
stobj non-atomically, one must specify :PROTECT t. This results in
extra code generated for the exported function, which provides a
check that atomicity was not actually violated by a call of the
exported function. The extra code might slow down execution, but
perhaps only negligibly in typical cases. If you can tolerate a bit
extra slow-down, then evaluate the form (set-absstobj-debug t).
Subsequent such errors will provide additional information, as in
the example displayed earlier in this documentation topic.
Finally we document the keyword arguments, other than :ALWAYS, which
is discussed in a book as mentioned above. When the value of
:EVENT-P is true, which it is by default, the call of
set-absstobj-debug will expand to an event. That event is a call of
[value-triple]. In that case, :ON-SKIP-PROOFS is passed to that
call so that set-absstobj-debug has an effect even when proofs are
being skipped, as during [include-book]. That behavior is the
default; that is, :ON-SKIP-PROOFS is nil by default. Also see
[value-triple]. The value of keyword :ON-SKIP-PROOFS must always be
either t or nil, but other than that, it is ignored when EVENT-P is
nil.")
(SET-ACCUMULATED-PERSISTENCE (POINTERS)
"See [accumulated-persistence].")
(SET-BACKCHAIN-LIMIT
(BACKCHAIN-LIMIT)
"Sets the backchain-limit used by the type-set and rewriting
mechanisms
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Moreover, its effect is to set the [ACL2-defaults-table], and hence
its effect is [local] to the book or [encapsulate] form containing
it; see [ACL2-defaults-table].
This event sets the global [backchain-limit] used by the ACL2
type-set and rewriting mechanisms. Its value may be a cons whose
car and cdr are each either nil or a non-negative integer. Its
value x may also be nil or a non-negative integer, which is treated
as a cons whose car and cdr are both x.
The car is used to limit backchaining used by the ACL2 type-set
mechanism, while the cdr is used to limit backchaining used by the
rewriting mechanism. See [backchain-limit] for details about how
backchain-limits are used. Rewrite backchain limits may also be
installed at the level of hints; see [hints] for a discussion of
:backchain-limit-rw.
:set-backchain-limit nil ; do not impose any additional limits
:set-backchain-limit 0 ; allow only type-set reasoning for rewriting
; hypotheses
:set-backchain-limit 500 ; allow backchaining to a depth of no more
; than 500 for rewriting hypotheses
(set-backchain-limit 500) ; same as above
:set-backchain-limit (500 500)
; same as above
(set-backchain-limit '(500 500))
; same as above
(set-backchain-limit '(3 500))
; allow type-set backchaining to a depth of no more
; than 3 and rewriter backchaining to a depth of no
; more than 500
The default limit is (nil nil).")
(SET-BODY
(DEFINITION EVENTS)
"Set the definition body
Examples:
(set-body foo (:definition foo)) ; restore original definition of foo
(set-body foo foo) ; same as just above
(set-body foo my-foo-def) ; use my-foo-def for the body of foo
(set-body foo (:definition my-foo-def)) ; same as just above
Rules of class :[definition] can install a new definition body, used
for example by :expand [hints]. See [definition] and also see
[hints] for a detailed discussion of the :install-body fields of
:[definition] rules and their role in :expand hints.
There may be several such definitions, but by default, the latest one
is used by :expand hints. Although the :with keyword may be used in
:expand hints to override this behavior locally (see [hints]), it
may be convenient to install a definition for expansion other than
the latest one --- for example, the original definition. Set-body
may be used for this purpose.
General Form:
(set-body function-symbol rule-name)
where rule-name is either a :definition [rune] or is a function
symbol, sym, which represents the rune (:definition sym).
You can view all definitions available for expansion; see
[show-bodies].")
(SET-BOGUS-DEFUN-HINTS-OK
(DEFUN)
"Allow unnecessary (xargs :hints ...).
General Forms:
(set-bogus-defun-hints-ok t)
(set-bogus-defun-hints-ok nil)
(set-bogus-defun-hints-ok :warn)
By default, ACL2 causes an error when the keyword :[hints] is
supplied in an [xargs] [declare] form for a non-recursive
definition (see [defun]). This behavior can be defeated with
(set-bogus-defun-hints-ok t), or if you still want to see a warning
in such cases, (set-bogus-defun-hints-ok :warn).")
(SET-BOGUS-MUTUAL-RECURSION-OK
(MUTUAL-RECURSION)
"Allow unnecessary ``mutual recursion''
Examples:
(set-bogus-mutual-recursion-ok t)
(set-bogus-mutual-recursion-ok nil)
(set-bogus-mutual-recursion-ok :warn)
By default, ACL2 checks that when a ``clique'' of more than one
function is defined simultaneously (using [mutual-recursion] or
[defuns]), then every body calls at least one of the functions in
the ``clique.'' Below, we refer to definitional events that fail
this check as ``bogus'' mutual recursions. The check is important
because ACL2 does not store induction schemes for functions defined
with other functions in a [mutual-recursion] or [defuns] event.
Thus, ACL2 may have difficulty proving theorems by induction that
involve such functions. Moreover, the check can call attention to
bugs, since users generally intend that their mutual recursions are
not bogus.
Nevertheless, there are times when it is advantageous to allow bogus
mutual recursions, for example when they are generated
mechanically, even at the expense of losing stored induction
schemes. The first example above allows bogus mutual recursion. The
second example disallows bogus mutual recursion; this is the
default. The third example allows bogus mutual recursion, but
prints an appropriate warning.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Moreover, its effect is to set the [ACL2-defaults-table], and hence
its effect is [local] to the book or [encapsulate] form containing
it; see [ACL2-defaults-table].
General Form:
(set-bogus-mutual-recursion-ok flg)
where flg is either t, nil, or :warn.")
(SET-CASE-SPLIT-LIMITATIONS
(MISCELLANEOUS)
"Set the case-split-limitations
Examples:
(set-case-split-limitations '(500 100))
(set-case-split-limitations 'nil)
(set-case-split-limitations '(500 nil))
The first of these prevents clausify from trying the
subsumption/replacement (see below) loop if more than 500 clauses
are involved. It also discourages the clause simplifier from
splitting into more than 100 cases at once.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Moreover, its effect is to set the [ACL2-defaults-table], and hence
its effect is [local] to the book or [encapsulate] form containing
it; see [ACL2-defaults-table].
See [hints] for discussion of a related hint,
:case-split-limitations. Also see [splitter] for information about
reports on rules that may be responsible for case splits.
General Form:
(set-case-split-limitations lst)
where lst is either nil (denoting a list of two nils), or a list of
length two, each element of which is either nil or a natural
number. When nil is used as an element, it is treated as positive
infinity. The default setting is (500 100).
The first number specifies the maximum number of clauses that may
participate in the ``subsumption/replacement'' loop. Because of the
expensive nature of that loop (which compares every clause to every
other in a way that is quadratic in the number of literals in the
clauses), when the number of clauses exceeds about 1000, the system
tends to ``go into a black hole,'' printing nothing and not even
doing many garbage collections (because the subsumption/replacement
loop does not create new clauses so much as it just tries to delete
old ones). The initial setting is lower than the threshold at which
we see noticeably bad performance, so you probably will not see
this behavior unless you have raised or disabled the limit.
Why raise the subsumption/replacement limit? The
subsumption/replacement loop cleans up the set of subgoals produced
by the simplifier. For example, if one subgoal is
(implies (and p q r) s) [1]
and another is
(implies (and p (not q) r) s) [2]
then the subsumption/replacement loop would produce the single
subgoal
(implies (and p r) s) [3]
instead. This cleanup process is simply skipped when the number of
subgoals exceeds the subsumption/replacement limit. But each
subgoal must nonetheless be proved. The proofs of [1] and [2] are
likely to duplicate much work, which is only done once in proving
[3]. So with a low limit, you may find the system quickly produces
a set of subgoals but then takes a long time to prove that set.
With a higher limit, you may find the set of subgoals to be
``cleaner'' and faster to prove.
Why lower the subsumption/replacement limit? If you see the system go
into a ``black hole'' of the sort described above (no output, and
few garbage collections), it could due to the
subsumption/replacement loop working on a large set of large
subgoals. You might temporarily lower the limit so that it begins
to print the uncleaned set of subgoals. Perhaps by looking at the
output you will realize that some function can be disabled so as to
prevent the case explosion. Then raise or disable the limit again!
The second number in the case-split-limitations specifies how many
case splits the simplifier will allow before it begins to shut down
case splitting. In normal operation, when a literal rewrites to a
nest of IFs, the system simplifies all subsequent literals in all
the contexts generated by walking through the nest in all possible
ways. This can also cause the system to ``go into a black hole''
printing nothing except garbage collection messages. This ``black
hole'' behavior is different from than mentioned above because
space is typically being consumed at a prodigious rate, since the
system is rewriting the literals over and over in many different
contexts.
As the simplifier sweeps across the clause, it keeps track of the
number of cases that have been generated. When that number exceeds
the second number in case-split-limitations, the simplifier stops
rewriting literals. The remaining, unrewritten, literals are copied
over into the output clauses. IFs in those literals are split out,
but the literals themselves are not rewritten. Each output clause
is then attacked again, by subsequent simplification, and
eventually the unrewritten literals in the tail of the clause will
be rewritten because the earlier literals will stabilize and stop
producing case splits.
The default setting of 100 is fairly low. We have seen successful
proofs in which thousands of subgoals were created by a
simplification. By setting the second number to small values, you
can force the system to case split slowly. For example, a setting
of 5 will cause it to generate ``about 5'' subgoals per
simplification.
You can read about how the simplifier works in the book
Computer-Aided Reasoning: An Approach (Kaufmann, Manolios, Moore);
also see [introduction-to-the-theorem-prover] for a detailed
tutorial on using the ACL2 prover. If you think about it, you will
see that with a low case limit, the initial literals of a goal are
repeatedly simplified, because each time a subgoal is simplified we
start at the left-most subterm. So when case splitting prevents the
later subterms from being fully split out, we revisit the earlier
terms before getting to the later ones. This can be good. Perhaps
it takes several rounds of rewriting before the earlier terms are
in normal form and then the later terms rewrite quickly. But it
could happen that the earlier terms are expensive to rewrite and do
not change, making the strategy of delayed case splits less
efficient. It is up to you.
Sometimes the simplifier produces more clauses than you might expect,
even with case-split-limitations in effect. As noted above, once
the limit has been exceeded, the simplifier does not rewrite
subsequent literals. But IFs in those literals are split out
nonetheless. Furthermore, the enforcement of the limit is -- as
described above -- all or nothing: if the limit allows us to
rewrite a literal then we rewrite the literal fully, without regard
for limitations, and get as many cases as ``naturally'' are
produced. It quite often happens that a single literal, when
expanded, may grossly exceed the specified limits.
If the second ``number'' is nil and the simplifier is going to
produce more than 1000 clauses, a ``helpful little message'' to
this effect is printed out. This output is printed to the system's
``comment window'' not the standard proofs output.")
(SET-CBD
(BOOKS-REFERENCE)
"To set the connected book directory
Example Forms:
ACL2 !>:set-cbd \"/usr/home/smith/\"
ACL2 !>:set-cbd \"my-acl2/books\"
See [cbd] for a description of the connected book directory.
General Form:
(set-cbd str)
where str is a nonempty string that represents the desired directory
(see [pathname]). This command sets the connected book directory
(see [cbd]) to the string representing the indicated directory.
Thus, this command may determine which files are processed by
[include-book] and [certify-book] [command]s typed at the
top-level. However, the [cbd] is also temporarily set by those two
book processing [command]s.
IMPORTANT: Pathnames in ACL2 are in the Unix (trademark of AT&T)
style. That is, the character ``/'' separates directory components
of a pathname, and pathnames are absolute when they start with this
character, and relative otherwise. See [pathname].")
(SET-CHECK-INVARIANT-RISK
(PROGRAMMING ADVANCED-FEATURES GUARD DEBUGGING)
"Potential slowdown for [program]-mode updates to [stobj]s or [arrays]
See [invariant-risk] for a brief introduction to the notion of
invariant-risk, and see [program-wrapper] for a more detailed
discussion. Briefly put, if a syntactic analysis suggests that the
call of a :[program] mode function can lead to an ill-guarded call
of a [stobj] updater or of certain built-ins, notably [aset1] or
[aset2], then ACL2 considers such a call to be an ``invariant-risk
call''. There are four different ways that ACL2 can handle such a
call, corresponding to four different values of the
``invariant-risk mode'', which is the value obtained by evaluating
(get-check-invariant-risk state). The default invariant-risk mode
is :WARNING: in that mode, ACL2 prints a warning when encountering
a topmost invariant-risk call and uses a slower mode of execution
in order to avoid ill-guarded calls as discussed above. Mode T has
the same behavior, but without the warning. Mode :ERROR causes a
break when encountering a topmost invariant-risk call; the Lisp
should give you the option of continuing (as though the mode were
T) or aborting, as you choose. Finally, mode NIL --- which can only
be set when there is an active trust tag (see [defttag]) --- avoids
any special treatment for invariant-risk calls: there is no slower
mode of execution, but rather, execution passes directly to raw
Lisp (see [program-wrapper]).
ACL2 provides a utility, set-check-invariant-risk, for changing the
invariant-risk mode. The simplest case is when that utility is only
called with one argument, in which case, that argument becomes the
new invariant-risk mode, as follows.
(set-check-invariant-risk :ERROR) ; new mode is :ERROR
(set-check-invariant-risk :WARNING) ; new mode is :WARNING (the default)
(set-check-invariant-risk T) ; new mode is T
(set-check-invariant-risk NIL) ; new mode is NIL
As noted above, there must be an active trust tag in order to set the
invariant-risk mode to NIL. However, ACL2 arranges automatically to
create a temporary trust tag when invoking set-check-invariant-risk
on an expression that is other than one of the symbols :ERROR,
:WARNING, or T.
An environment variable, ACL2_CHECK_INVARIANT_RISK, provides a
convenient way to evaluate one of these forms automatically when
ACL2 is invoked. When that environment variable has a value other
than the empty string, the value is converted to a symbol after
converting to upper-case with the function [string-upcase], and
then corresponding call is make automatically (after loading the
[ACL2-customization] file, if any).
\"error\", \":error\" ==> (set-check-invariant-risk :ERROR)
\"warning\", \":warning\" ==> (set-check-invariant-risk :WARNING)
\"t\" ==> (set-check-invariant-risk T)
\"nil\" ==> (set-check-invariant-risk NIL)
Whether by direct user evaluation or environment variable, these
calls simply set a certain global parameter, 'check-invariant-risk
(technicaly, a [state] global variable). However, they are not
embedded event forms (see [embedded-event-form]: they cannot appear
at the top level of books, [encapsulate] [events], or [progn]
events. A non-nil second (optional) argument causes an
[ACL2-defaults-table] entry to be made, associating the key
:check-invariant-risk with the invariant-risk mode. Thus, the
following forms are embedded event forms. Notice the new ``mode'',
:CLEAR, which behaves as though removing the key
:check-invariant-risk from the [ACL2-defaults-table].
(set-check-invariant-risk :ERROR t)
(set-check-invariant-risk :WARNING t)
(set-check-invariant-risk t t)
(set-check-invariant-risk NIL t)
(set-check-invariant-risk :CLEAR t) ; avoid using table to determine mode
As before, the value NIL requires an active trust tag; but unlike
before, ACL2 does not create a temporary trust tag, but instead
expect the user to have done so already. Note also that changes to
the acl2-defaults-table are automatically local to a book or
[encapsulate] event in which they occur; [ACL2-defaults-table].
Therefore, do not surround the forms just above with [local].
When the [ACL2-defaults-table] associates the key
:check-invariant-risk with any value (as in the calls above) other
than :CLEAR, then the invariant-risk mode is actually the
``minimum'' of that value and the value of the global parameter,
'check-invariant-risk, where the modes are ordered from greatest to
least as shown in the displays above. An [observation] is printed
when the new mode does not change: for example, if you start your
ACL2 session by evaluating (set-check-invariant-risk :ERROR t),
then the invariant-risk mode will be the minimum of the existing
(default) value of :WARNING and the proposed value (newly stored in
the acl2-defaults-table of :ERROR; that minimum is :WARNING, so the
mode will remain :WARNING and an [observation] will be printed to
that effect. You can see all the relevant mode values as follows.
; current invariant-risk mode (:WARNING by default):
(get-check-invariant-risk state)
; invariant-risk mode stored in global parameter 'check-invariant-risk:
(@ check-invariant-risk)
; invariant-risk mode stored in the acl2-defaults-table:
(table acl2-defaults-table :check-invariant-risk)
The following log illustrates the interaction of the two ways of
setting the invariant-risk mode (state global and table).
ACL2 !>(set-check-invariant-risk :error t)
ACL2 Observation in SET-CHECK-INVARIANT-RISK: No change is being made
in the value computed by (GET-CHECK-INVARIANT-RISK STATE). This happens
when the value of state global 'check-invariant-risk is less than the
new table value; see :DOC set-check-invariant-risk.
:ERROR
ACL2 !>(get-check-invariant-risk state)
:WARNING
ACL2 !>(@ check-invariant-risk)
:WARNING
ACL2 !>(set-check-invariant-risk :error)
:ERROR
ACL2 !>(@ check-invariant-risk)
:ERROR
ACL2 !>(get-check-invariant-risk state)
:ERROR
ACL2 !>(set-check-invariant-risk t t)
T
ACL2 !>(get-check-invariant-risk state)
T
ACL2 !>(set-check-invariant-risk :warning)
ACL2 Observation in SET-CHECK-INVARIANT-RISK: No change is being made
in the value computed by (GET-CHECK-INVARIANT-RISK STATE), because
the new value of state global 'check-invariant-risk is greater than
the table value; see :DOC set-check-invariant-risk.
:WARNING
ACL2 !>(get-check-invariant-risk state)
T
ACL2 !>(set-check-invariant-risk :clear t)
:CLEAR
ACL2 !>(get-check-invariant-risk state)
:WARNING
ACL2 !>
Note that the handling of an invariant-risk call of a function, f,
depends on the current invariant-risk mode, not on the mode in
place when f was defined.
It might not be obvious how a given function call could lead to an
ill-guarded call of a [stobj] updater or of a primitive with
invariant-risk such as [aref1]. It should be reasonably
straightforward to write a utility that provides this information;
contact the ACL2 implementors if you want assistance in writing
such a utility.
Subtopics
[Invariant-risk]
Potential slowdown for [program]-mode updates to [stobj]s or
[arrays]")
(SET-CHECKPOINT-SUMMARY-LIMIT
(SET-GAG-MODE)
"Control printing of key checkpoints upon a proof's failure
See [set-gag-mode] for a discussion of key checkpoints.
Examples:
; (Default) When a proof fails, print all key checkpoints before
; induction but at most 3 key checkpoints after induction:
(set-checkpoint-summary-limit (nil . 3))
; When a proof fails, print at most 3 key checkpoints before
; induction but all 3 key checkpoints after induction:
(set-checkpoint-summary-limit (3 . nil))
; When a proof fails, print at most 3 key checkpoints before
; induction and at most 5 key checkpoints after induction:
(set-checkpoint-summary-limit (3 . 5))
; When a proof fails, print at most 3 key checkpoints before
; induction and at most 3 key checkpoints after induction:
(set-checkpoint-summary-limit (3 . 3))
; or equivalently,
(set-checkpoint-summary-limit 3)
; When a proof fails, print all key checkpoints:
(set-checkpoint-summary-limit (nil . nil))
; or equivalently,
(set-checkpoint-summary-limit nil)
; When a proof fails, print no information at all about key checkpoints:
(set-checkpoint-summary-limit t)
General Forms:
(set-checkpoint-summary-limit (n1 . n2))
(set-checkpoint-summary-limit n)
(set-checkpoint-summary-limit t)
where each of n1 and n2 is a natural number or nil. For the second
form, n can be a natural number or nil and is treated as (n . n).
The value t inhibits all printing of checkpoint summary
information. The values n1 and n2 determine printing of key
checkpoints generated before the first induction and generated
after the first induction, respectively, where at most n1 or n2
(respectively) such key checkpoints are printed unless the value is
nil, in which case there is no limitation.
The argument x for set-checkpoint-summary-limit, as described above,
may be quoted, i.e. supplied as 'x or (quote x). Thus, you may use
the keyword form (see [keyword-commands]) if you prefer, for
example:
:set-checkpoint-summary-limit (nil . 3)")
(SET-COMPILE-FNS
(COMPILATION)
"Have each function compiled as you go along.
Example Forms:
(set-compile-fns t) ; new functions compiled after DEFUN
(set-compile-fns nil) ; new functions not compiled after DEFUN
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Also see [comp], because it may be more efficient in some Common
Lisps to compile many functions at once rather than to compile each
one as you go along.
General Form:
(set-compile-fns term)
where term is a variable-free term that evaluates to t or nil. This
macro is equivalent to
(table acl2-defaults-table :compile-fns term)
and hence is [local] to any [books] and [encapsulate] [events] in
which it occurs; see [ACL2-defaults-table]. However, unlike the
above simple call of the [table] event function (see [table]), no
output results from a set-compile-fns event.
Set-compile-fns may be thought of as an event that merely sets a flag
to t or nil. The flag's effect is felt when functions are defined,
as with [defun]. If the flag is t, functions are automatically
compiled after they are defined, as are their executable
counterparts (see [executable-counterpart]). Otherwise, functions
are not automatically compiled. Exception: The flag has no effect
when explicit compilation is suppressed; see [compilation].
Because set-compile-fns is an event, the old value of the flag is
restored when a set-compile-fns event is undone.
Even when :set-compile-fns t has been executed, functions are not
individually compiled when processing an [include-book] event. If
you wish to include a book of compiled functions, we suggest that
you first certify it with the [compilation] flag set (see
[certify-book]) or else compile the book by supplying the
appropriate load-compiled-file argument to [include-book]. More
generally, [compilation] via set-compile-fns is suppressed when the
[state] global variable [ld-skip-proofsp] has value
'[include-book].")
(SET-COMPILER-ENABLED
(COMPILATION)
"Disable [compilation].
For a thorough discussion of this utility, see [compilation].
Probably its most common use is the following, in order to prohibit
[include-book] from attempting to include compiled files:
(set-compiler-enabled nil state)")
(SET-DEBUGGER-ENABLE
(DEBUGGING)
"Control whether Lisp errors and breaks invoke the Lisp debugger
Forms (see below for explanations and GCL exceptions):
(set-debugger-enable t) ; enable breaks into the raw Lisp debugger
(set-debugger-enable :break) ; same as above
:set-debugger-enable t ; same as above
(set-debugger-enable :break-bt) ; as above, but print a backtrace first
(set-debugger-enable :bt-break) ; as above, but print a backtrace first
(set-debugger-enable :bt) ; print a backtrace but do not enter debugger
(set-debugger-enable :never) ; disable all breaks into the debugger
(set-debugger-enable nil) ; disable debugger except when calling break$
Introduction. Suppose we define foo in :[program] mode to take the
[car] of its argument. This can cause a raw Lisp error. ACL2 will
then return control to its top-level loop unless you enable the
Lisp debugger, as shown below (except: the error message can take
quite a different form in non-ANSI GCL).
ACL2 !>(defun foo (x) (declare (xargs :mode :program)) (car x))
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FOO
ACL2 !>(foo 3)
***********************************************
************ ABORTING from raw Lisp ***********
Error: Attempt to take the car of 3 which is not listp.
***********************************************
If you didn't cause an explicit interrupt (Control-C),
then the root cause may be call of a :program mode
function that has the wrong guard specified, or even no
guard specified (i.e., an implicit guard of t).
See :DOC guards.
To enable breaks into the debugger (also see :DOC acl2-customization):
(SET-DEBUGGER-ENABLE T)
ACL2 !>(SET-DEBUGGER-ENABLE T)
<state>
ACL2 !>(foo 3)
Error: Attempt to take the car of 3 which is not listp.
[condition type: TYPE-ERROR]
Restart actions (select using :continue):
0: Abort entirely from this (lisp) process.
[Current process: Initial Lisp Listener]
[1] ACL2(1): [RAW LISP]
Details. ACL2 usage is intended to take place inside the ACL2
read-eval-print loop (see [lp]). Indeed, in most Lisp
implementations ACL2 comes up inside that loop, as evidenced by the
prompt:
ACL2 !>
However, one can occasionally hit a raw Lisp error. Here is the above
example again, this time for a GCL implementation, which
unfortunately gives a slightly less aesthetic report.
ACL2 !>(foo 3)
Error: 3 is not of type LIST.
Fast links are on: do (si::use-fast-links nil) for debugging
Error signalled by CAR.
Backtrace: funcall > system:top-level > lisp:lambda-closure > lp > acl2_*1*_acl2::foo > foo > car > system:universal-error-handler > system::break-level-for-acl2 > let* > UNLESS
ACL2 !>
Here, the user has defined foo in :[program] mode, with an implicit
[guard] of t. The ACL2 evaluator therefore called the Lisp
evaluator, which expected nil or a [consp] argument to [car].
By default, ACL2 will return to its top-level loop (at the same level
of [ld]) when there is a raw Lisp error, as though a call of [er]
with flag HARD has been evaluated. If instead you want to enter the
raw Lisp debugger in such cases, evaluate the following form.
(set-debugger-enable t)
You can subsequently return to the default behavior with:
(set-debugger-enable nil)
Either way, you can enter the Lisp debugger from within the ACL2 loop
by evaluating ([break$]). If you want break$ disabled, then
evaluate the following, which disables entry to the Lisp debugger
not only for Lisp errors but also when executing (break$).
(set-debugger-enable :never)
The discussion above also applies to interrupts (from Control-C) in
some, but not all, host Common Lisps --- perhaps all except for
non-ANSI GCL, where interrupts will likely always put you into the
debugger.
It remains to discuss options :break, :bt, :break-bt, and :bt-break.
Option :break is synonymous with option t, while option :bt prints
a backtrace. Options :break-bt and :bt-break are equivalent, and
each has the combined effect of :bt and :break: a backtrace is
printed and then the debugger is entered.
Note that set-debugger-enable applies not only to raw Lisp errors,
but also to ACL2 errors: those affected by [break-on-error].
However, for ACL2 errors, entering the debugger is controlled only
by break-on-error, not by set-debugger-enable. For ACL2 errors
encountered after evaluating (break-on-error t), the
set-debugger-enable values of :bt, :break-bt, and :bt-break will
result in the same effect: in many host LIsps, this effect will be
to cause a backtrace to be printed.
Remark for Common Lisp hackers (except for the case that the host
Lisp is non-ANSI GCL). You can customize the form of the backtrace
printed by entering raw Lisp (with :q) and then redefining function
print-call-history, whose definition immediately precedes that of
break-on-error in ACL2 source file ld.lisp. Of course, all bets are
off when defining any function in raw Lisp, but as a practical
matter you are probably fine as long as your books are ultimately
certified with an unmodified copy of ACL2. If you come up with
improvements to print-call-history, please pass them along to the
ACL2 implementors.")
(SET-DEFAULT-BACKCHAIN-LIMIT
(BACKCHAIN-LIMIT)
"Sets the default backchain-limit used when admitting a rule
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Moreover, its effect is to set the [ACL2-defaults-table], and hence
its effect is [local] to the book or [encapsulate] form containing
it; see [ACL2-defaults-table].
This event sets the default [backchain-limit] used when a new
[rewrite], [linear], [meta], or [type-prescription] rule is
admitted. Its value may be a two-element list whose elements are
each either nil or a non-negative integer. Its value x may also be
nil or a non-negative integer, which is treated as the two element
list (x x).
The first element of the list is used to limit backchaining for a
rule of class [type-prescription] while the second element is used
to limit backchaining for the other three classes of rules
mentioned above. See [backchain-limit] for details about how
backchain-limits are used. The examples below assume that a new
rule doesn't itself specify a value for :backchain-limit-lst.
:set-default-backchain-limit nil ; do not impose backchain limits for the
; rule
:set-default-backchain-limit 0 ; allow only type-set reasoning for
; relieving a new rule's hypotheses
:set-default-backchain-limit 500 ; allow backchaining through a new rewrite,
; linear, or meta rule's hypotheses to a
; depth of no more than 500
(set-default-backchain-limit 500) ; same as above
:set-default-backchain-limit (nil 500)
; same as above
(set-default-backchain-limit '(nil 500))
; same as above
(set-default-backchain-limit '(3 500))
; for a new :type-prescription rule, allow
; type-set backchaining to a depth
; of no more than 3; for a new
; rule of class :rewrite, :linear,
; or :meta, allow backchaining to
; a depth of no more than 50
(set-default-backchain-limit '(nil 500))
; do not limit backchaining for a
; new :type-prescription rule; for
; a new rule of class :rewrite,
; :linear, or :meta, allow
; backchaining to a depth of no
; more than 50
The initial default backchain-limit is nil.")
(SET-DEFAULT-HINTS
(DEFAULT-HINTS)
"Set the default hints
Examples:
(set-default-hints '((computed-hint-1 clause)
(computed-hint-2 clause
stable-under-simplificationp)))
(set-default-hints nil)
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It is [local] to the book or [encapsulate] form in which it occurs;
see [set-default-hints!] for a corresponding non-[local] event.
General Form:
(set-default-hints lst)
where lst is a list. Generally speaking, the elements of lst should
be suitable for use as [computed-hints].
Whenever a [defthm] or [thm] command is executed, the default hints
are appended to the right of any explicitly provided :[hints] in
the command. The same applies to [defun]s as well (:hints,
:guard-hints, and (for ACL2(r)) :std-hints). The hints are then
translated and processed just as though they had been explicitly
included.
Technically, we do not put restrictions on lst, beyond that it is a
true list. It would be legal to execute
(set-default-hints '((\"Goal\" :use lemma23)))
with the effect that the given hint is added to subsequent hints
supplied explicitly. An explicit \"Goal\" hint would, however, take
priority, as suggested by the mention above of ``appended to the
right.''
Note that set-default-hints sets the default hints as specified. To
add to or remove from the current default, see [add-default-hints]
and see [remove-default-hints]. To see the current default hints,
see [default-hints].
Finally, note that the effects of set-default-hints,
[add-default-hints], and [remove-default-hints] are [local] to the
book in which they appear. Thus, users who include a book with such
forms will not have their default hints affected by such forms. In
order to export the effect of setting the default hints, use
[set-default-hints!], [add-default-hints!], or
[remove-default-hints!].
For a related feature, which however is only for advanced system
builders, see [override-hints].")
(SET-DEFAULT-HINTS!
(DEFAULT-HINTS)
"Set the default hints non-[local]ly
Please see [set-default-hints], which is the same as
set-default-hints! except that the latter is not [local] to the
[encapsulate] or the book in which it occurs. Probably
[set-default-hints] is to be preferred unless you have a good
reason for wanting to export the effect of this event outside the
enclosing [encapsulate] or book.")
(SET-DEFERRED-TTAG-NOTES
(DEFTTAG)
"Modify the verbosity of TTAG NOTE printing
General Form:
(set-deferred-ttag-notes val state)
where val is t or nil.
See [defttag] for a discussion of trust tags (ttags). By default, a
``TTAG NOTE'' is printed in order to indicate reliance on a ttag.
When many such notes are printed, it may be desirable to avoid
seeing them all. Upon evaluation of the form
(set-deferred-ttag-notes t state)
ACL2 will enter a deferred mode for the printing of ttag notes. In
this mode, only the first ttag note is printed for each top-level
command, and the remainder are summarized before the next top-level
prompt (if any) is printed, hence before the next command is
evaluated. That summary is merely a list of ttags, but the summary
explains that the full ttag notes may be printed with the command
(show-ttag-notes).
Note that (show-ttag-notes) spares you duplicate ttag notes. If you
want to see every ttag note as it would normally appear, for
maximum security, do not evaluate the command
(set-deferred-ttag-notes t state). You can undo the effect of this
command, returning to an immediate mode for printing ttag notes, by
evaluating:
(set-deferred-ttag-notes nil state)")
(SET-DIFFERENCE$
(LISTS ACL2-BUILT-INS)
"Elements of one list that are not elements of another
General Forms:
(set-difference$ l1 l2)
(set-difference$ l1 l2 :test 'eql) ; same as above (eql as equality test)
(set-difference$ l1 l2 :test 'eq) ; same, but eq is equality test
(set-difference$ l1 l2 :test 'equal) ; same, but equal is equality test
(Set-difference$ l1 l2) equals a list that contains the [member]s of
l1 that are not [member]s of l2. More precisely, the resulting list
is the same as one gets by deleting the members of l2 from l1,
leaving the remaining elements in the same order as in l1. The
optional keyword, :TEST, has no effect logically, but provides the
test (default [eql]) used for comparing members of the two lists.
The [guard] for a call of set-difference$ depends on the test. In all
cases, both arguments must satisfy [true-listp]. If the test is
[eql], then one of the arguments must satisfy [eqlable-listp]. If
the test is [eq], then one of the arguments must satisfy
[symbol-listp].
See [equality-variants] for a discussion of the relation between
set-difference$ and its variants:
(set-difference-eq l1 l2) is equivalent to (set-difference$ l1 l2
:test 'eq);
(set-difference-equal l1 l2) is equivalent to (set-difference$ l1 l2
:test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function set-difference-equal.
Function: <set-difference-equal>
(defun
set-difference-equal (l1 l2)
(declare (xargs :guard (and (true-listp l1) (true-listp l2))))
(cond ((endp l1) nil)
((member-equal (car l1) l2)
(set-difference-equal (cdr l1) l2))
(t (cons (car l1)
(set-difference-equal (cdr l1) l2)))))
Set-difference$ is similar to the Common Lisp primitive
set-difference. However, Common Lisp does not specify the order of
elements in the result of a call of set-difference.")
(SET-DIFFERENCE-EQ (POINTERS)
"See [set-difference$].")
(SET-DIFFERENCE-EQUAL (POINTERS)
"See [set-difference$].")
(SET-DIFFERENCE-THEORIES
(THEORIES THEORY-FUNCTIONS)
"Difference of two [theories]
Example:
(set-difference-theories (current-theory :here)
'(fact (fact)))
General Form:
(set-difference-theories th1 th2)
where th1 and th2 are [theories] (see [theories]). To each of the
arguments there corresponds a runic theory. This function returns
the set-difference of those two runic [theories], represented as a
list and ordered chronologically. That is, a [rune] is in the
result iff it is in the first runic theory but not in the second.
The standard way to ``disable'' a theory, lst, is: (in-theory
(set-difference-theories (current-theory :here) lst)).
This ``function'' is actually a macro that expands to a term
mentioning the single free variable [world]. When theory
expressions are evaluated by [in-theory] or the :[in-theory] hint,
[world] is bound to the current ACL2 [world].")
(SET-DUPLICATE-KEYS-ACTION
(MACRO-ARGS MACROS PROGRAMMING ADVANCED-FEATURES)
"Control action for macro calls with duplicate keyword arguments
Example Forms:
(set-duplicate-keys-action thm :warning)
(set-duplicate-keys-action my-macro-1 nil)
General Forms:
(set-duplicate-keys-action name :error)
(set-duplicate-keys-action name :warning)
(set-duplicate-keys-action name nil)
where name is a symbol, one that is generally expected to be the name
of a macro.
By default, an error occurs when ACL2 encounters a macro call with
duplicate keys, for example (foo 3 :y 4 :y 5) where :y is a keyword
argument of the macro, foo. However, the event
(set-duplicate-keys-action name val) can be used to determine
whether such duplicate keys cause an error, a warning, or neither,
according to whether val is the keyword :error, :warning, or nil,
respectively.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It is [local] to the book or [encapsulate] form in which it occurs;
see [set-duplicate-keys-action!] for a corresponding non-[local]
event. Indeed, (set-duplicate-keys-action ...) is equivalent to
(local (set-duplicate-keys-action! ...)).")
(SET-DUPLICATE-KEYS-ACTION!
(PROVER-OUTPUT)
"Non-[local] version of [set-duplicate-keys-action]
Please see [set-duplicate-keys-action], which is the same as
set-duplicate-keys-action! except that the latter is not [local] to
the [encapsulate] or the book in which it occurs. Perhaps
[set-duplicate-keys-action] is to be preferred unless you have a
good reason for wanting to export the effect of this event outside
the enclosing [encapsulate] or book.")
(SET-ENFORCE-REDUNDANCY
(REDUNDANT-EVENTS)
"Require most events to be redundant
General Forms:
(set-enforce-redundancy nil) ; do not require redundancy (default)
(set-enforce-redundancy t) ; most events (see below) must be redundant
(set-enforce-redundancy :warn) ; warn for most non-redundant events
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
General Form:
(set-enforce-redundancy flag)
where flag is nil, t, or :warn, as indicated above. This macro is
essentially equivalent to
(table acl2-defaults-table :enforce-redundancy flag)
and hence is [local] to any [books] and [encapsulate] [events] in
which it occurs; see [ACL2-defaults-table]. However, unlike the
above simple call of the [table] event function (see [table]), no
output results from a set-enforce-redundancy event.
Set-enforce-redundancy may be thought of as an event that merely sets
a flag as indicated above, which determines whether most [events],
including [defun] and [defthm] events, are allowed to be redundant;
see [redundant-events]. The exceptions are [deflabel], [defpkg],
[encapsulate], [include-book], [push-untouchable],
[remove-untouchable], [set-body], and [table] [events]. Any other
type of non-redundant event will cause an error if flag is t and a
warning if flag is nil, except in the course of carrying out an
[include-book] form.
Note that because [table] [events] that set the [ACL2-defaults-table]
are implicitly [local], set-enforce-redundancy events are ignored
when including books. However, the presence of the event
(set-enforce-redundancy t) in a book guarantees that its subsequent
definitions and theorems are redundant. This can be a useful
property to maintain in library development, as we now describe.
An example of the use of this form can be found in the community
[books] under directory books/rtl/rel4/. The intention in that
directory has been to put all the gory details in subdirectories
support/ and arithmetic/, so that the books in subdirectory lib/
contain only the ``exported'' definitions and theorems. This
approach is useful for human readability. Moreover, suppose we want
to prove new theorems in lib/. Typically we wish to prove the new
theorems using the existing books in lib/; however, our methodology
demands that the proofs go into books in support/. If every theorem
in lib/ is redundant, then we can develop the proofs in lib/ but
then when we are done, move each book with such proofs into
support/ as follows. In any such book, we first replace
[include-book] forms referring to books in lib/ by [include-book]
forms referring to corresponding books in support/ and/or
arithmetic/. Then, we add suitable [in-theory] events to get us
back into the original lib/ proof environment.
The default behavior of the system is as though the
:enforce-redundancy value is nil. The current behavior can be
ascertained by evaluating the following form.
(cdr (assoc-eq :enforce-redundancy (table-alist 'acl2-defaults-table wrld)))")
(SET-EVISC-TUPLE
(IO)
"Control suppression of details when printing
ACL2 output is generally printed in full. However, ACL2 can be
directed to abbreviate, or ``eviscerate'', objects before printing
them, though the use of a so-called ``evisc-tuple''. See
[evisc-tuple] for a discussion of evisc-tuples. The utility
set-evisc-tuple modifies certain global evisc-tuples, as explained
below, to affect the extent to which ACL2 eviscerates objects
during printing, for example during proof output or when printing
top-level evaluation results.
General Form:
(set-evisc-tuple evisc-tuple ; a legal evisc-tuple, or :DEFAULT
:iprint val ; one of *iprint-actions*
:sites sites) ; either :ALL, or an element or a subset of
; the list of legal sites (see below)
where the value of :iprint is passed to [set-iprint], :sites :all
abbreviates :sites '(:term :ld :trace :abbrev :gag-mode), and other
documentation is provided below. Note that all arguments are
evaluated.
See [without-evisc] for how to avoid evisceration for ACL2 output.
The following example illustrates an invocation of set-evisc-tuple
that limits the print-level to 3 --- only three descents into list
structures are permitted before eviscerating a subterm --- and
limits the print-length to 4 --- only the first four elements of
any list structure will be printed.
ACL2 !>(set-evisc-tuple (evisc-tuple 3 ; print-level
4 ; print-length
nil ; alist
nil ; hiding-cars
)
:iprint :same ; better yet, T
:sites :all)
(:TERM :LD :TRACE :ABBREV)
ACL2 !>'((a b ((c d)) e f g) u v w x y)
((A B (#) E ...) U V W ...)
ACL2 !>
We recommend however using :iprint t so that eviscerated terms may be
read back in; see [set-iprint]. Indeed, the :iprint argument is
required as a reminder to the user to consider that issue, unless
iprinting has been enabled at least once. If :sites or a required
:iprint argument is omitted, however, ACL2 will query the user for
the missing arguments rather than causing an error.
ACL2 eviscerates by default only in a few cases, primarily in
informational messages for errors, warnings, and queries (i.e., in
the :EVISC case below). Users can modify the default behavior by
supplying a suitable argument to set-evisc-tuple. The argument may
be :default, which denotes the evisceration provided when ACL2
starts up. Otherwise that argument is an evisc-tuple, which is
either nil (no evisceration) or as described above. Moreover, there
are four evisc-tuple ``evisceration contexts'', each with its own
evisceration control. The value returned by set-evisc-tuple
indicates the evisceration contexts whose evisc-tuple has been set.
The evisceration contexts are as follows, all of which use a
default value of nil for the hiding-cars. Accessors are also shown
for retrieving the corresponding evisc-tuple.
* :TERM --- used for printing terms. The accessor is (term-evisc-tuple
flg state), where flg is ignored if set-evisc-tuple has been
called for :term with value other than :default, and otherwise
(hence initially): a flg of nil indicates an evisc-tuple of
nil, and otherwise the term-evisc-tuple has a print-level of 3
and print-length of 4.
* :ABBREV --- used for printing informational messages for errors,
warnings, and queries. Initially, the alist abbreviates the
ACL2 world, print-level is 5, and print-level is 7. The
accessor is (abbrev-evisc-tuple state).
* :GAG-MODE --- used for printing induction schemes (and perhaps, in
the future, for other printing) when [gag-mode] is on. If
gag-mode is off, the value used for this [evisc-tuple] is
(term-evisc-tuple nil state). But if gag-mode is on (i.e.,
(gag-mode) evaluates to a non-nil value), then with one
exception, the value is an evisc-tuple or nil, to be used in
gag-mode for printing of induction schemes and, during proofs,
the ``The non-trivial part of the guard conjecture''. The
exceptional value is t, which indicates that in gag-mode, no
printing of induction schemes should be and the guard
conjecture should be printed using (term-evisc-tuple t state).
The accessor is (gag-mode-evisc-tuple state).
* :LD --- used by the ACL2 read-eval-print loop. The accessor is
([ld-evisc-tuple] state).
* :TRACE --- used for printing [trace] output. No accessor is available
(though in raw Lisp, (trace-evisc-tuple) returns the
trace-evisc-tuple).
Each context ectx also has an updater, (set-ectx-evisc-tuple val
state), where val is a legal value for set-evisc-tuple as described
above: :default or an [evisc-tuple] (possibly nil).
Note that the [break-rewrite] commands and the [proof-checker]
generally do their printing using the term-evisc-tuple.")
(SET-FC-CRITERIA
(FORWARD-CHAINING-REPORTS)
"To set the tracking criteria for forward chaining reports
Examples:
(set-fc-criteria) ; shut off all tracking
(set-fc-criteria nil)
(set-fc-criteria t) ; to track all forward chaining
(set-fc-criteria (t t t))
(set-fc-criteria
((:FORWARD-CHAINING LEMMA1) ; track all uses of LEMMA1,
t
t)
((:FORWARD-CHAINING LEMMA2) ; uses of LEMMA2 triggered
(ALISTP (BASIC-MAPPER A B)) ; by this specific ALISTP term
t)
(t t (TRUE-LISTP (DLT D)))) ; and every rule deriving
; this TRUE-LISTP term.
General Forms:
(set-fc-criteria nil)
(set-fc-criteria t)
(set-fc-criteria triple1 triple2 ...)
where each triple is of the form (rune inst-trigger inst-concl). If
rune is non-t is must be a forward chaining [rune]. The other two
components, inst-trigger and inst-concl, if non-t, must be terms.
The list of all the triples supplied is called the ``criteria.'' In
the form (set-fc-criteria nil), the criteria used is the empty list
of triples. (Technically, supplying nil as a triple ``ought'' to be
an error, but it is a more ``natural'' way to say the list of
criteria is empty than to use the correct form (set-fc-criteria).)
In the form (set-fc-criteria t) the criteria used is the list
containing the single triple (t t t).
This function sets the tracking criteria for forward chaining
reporting. See [forward-chaining-reports] for a general discussion
of tracking and reporting forward chaining activity.
Think of the forward chaining criteria as a list of triples,
representing a disjunction of conjunctions. The activation of a
:[forward-chaining] rune by some triggering term in the current
context satisfies the criteria if it satisfies one of the triples.
To satisfy the triple (rune inst-trigger inst-concl), the
activation must satisfy each component of the triple. Any t
component is always satisfied. If rune is non-t it is satisfied if
the activation is for the given rune. If inst-trigger is non-t, it
is satisfied if the activation is triggered by the given term.
(``Inst-trigger'' stands for ``instantiated trigger.'' It is not
the trigger term of the rule but is supposed to be an instance of
that term that you believe will arise in some proof attempt you are
debugging -- an instance you want to ``watch'' as it fires the
rule.) If inst-concl is non-t, it is satisfied if the activation
could possibly derive the conclusion given. (Again, ``inst-concl''
stands for ``instantiated conclusion'' and shows the term in your
problem that you expect to be derived by forward chaining.)
Note that if the criteria is empty, it is never satisfied, so
tracking is turned off. If the criteria is the singleton list
containing just the triple (t t t), then every activation satisfies
it and so all :forward chaining rules are tracked.
See [forward-chaining-reports] for details.")
(SET-FC-REPORT-ON-THE-FLY
(FORWARD-CHAINING-REPORTS)
"To determine when forward-chaining reports are printed
Examples: (set-fc-report-on-the-fly t)
(set-fc-report-on-the-fly nil)
If the flag is set to t, forward chaining tracking reports are
printed when forward chaining occurs. If the flag is set to nil,
very short reports (giving just the caller and the report number)
are printed during forward chaining but you can use [fc-report] to
see the full report afterwards.
Since nothing is tracked when the criteria is nil, this function also
prints out the current criteria to remind you of what it is.
The flag manipulated by this function does not shut off tracking. It
only determines whether reports are printed on-the-fly or not. To
shut off tracking [set-fc-criteria].
See [forward-chaining-reports] for details.")
(SET-FMT-HARD-RIGHT-MARGIN
(IO ACL2-BUILT-INS)
"Set the right margin for formatted output
In this documentation topic we discuss setting of both a ``soft'' and
a ``hard'' right margin.
Example Forms:
(set-fmt-soft-right-margin 55 state) ; set soft right margin to 55
(set-fmt-hard-right-margin 68 state) ; set hard right margin to 68
[Fmt] and related functions insert linebreaks when lines get too
long. A linebreak is inserted at an aesthetically appropriate point
once the column exceeds the value of (@ fmt-soft-right-margin). If
however the column exceeds the value of (@ fmt-hard-right-margin),
then a linebreak is soon inserted. Such a ``hard'' linebreak
follows the insertion of a backslash (\\) character unless [fmt!],
[fms!], or [fmt1!] is used, or state global write-for-read is true.")
(SET-FMT-SOFT-RIGHT-MARGIN
(IO ACL2-BUILT-INS)
"Set the soft right margin for formatted output
See [set-fmt-hard-right-margin] for a discussion of the soft and hard
right margin for formatted output.")
(SET-GAG-MODE
(PROVER-OUTPUT)
"Modify the nature of proof output
Examples:
:set-gag-mode t ; enable gag-mode, suppressing most proof commentary
(set-gag-mode t) ; same as above
:set-gag-mode :goals ; same as above, but print names of goals when produced
:set-gag-mode nil ; disable gag-mode
General Forms:
(set-gag-mode val)
:set-gag-mode val
where val is one of t, nil, or :goals.
The basic idea of [gag-mode] is to avoid much of the verbose output
from the theorem prover, leaving only output that is expected to be
helpful. The first two forms below set gag-mode on, while the other
turns it off; these may be placed in your ACL2 customization file;
see [ACL2-customization].
(set-gag-mode :goals) ; (default) avoid most prover output; show goal names
(set-gag-mode t) ; avoid most prover output; also, hide goal names
(set-gag-mode nil) ; allow prover output
Gag-mode focuses attention on so-called ``key checkpoints''. By
default, a checkpoint is a goal that cannot be simplified. (Below
we discuss how to change this default.) A key checkpoint is a
checkpoint that is not descended from another checkpoint.
(Technical point: ``descended'' signifies that both goals are at
the top level in the same forcing round, or are in the same proof
by induction.) Successful ACL2 users generally focus their
attention on key checkpoints, or less often, induction schemes. (To
suppress or abbreviate induction schemes in gag-mode, see
[set-evisc-tuple], specifically, the discussion of :GAG-MODE.) For
a discussion of how to use ACL2 prover output in an effective
manner, see [the-method], and see
[introduction-to-the-theorem-prover] for a more detailed tutorial.
In gag-mode, a key checkpoint is only displayed when ACL2 is unable
to make any further progress on that goal or some descendent of it,
other than with a proof by induction.
Evaluation of set-gag-mode t enters gag-mode, so that only key
checkpoints are printed. Evaluation of set-gag-mode :goals also
enters gag-mode, but will additionally cause the name of a goal to
be printed as soon as it is generated (by invoking
[set-print-clause-ids]). The :goals setting is the default, and is
useful for cases in which the prover spends very little of its time
generating goals to be proved by induction, yet you want to see
that it is making progress. For finer-grained feedback about the
simplifier's activity, see [dmr].
The current value of [gag-mode] is returned by a macro of the same
name:
(gag-mode) ; evaluates to t, nil, or :goals
An alternative to gag-mode is to use proof-trees; see [proof-tree].
With proof-trees it is not so important to avoid excessive prover
output, since the proof-tree display provides structure that makes
it easy to monitor proof attempts and navigate output for a proof
that has failed or seems to be failing. Still, output can take time
to print, so you may get better performance with gag-mode.
The intention of gag-mode is to show you only the parts of a proof
attempt that are relevant for debugging a failure; additional
output is generally more likely to be distracting than truly
helpful. But on occasion you may want to see the full proof output
after an attempt made with gag-mode. This can be done provided
proof output is not inhibited (see [set-inhibit-output-lst]) during
the proof attempt; see [pso] and see [pso!]. Since set-gag-mode
takes responsibility for the saving of output, related utility
[set-saved-output] is disabled when gag-mode is active. Also note
that calling set-gag-mode erases the currently saved output, if
any.
You may notice that gag-mode tends to print relatively little
information about goals pushed for proof by sub-induction --- i.e.,
a proof of *i.j, *i.j.k, etc. That feature emphasizes that
unsuccessful sub-inductions should generally be avoided, not
analyzed for ways to make them succeed. Instead, the key checkpoint
that generated the goal pushed for this induction is more
appropriate to analyze. In general, the ``higher level'' the
checkpoint, the more worthy it is of attention. Thus, we suggest
that look at the top-level checkpoints before looking at those
labeled ``Key checkpoints under a top-level induction''.
We conclude with remarks for advanced users.
The notion of ``checkpoint'' can be modified by the user. The
default, as discussed above, is for a checkpoint to be a goal that
cannot be simplified. Put differently, a checkpoint is acted on by
one of the processes in the value of the form (@
checkpoint-processors); see [@]. Any or all of the symbols
eliminate-destructors-clause, fertilize-clause, generalize-clause,
or eliminate-irrelevance-clause can be removed from this value in
order that invocation of the corresponding proof process does not
cause its input goal to be labeled a checkpoint. For example, if
you do not want destructor elimination to be treated differently
from simplification for purposes of labeling checkpoints, you can
evaluate the following form (see [assign]):
(assign checkpoint-processors
(remove 'eliminate-destructors-clause
(@ checkpoint-processors)))
Note that the value of (@ checkpoint-processors) also affects the
proof tree display; see [proof-tree-details]. End of Remark.)
See [set-evisc-tuple], in particular the discussion there of
:GAG-MODE, for how to influence slightly just what is printed in
gag-mode.
Subtopics
[Set-checkpoint-summary-limit]
Control printing of key checkpoints upon a proof's failure
[Set-saved-output]
Save proof output for later display with :[pso] or :[pso!]")
(SET-GC-STRATEGY
(MISCELLANEOUS ACL2-BUILT-INS)
"Set the garbage collection strategy (CCL only)
Note: This macro has no effect unless the host Lisp is CCL.
General Forms:
(set-gc-strategy :egc) ; the default: EGC is on, full GC is not delayed
(set-gc-strategy :delay) ; EGC is off, full GC is delayed
(set-gc-strategy :current) ; same as replacing :current by the latest
; strategy set (:egc or :delay)
(set-gc-strategy strategy threshold)
; Same as (set-gc-strategy strategy), but sets
; threshold to the indicated number of bytes
; (see below)
Logically, (set-gc-strategy op) returns op. But in some host Lisps
(currently CCL only), it changes how garbage collection is invoked.
Exactly how that is done is best understood by reading the ACL2
source code, starting with set-gc-strategy. Here we document what
most users might want to know about this utility, assuming they are
using CCL. We defer discussion of the optional second argument,
threshold, to the end.
Normally the default garbage collection strategy will probably be
fine. That default has the ephemeral garbage collector (EGC)
enabled. But in jobs that stress [hons], or perhaps memoization
(see [memoize]) or [fast-alists], it might be useful to switch to a
strategy that disables EGC but also significantly delays garbage
collection. To switch to that delaying strategy:
(set-gc-strategy :delay)
Then, you can return to the default strategy, re-enabling EGC and no
longer causing delays in garbage collection, as follows.
(set-gc-strategy :egc)
It is also legal to invoke (set-gc-strategy :current), which is
equivalent to replacing :current by the current strategy; see
[gc-strategy].
If you want to change the gc-strategy during certification of a book,
but not when including that book, you can place your call of
set-gc-strategy inside [value-triple], for example as follows.
(value-triple (set-gc-strategy :delay))
The following variant causes the [gc-strategy] to be modified when
including the book as well.
(value-triple (set-gc-strategy :delay) :on-skip-proofs t)
This capability might be extended to other host Lisps in the future,
especially if ACL2 users provide suggestions for how to do so.
Note that the default behavior can be changed to :delay at ACL2 build
time, by setting Make variable ACL2_EGC_ON=nil when building an
ACL2 executable.
The threshold argument
When a second argument is supplied in a call of set-gc-strategy, it
must be either nil, which is equivalent to supplying no second
argument, or else a positive integer. This positive integer will be
the ``GC threshold'' number of bytes CCL will try to ensure are
available before the next full garbage collection. The default
(i.e., the value used when the second argument is nil or is
omitted) is the minimum of the following two values: 1/2 GB, and
1/32 of physical memory (or 1/32 of 4 GB, if the physical memory
cannot be determined). (Technical note: The GC threshold is stored
in raw Lisp variable *gc-min-threshold*.)")
(SET-GUARD-CHECKING
(GUARD)
"Control checking [guard]s during execution of top-level forms
Detailed comments about the arguments of this function may be found
elsewhere: see [guard-evaluation-table]. Here we provide an
introduction to the use of set-guard-checking.
New users are encouraged to execute one of the following forms in
order to avoid evaluation errors due to [guard]s:
(set-guard-checking :none)
(set-guard-checking nil)
The former avoids all guard-checking on user-defined functions and
should generally work fine for new users, the only drawback being
efficiency loss on compute-intensive problems. All settings other
than :none check guards, but a value of nil allows evaluation to
continue in the logic when guards fail (avoiding the raw Lisp
definition in that case).
You may put one of the above forms in the \"acl2-customization.lsp\"
file in your current directory (see [cbd]) or your home directory;
see [ACL2-customization].
Note that [guard]s are not part of the ACL2 logic, and hence new
users can completely ignore the notion of [guard] (and the rest of
this documentation section after this paragraph!). For example,
(car 3) and nil can be proved equal in the ACL2 logic, as follows,
even though the [guard] on [car] requires its first argument to be
a [cons] pair or nil.
(thm (equal (car 3) nil))
Moreover, unless your functions or top-level forms call built-in ACL2
functions that are defined in :[program] mode, the following
property will hold.
Evaluation of (set-guard-checking :none) will allow evaluation of
forms such as (car 3) to take place without error in the top
level loop, not only when proving theorems.
If you feel bold, then you may wish to read the rest of this
documentation topic; also see [guard].
See [guard-evaluation-table] for a succinct table, with associated
discussion, that covers in detail the material presented in the
rest of the present topic.
The top-level ACL2 loop has a variable which controls which sense of
execution is provided. To turn ``[guard] checking on,'' by which we
mean that [guard]s are checked at runtime, execute the top-level
form :set-guard-checking t. To allow guard violations, do
:set-guard-checking nil, or do :set-guard-checking :none to turn
off all guard-checking, so that raw Lisp definitions of
user-defined functions are avoided unless their [guard] is t. The
status of guard-checking is reflected in the [prompt].
ACL2 !>
means [guard] checking is on and
ACL2 >
means [guard] checking is off. The exclamation mark can be thought of
as ``barring'' certain computations. The absence of the mark
suggests the absence of error messages or unbarred access to the
logical axioms. Thus, for example
ACL2 !>(car 'abc)
will signal an error, while
ACL2 >(car 'abc)
will return nil.
We will return at the end of this documentation topic to discuss two
other values, :all and :nowarn, for :set-guard-checking. We also
note that evaluation of built-in :program mode functions always
takes place in raw Lisp.
Whether [guard]s are checked during evaluation is independent of the
[default-defun-mode]. We note this simply because it is easy to
confuse ``:[program] mode'' with ``evaluation in Common Lisp'' and
thus with ``[guard] checking on;'' and it is easy to confuse
``:[logic] mode'' with ``evaluation in the logic'' and with
``[guard] checking off.'' But the [default-defun-mode] determines
whether newly submitted definitions introduce programs or add
logical axioms. That mode is independent of whether evaluation
checks [guard]s or not. You can operate in :[logic] mode with
runtime [guard] checking on or off. Analogously, you can operate in
:[program] mode with runtime [guard] checking on or off.
For further discussion on evaluation and guards see
[guards-and-evaluation], in particular the exception for safe-mode
in the ``Aside'' there. See [guard] for a general discussion of
[guard]s.
Now we fulfill our promise above to discuss two other values for
:set-guard-checking:
:set-guard-checking :nowarn
:set-guard-checking :all
The meaning of these values is perhaps best described by the
following example provided by David Rager.
ACL2 !>(defun my-test (expr)
(declare (xargs :guard (true-listp expr)
:verify-guards nil))
(if (atom expr)
expr
(cons (my-test (car expr))
(my-test (cdr expr)))))
The admission of MY-TEST is trivial, using the relation O< (which is
known to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT EXPR). We could deduce no constraints on the type of MY-
TEST. However, in normalizing the definition we used primitive type
reasoning.
Summary
Form: ( DEFUN MY-TEST ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: None
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
MY-TEST
ACL2 !>(my-test '(a b c))
ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited
on recursive calls of the executable counterpart (i.e., in the ACL2
logic) of MY-TEST. To check guards on all recursive calls:
(set-guard-checking :all)
To leave behavior unchanged except for inhibiting this message:
(set-guard-checking :nowarn)
(A B C)
ACL2 !>
If you think about evaluation of (my-test '(a b c)), you will see
that it leads to the recursive call (my-test 'a), which one might
expect to cause a guard violation since the symbol a is not a
[true-listp]. However, as the warning above explains, we do not by
default check guards on recursive calls. The reason is efficiency
--- imagine a simple definition with a guard that is slow to
evaluate. The values :nowarn and :all for :set-guard-checking have
been introduced as ways of dealing with the above warning. The
value :nowarn simply turns off the warning above. The value :all
causes all guards to be checked, even on recursive calls and even
on all calls of non-built-in :[program] mode functions --- unless,
of course, a call is made of a function whose guard has been
verified (see [verify-guards]), where the arguments satisfy the
guard, in which case the corresponding call is made in raw Lisp
without subsidiary guard-checking. We still say that
``guard-checking is on'' after :set-guard-checking is invoked with
values t, :nowarn, and :all, otherwise (after value nil) we say
``guard-checking is off.
For technical reasons, :all does not have its advertised effect in
the case of built-in :[program]-mode functions. If you are
interested in this technical detail, see the comment ``In the
boot-strap world...'' in source function oneify-cltl-code.
We conclude with a remark about the use of :set-guard-checking for
experimenting with ACL2 as a logic or as a programming language. If
one views ACL2 as a logic, one may wish to use :set-guard-checking
:none, while if instead one views ACL2 as a functional programming
language, one may wish to use :set-guard-checking :all. The
following transcript illustrates this distinction by way of
example. Specifically, (car 3) is equal to nil in the ACL2 logic,
but may be viewed as a programming error. The default of
:set-guard-checking t is problematic for learning ACL2 using
:[program] mode functions, since one can get raw Lisp errors. In
the example below, the raw Lisp error occurs because foo implicitly
has a [guard] of t, hence (foo 3) is evaluated in raw Lisp, which
leads to a raw Lisp call of c[(car 3)].
ACL2 !>(defun foo (x)
(declare (xargs :mode :program))
(car x))
Summary
Form: ( DEFUN FOO ...)
Rules: NIL
Warnings: None
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
FOO
ACL2 !>(foo 3)
Error: Attempt to take the car of 3 which is not listp.
[condition type: TYPE-ERROR]
Restart actions (select using :continue):
0: Abort entirely from this (lisp) process.
[Current process: Initial Lisp Listener]
[1] ACL2(1): [RAW LISP] :pop
ACL2 !>:set-guard-checking :none
Turning off guard checking entirely. To allow execution in raw Lisp
for functions with guards other than T, while continuing to mask guard
violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking.
ACL2 >(foo 3)
NIL
ACL2 >:set-guard-checking :all
Turning guard checking on, value :ALL.
ACL2 !>(foo 3)
ACL2 Error in TOP-LEVEL: The guard for the function symbol CAR, which
is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
call (CAR 3). See :DOC trace for a useful debugging utility. See :DOC
set-guard-checking for information about suppressing this check with
(set-guard-checking :none), as recommended for new users.
ACL2 !>")
(SET-GUARD-MSG
(GUARD DEBUGGING)
"Specify what is printed when a [guard] is violated
This is an advanced feature that may require considerable
understanding of ACL2 programming. ACL2 provides default error
messages for guard violations. However, ACL2 also provides a
[table], guard-msg-table, that allows custom error messages for
guard-checking failures. The macro set-guard-msg provides a
convenient way to update this table. The keys of the table are
symbols, which can be expected to be function symbols or names of
macros. Each value is a (translated) [term] whose only free
variables are world, args, and coda. When guard-checking fails, the
term is evaluated to create a message suitable for \"~@\" formatted
printing directives; see [fmt]. That evaluation is done with world
bound to the current ACL2 logical [world], with args bound to the
actual parameters of the call, and with coda bound to the message
that would typically be printed by default at the end of a guard
violation. (See ACL2 source function guard-er-message-coda for
details, or simply experiment.)
Example
Consider the following example.
(defun foo (x)
(declare (xargs :mode :program :guard (consp x)))
(car x))
(set-guard-msg foo (msg \"An error for call ~x0.\"
(cons 'foo args)))
Corresponding output for a guard violation is as follows.
ACL2 !>(foo 3)
ACL2 Error in TOP-LEVEL: An error for call (FOO 3).
ACL2 !>
Continuing in the same session, suppose we provide this fancier error
message specification.
(set-guard-msg foo
(msg \"An error for call ~x0 in a world of length ~x1.~@2\"
(cons 'foo args)
(length world) ; length of the current ACL2 world
coda))
The corresponding error is shown below. Notice that the coda starts
on a new line, with the same \"See :DOC ...\" message that one would
see if the default error message were supplied for the same guard
violation.
ACL2 !>(foo 3)
ACL2 Error in TOP-LEVEL: An error for call (FOO 3) in a world of length
98582.
See :DOC set-guard-checking for information about suppressing this
check with (set-guard-checking :none), as recommended for new users.
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.
ACL2 !>
The capability shown above for function symbols is also available for
macro names. However, the variable, coda, should not be used for
macro names.")
(SET-IGNORE-OK
(DECLARE DEFUN)
"Allow unused formals and locals without an ignore or ignorable
declaration
Examples:
(set-ignore-ok t)
(set-ignore-ok nil)
(set-ignore-ok :warn)
The first example above allows unused formals and locals, i.e.,
variables that would normally have to be [declare]d ignored or
ignorable. The second example disallows unused formals and locals;
this is the default. The third example allows them, but prints an
appropriate warning.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Moreover, its effect is to set the [ACL2-defaults-table], and hence
its effect is [local] to the book or [encapsulate] form containing
it; see [ACL2-defaults-table].
General Form:
(set-ignore-ok flg)
where flg is either t, nil, or :warn.
One might find this event useful when one is generating function
definitions by an automated procedure, when that procedure does not
take care to make sure that all formals are actually used in the
definitions that it generates.
Note: Defun will continue to report irrelevant formals even if
:set-ignore-ok has been set to t, unless you also use
[set-irrelevant-formals-ok] to instruct it otherwise.")
(SET-INHIBIT-OUTPUT-LST
(PROVER-OUTPUT)
"Control output
Examples:
(set-inhibit-output-lst '(warning))
(set-inhibit-output-lst '(proof-tree prove proof-checker))
(set-inhibit-output-lst *valid-output-names*) ; inhibit all prover output
:set-inhibit-output-lst (proof-tree prove)
General Form:
(set-inhibit-output-lst lst)
where lst is a form (which may mention [state]) that evaluates to a
list of names, each of which is the name of one of the following
``kinds'' of output produced by ACL2.
error error messages
warning warnings other than those related to soundness
warning! warnings (of all degrees of importance)
observation observations
prove commentary produced by the theorem prover
proof-checker commentary produced by the proof-checker
event non-proof commentary produced by events such as defun
and encapsulate
history output from history commands such as :ubt and :pbt
summary the summary at the successful conclusion of an event
proof-tree proof-tree output
It is possible to inhibit each kind of output by putting the
corresponding name into lst. For example, if 'warning is included
in (the value of) lst, then no warnings are printed except those
related to soundness, e.g., the inclusion of an uncertified book.
Note that [proof-tree] output is affected by
set-inhibit-output-lst; see [proof-tree].
Note that proof output can be controlled without inhibiting it using
this utility, and indeed is already quite limited by default. See
[set-gag-mode].
See [with-output] for a variant of this utility that can be used in
[books]. Also see [set-inhibit-warnings] for how to inhibit
individual warning types and see [set-inhibited-summary-types] for
how to inhibit individual parts of the summary.
Printing of events on behalf of [certify-book] and [encapsulate] is
inhibited when both 'event and 'prove belong to lst. Otherwise,
printing of events is controlled by the [ld] special
[ld-pre-eval-print].
Note for advanced users. By including warning! in lst, you are
automatically including warning as well: all warnings will be
inhibited. This is not the case if you modify value of state global
variable 'inhibit-output-lst directly (with [assign] or
f-put-global); then, if you include warning! but not warning, then
warnings not related to soundness will still be printed (which is
probably not what was intended).")
(SET-INHIBIT-WARNINGS
(PROVER-OUTPUT)
"Control warnings
Examples:
(set-inhibit-warnings \"theory\" \"use\")
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It is [local] to the book or [encapsulate] form in which it occurs;
see [set-inhibit-warnings!] for a corresponding non-[local] event.
Indeed, (set-inhibit-warnings ...) is equivalent to (local
(set-inhibit-warnings! ...)).
General Form:
(set-inhibit-warnings string1 string2 ...)
where each string is considered without regard to case. This macro is
equivalent to (local (table inhibit-warnings-table nil 'lst
:clear)), where lst is the list of strings supplied. This macro is
an event (see [table]), but no output results from a
set-inhibit-warnings event.
ACL2 prints warnings that may, from time to time, seem excessive to
experienced users. Each warning is ``labeled'' with a string
identifying the type of warning. Consider for example
ACL2 Warning [Use] in ( THM ...): It is unusual to :USE ....
Here, the label is \"Use\". The argument list for set-inhibit-warnings
is a list of such labels, each of which is a string. Any warning is
suppressed if its label is a member of this list, where case is
ignored. Thus, for example, the warning above will not be printed
after a call of set-inhibit-warnings that contains the string,
\"Use\" (or any string that is [string-equal] to \"Use\", such as \"use\"
or \"USE\"). In summary: the effect of this event is to suppress any
warning whose label is a member of the given argument list, where
case is ignored.
The list of currently inhibited warnings is the list of keys in the
[table] named inhibit-warnings-table. (The values in the table are
irrelevant.) One way to get that value is to get the result from
evaluating the following form: (table-alist 'inhibit-warnings-table
(w state)). Of course, if warnings are inhibited overall --- see
[set-inhibit-output-lst] --- then this value is entirely
irrelevant.")
(SET-INHIBIT-WARNINGS!
(PROVER-OUTPUT)
"Control warnings non-[local]ly
Please see [set-inhibit-warnings], which is the same as
set-inhibit-warnings! except that the latter is not [local] to the
[encapsulate] or the book in which it occurs. Probably
[set-inhibit-warnings] is to be preferred unless you have a good
reason for wanting to export the effect of this event outside the
enclosing [encapsulate] or book.")
(SET-INHIBITED-SUMMARY-TYPES
(PROVER-OUTPUT)
"Control which parts of the summary are printed
Example:
(set-inhibited-summary-types '(rules time))
Note: This is not an event. Rather, it changes the [state], in
analogy to [set-inhibit-output-lst].
General Form:
(set-inhibited-summary-types form)
where form evaluates to a true-list of symbols, each of which is
among the values of the constant *summary-types*, i.e.: header,
form, rules, hint-events, warnings, time, steps, value, and
splitter-rules. Each specified type inhibits printing of the
corresponding portion of the summaries printed at the conclusions
of [events], where header refers to an initial newline followed by
the line containing just the word Summary.
Note the distinction between rules and hint-events. Rules provides a
record of automatic rule usage by the prover, while hint-events
shows the names of events given to :USE or :BY [hints], as well as
[clause-processor] functions given to :CLAUSE-PROCESSOR hints that
have an effect on the proof.
Also see [set-inhibit-output-lst]. Note that
set-inhibited-summary-types has no effect when summary is one of
the types inhibited by [set-inhibit-output-lst], because in that
case none of the summary will be printed.
To control summary types for a single event, see [with-output].")
(SET-INVISIBLE-FNS-TABLE
(LOOP-STOPPER)
"Set the invisible functions table
Examples:
(set-invisible-fns-table ((binary-+ unary--)
(binary-* unary-/)
(unary-- unary--)
(unary-/ unary-/)))
(set-invisible-fns-table t) ; restore original invisible-fns-table
Among other things, the setting above has the effect of making
[unary--] ``invisible'' for the purposes of applying permutative
:[rewrite] rules to [binary-+] trees. Thus, arg and (unary-- arg)
will be given the same weight and will be permuted so as to be
adjacent. The form (invisible-fns-table (w state)) returns the
current value of the invisible functions table.
Also see [add-invisible-fns] and see [remove-invisible-fns] for
events that add to and remove from the invisible functions table,
while accounting for macro aliases (see [macro-aliases-table]).
General Form:
(set-invisible-fns-table alist)
where alist is either t or a true list of pairs, each element of
which is of the form (fn ufn1 ... ufnk), where fn is a function
symbol and each ufni is a unary function symbol. When alist is t,
the initial value of this table is used in its place. Modulo the
replacement of alist by the default setting when alist is t, this
macro is equivalent to
(table invisible-fns-table nil 'alist :clear)
which is also an event (see [table]).
Note that set-invisible-fns-table does not evaluate its argument.
However, you can call [table] directly for that purpose. For
example,
(set-invisible-fns-table ((binary-+ unary--)
(binary-* unary-/)
(unary-- unary--)
(unary-/ unary-/)))
ie equivalent to the following; see [table].
(table invisible-fns-table nil
(quote ((binary-+ unary--)
(binary-* unary-/)
(unary-- unary--)
(unary-/ unary-/)))
:clear)
See [invisible-fns-table] for a description of the invisible
functions table.")
(SET-IPRINT
(IO)
"Control whether abbreviated output can be read back in
The following log may be sufficient for you to see how to use
set-iprint; more explanation is below. The example is taken from a
session that used the [break-rewrite] utility, but familiarity with
that utility is not necessary in order to understand this example.
What it shows is that the form (set-iprint t) allows you to
recover, using [without-evisc], output that had been hidden.
ACL2 !>(thm (p y))
(1 Breaking (:REWRITE AX) on (P Y):
1 ACL2 >:eval
1x (:REWRITE AX) failed because :HYP 1 rewrote to
(EQUAL Y '(NIL NIL NIL NIL ...)).
1 ACL2 >:a!
Abort to ACL2 top-level
Here is the current pstack [see :DOC pstack]:
(REWRITE-ATM SIMPLIFY-CLAUSE WATERFALL)
*** Note: No checkpoints to print. ***
ACL2 Version 6.4. Level 1. Cbd \"u/smith/\".
System books directory \"/u/smith/acl2/v6-4/books/\".
Type :help for help.
Type (good-bye) to quit completely out of ACL2.
ACL2 !>(set-iprint t)
ACL2 Observation in SET-IPRINT: Iprinting has been enabled.
ACL2 !>(thm (p y))
(1 Breaking (:REWRITE AX) on (P Y):
1 ACL2 >:eval
1x (:REWRITE AX) failed because :HYP 1 rewrote to
(EQUAL Y '(NIL NIL NIL NIL . #@2#)).
1 ACL2 >(without-evisc '(EQUAL Y '(NIL NIL NIL NIL . #@2#)))
(EQUAL Y
'(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL NIL NIL NIL NIL NIL NIL NIL))
1 ACL2 >
This concludes the introductory example.
When ACL2 pretty-prints large expressions using formatted printing
(see [fmt]), it may save time and space by printing tokens `#' or
`...' in place of certain subexpressions. By default this only
happens for a few settings such as error and warning messages; see
[set-evisc-tuple] for controlling such elision in general. The full
expression is unavailable to the user when `#' or `...' is printed,
but that is easily solved by evaluating the form
(set-iprint t)
to enable a mode called ``iprinting''. Then, instead of printing `#'
or `...', ACL2 prints `#@i#' for i = 1,2,3,... --- all in base 10.
ACL2 can read back in such `#@i#' because under the hood, i is
associated with its corresponding elided form. Thus the term
``iprint'' can be viewed as suggesting ``interactive print'' or
``index print''. We also think of ``iprint'' as suggesting ``i
printing'', to suggest the printing of token `#@i#'. We call i the
``iprint index'' of that token.
The following example should suffice to illustrate how to recover
elided subexpressions. (Below this example we provide details that
may be of interest only to advanced users.) Here we cause an error
by defining a macro of one argument and then calling it with two
arguments. By default, error messages abbreviate subexpressions
deeper than level 5 with `#' and past the 7th element of a list
with `...'. We see this behavior below.
ACL2 !>(defmacro foo (x) x)
Summary
Form: ( DEFMACRO FOO ...)
Rules: NIL
Warnings: None
Time: 0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
FOO
ACL2 !>(foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n))
ACL2 Error in macro expansion: Wrong number of args in macro expansion
of (FOO ARG1 (A (B (C (D #))) H I J K L ...)). (See :DOC set-iprint
to be able to see elided values in this message.)
ACL2 !>(set-iprint t)
ACL2 Observation in SET-IPRINT: Iprinting has been enabled.
ACL2 !>(foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n))
ACL2 Error in macro expansion: Wrong number of args in macro expansion
of (FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)).
ACL2 !>(acl2-count '(FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)))
23
ACL2 !>
Sometimes you may want to supply the abbreviated form not to compute
with it, as in the [ACL2-count] example just above, but so that you
can see it. The macro [without-evisc] eliminates elision during
printing. Below we show two ways to use this utility: first, we use
it to print the elided form, and then, we use it instead on the
original input form to print the entire error message.
ACL2 !>(without-evisc '(FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)))
(FOO ARG1
(A (B (C (D (E (F (G))))))
H I J K L M N))
ACL2 !>(without-evisc (foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n)))
ACL2 Error in macro expansion: Wrong number of args in macro expansion
of (FOO ARG1 (A (B (C (D (E (F (G)))))) H I J K L M N)).
ACL2 !>
The documentation above probably suffices for most users. For those
who want more details, below we detail all the ways to use the
set-iprint utility.
Example Forms:
(set-iprint t) ; enable iprinting (elision with #@i@)
(set-iprint nil) ; disable iprinting
General Form:
(set-iprint action ; t, nil, :reset, :reset-enable, or :same
:soft-bound s ; initially 1000
:hard-bound h ; initially 10000)
where all arguments are optional, but ACL2 queries for action if it
is omitted. We defer the explanations of :soft-bound and
:hard-bound. The values for action are as follows:
T --- Enable iprinting.
NIL --- Disable iprinting.
:RESET --- Reset iprinting to its initial disabled state, so that
when enabled, the first index i for which `#@i# is printed will
be 1. Note that all stored information for existing iprint
indices will be erased.
:RESET-ENABLE --- Reset iprinting as with :reset, and then enable
iprinting.
:SAME --- Make no change to the iprinting state (other than setting
the :soft-bound and/or :hard-bound if specified, as explained
below).
Immediately after a top-level form is read, hence before it is
evaluated, a check is made for whether the latest iprint index
exceeds a certain bound, (iprint-soft-bound state) --- 1000, by
default. If so, then the (iprint-last-index state) is set back to
0. This soft bound can be changed to any positive integer k by
calling set-iprint with :soft-bound k, typically (set-iprint :same
:soft-bound k)].
The above ``soft bound'' is applied once for each top-level form, but
you may want finer control by applying a bound after the
pretty-printing of each individual form (since many forms may be
pretty-printed between successive evaluations of top-level forms).
That bound is (iprint-hard-bound state), and can be set with the
:hard-bound argument in analogy to how :soft-bound is set, as
described above.
A ``rollover'' is the detection that the soft or hard bound has been
exceeded, along with a state update so that the next iprint index
will be 1. When a rollover occurs, any index beyond the latest
iprint index is no longer available for reading. At the top level
of the ACL2 read-eval-print loop, this works as follows: ACL2 reads
the next top-level form according to the current iprint state, then
handles a rollover if the latest iprint index exceeded the current
soft bound. The following log illustrates a rollover, which follows
the description above.
ACL2 !>(set-iprint t :soft-bound 3)
ACL2 Observation in SET-IPRINT: The soft-bound for iprinting has been
set to 3.
ACL2 Observation in SET-IPRINT: Iprinting has been enabled.
ACL2 !>(set-evisc-tuple (evisc-tuple 2 3 nil nil) :sites :ld)
(:LD)
ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
((A B C . #@1#) (A B C . #@2#) (A B C . #@3#))
ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
((A B C . #@4#) (A B C . #@5#) (A B C . #@6#))
ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))
((A B C D E F G)
(A B C D E F G)
(A B C D E F G))
ACL2 !>'(1 2 3 4 5)
(1 2 3 . #@1#)
ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
((A B C . #@2#) (A B C . #@3#) (A B C . #@4#))
ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))
((A B C D E F G)
(A B C D E F G)
(A B C D E F G))
ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))
***********************************************
************ ABORTING from raw Lisp ***********
Error: Out-of-bounds index in #@5#. See :DOC set-iprint.
***********************************************
If you didn't cause an explicit interrupt (Control-C),
then the root cause may be call of a :program mode
function that has the wrong guard specified, or even no
guard specified (i.e., an implicit guard of t).
See :DOC guards.
To enable breaks into the debugger (also see :DOC acl2-customization):
(SET-DEBUGGER-ENABLE T)
ACL2 !>
We conclude by mentioning two cases where iprinting and evisc-tuples
are ignored. (1) This is typically the case when printing results
in raw Lisp outside the ACL2 loop. To use iprinting and
evisc-tuples in raw Lisp, use raw-mode; see [set-raw-mode]. In
raw-mode, results that are ACL2 objects will be printed in the same
way that ACL2 would print those results if not in raw-mode. (2)
Iprinting and evisc-tuples are ignored by [print-object$], which
however is sensitive to many settings that do not affect formatted
([fmt] etc.) printing; see [print-control].
The reader interested in design and implementation issues considered
during the addition of iprinting to ACL2 is invited to read the
paper ``Abbreviated Output for Input in ACL2: An Implementation
Case Study''; see the {proceedings of ACL2 Workshop 2009 |
http://www.cs.utexas.edu/users/moore/acl2/workshop-2009/}.")
(SET-IRRELEVANT-FORMALS-OK
(DEFUN)
"Allow irrelevant formals in definitions
Examples:
(set-irrelevant-formals-ok t)
(set-irrelevant-formals-ok nil)
(set-irrelevant-formals-ok :warn)
The first example above allows irrelevant formals in definitions; see
[irrelevant-formals]. The second example disallows irrelevant
formals; this is the default. The third example allows irrelevant
formals, but prints an appropriate warning.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Moreover, its effect is to set the [ACL2-defaults-table], and hence
its effect is [local] to the book or [encapsulate] form containing
it; see [ACL2-defaults-table].
General Form:
(set-irrelevant-formals-ok flg)
where flg is either t, nil, or :warn.")
(SET-LD-KEYWORD-ALIASES (POINTERS)
"See [ld-keyword-aliases].")
(SET-LD-KEYWORD-ALIASES! (POINTERS)
"See [ld-keyword-aliases].")
(SET-LD-REDEFINITION-ACTION (POINTERS)
"See [ld-redefinition-action].")
(SET-LD-SKIP-PROOFS (POINTERS)
"See [ld-skip-proofsp].")
(SET-LD-SKIP-PROOFSP (POINTERS)
"See [ld-skip-proofsp].")
(SET-LET*-ABSTRACTION (POINTERS)
"See [set-let*-abstractionp].")
(SET-LET*-ABSTRACTIONP
(PROVER-OUTPUT)
"To shorten many prettyprinted clauses
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Moreover, its effect is to set the [ACL2-defaults-table], and hence
its effect is [local] to the book or [encapsulate] form containing
it; see [ACL2-defaults-table].
When this flag is set to t, subterms that occur more than once in a
clause are abstracted away with [let*], generally shortening the
displayed size of the clauses. This flag only affects how clauses
are printed. It does not change what terms the theorem prover
manipulates.
:set-let*-abstractionp t ;;; or, (set-let*-abstractionp t)
will cause the prettyprinter to do ``let* abstraction'' on clauses
before they are printed. The algorithm finds the maximal
multiply-occuring subterm and extracts it, binding it to some new
variable and replacing its occurrences by that variable. This
produces a let* form. This process is iterated until no subterm
occurs more than once. This process generally takes a little time,
but less time than to print large clauses. The process can greatly
reduce the amount of text produced by the prover.
THIS ONLY AFFECTS HOW THE CLAUSES ARE PRINTED! The unabstracted
clauses are manipulated by the theorem prover.
:set-let*-abstractionp nil
restores normal clause printing.
The mode is stored in the defaults table, See [ACL2-defaults-table].
Thus, the mode may be set locally in books.")
(SET-MATCH-FREE-DEFAULT
(FREE-VARIABLES)
"Provide default for :match-free in future rules
General Forms:
(set-match-free-default :once)
(set-match-free-default :all)
(set-match-free-default nil)
Note: This utility does not apply to [type-prescription] rules; for a
related topic pertinent to such rules, see
[free-variables-type-prescription].
As described elsewhere (see [free-variables]), a [rewrite], [linear],
or [forward-chaining] rule may have free variables in its
hypotheses, and ACL2 can be directed either to try all bindings
(``:all'') or just the first (``:once'') when relieving that
hypothesis, as a basis for relieving subsequent hypotheses. This
directing of :all or :once is generally provided by specifying
either :match-free :once or :match-free :all in the :[rule-classes]
of the rule. If neither of these is specified, then the most recent
set-match-free-default is used by ACL2 to fill in this missing
:match-free field. See [rule-classes]. Except: If the last
set-match-free-default specifies nil, then ACL2 reverts to the
behavior it had at start-up, as described in Remarks (2) and (3)
below.
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It uses the [ACL2-defaults-table], and hence its effect is [local]
to the book or [encapsulate] form in which it occurs.
Remarks.
(1) The use of set-match-free-default has no effect on existing
rules. In order to change the behavior of existing rules with
respect to free-variable matching, see [add-match-free-override].
(2) If you submit a [rewrite], [linear], or [forward-chaining] rule
with a free variable in a hypothesis, and no default setting was
previously specified with set-match-free-default or the default
setting is nil, and the rule is not within a book being processed
with [include-book], [certify-book], or [rebuild], then a warning
or error is caused. In order to make this an error instead of a
warning, see [set-match-free-error].
(3) If you submit a [rewrite], [linear], or [forward-chaining] rule
with a free variable in a hypothesis, and no default setting has
been previously specified with set-match-free-default or the
default setting is nil, and no error is caused (see (2) above),
then the default :all is used.")
(SET-MATCH-FREE-ERROR
(FREE-VARIABLES)
"Control error vs. warning when :match-free is missing
Legal Forms:
(set-match-free-error nil)
:set-match-free-error nil
(set-match-free-error t)
:set-match-free-error t
As described elsewhere (see [free-variables]), when a [rewrite],
[linear], or [forward-chaining] rule has free variables in its
hypotheses, the user can specify whether to try all bindings
(``:all'') or just the first (``:once'') when relieving its
hypotheses, as a basis for relieving subsequent hypotheses. This
direction of :all or :once is generally provided by specifying
either :match-free :once or :match-free :all in the :[rule-classes]
of the rule.
But suppose that neither of these is specified for such a rule.
(Note: set-match-free-error is not relevant for [type-prescription]
rules.) Also suppose that set-match-free-default has not specified
a default of :once or :all (see [set-match-free-default]). In this
case a warning will occur except when in the context of
[include-book]. If you prefer to see an error in such cases, except
in the context of [certify-book], execute (set-match-free-error t).
If there is no error, then a default of :all is used.
Note: This is NOT an event! Instead, set-match-free-error sets the
state global 'match-free-error (see [state] and see [assign]).
Thus, this form cannot be put into a book. If you are tempted to
put it into a book, consider the fact that it really isn't needed
there, since the absence of :match-free does not cause an error in
the context of [certify-book] or [include-book]. If you still feel
the need for such a form, consider using set-match-free-default to
provide a default, at least within the scope of the current book
(if any); see [set-match-free-default].")
(SET-MEASURE-FUNCTION
(DEFUN)
"Set the default measure function symbol
Examples:
(set-measure-function nqthm::count)
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
General Form:
(set-measure-function name)
where name is a function symbol of one argument. This macro is
equivalent to (table acl2-defaults-table :measure-function 'name),
and hence is [local] to any [books] and [encapsulate] [events] in
which it occurs; see [ACL2-defaults-table]. Although this is thus
an event (see [table]), nevertheless no output results from a
set-measure-function event.
This event sets the default measure function to name. Subsequently,
if a recursively defined function is submitted to [defun] with no
explicitly given :measure argument, [defun] ``guesses'' the measure
(name var), where name is the then current default measure function
and var is the first formal found to be tested along every branch
and changed in every recursive call.
Note that if (table acl2-defaults-table :measure-function 'name) has
its default value of nil, then the default measure function is
[ACL2-count].")
(SET-NON-LINEAR (POINTERS)
"See [set-non-linearp].")
(SET-NON-LINEARP
(NON-LINEAR-ARITHMETIC)
"To turn on or off non-linear arithmetic reasoning
Examples:
(set-non-linearp t)
(set-non-linearp nil)
See [non-linear-arithmetic]. This event is equivalent to (table
acl2-defaults-table :non-linearp <t-or-nil>), and hence is [local]
to any [books] and [encapsulate] [events] in which it occurs; see
[ACL2-defaults-table].
The initial value is nil.")
(SET-OVERRIDE-HINTS
(OVERRIDE-HINTS)
"Set the [override-hints]
See [override-hints] for a discussion of override-hints. Here we
describe how to set them. Note that the effects of
set-override-hints [events] are [local] to the [books] or
encapsulate [events] in which they reside; see
[set-override-hints!] to avoid that restriction. Also see
[add-override-hints] to add to the list of override-hints, rather
than setting a new list and ignoring the present list.
General Form:
(set-override-hints form)
where form evaluates to a list of computed hint forms. The effect of
this event is to set the list of [override-hints] to the result of
that evaluation.")
(SET-OVERRIDE-HINTS!
(OVERRIDE-HINTS)
"Set the [override-hints] non-[local]ly
Set-override-hints! is the same as [set-override-hints], except that
the former is not [local] to [books] or [encapsulate] [events] in
which it occurs. See [set-override-hints]; also see
[add-override-hints].")
(SET-PARALLEL-EXECUTION
(PARALLELISM)
"For ACL2(p): enabling parallel execution for four parallelism
primitives
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
See [parallelism-tutorial] for an introduction to parallel
execution in ACL2.
General Forms:
(set-parallel-execution nil) ; default for images not built for parallelism
(set-parallel-execution t) ; default for images built for parallelism
(set-parallel-execution :bogus-parallelism-ok)
Set-parallel-execution takes an argument that specifies the enabling
or disabling of [parallel] execution for the primitives [pand],
[por], [plet], and [pargs] (but not [spec-mv-let], whose parallel
execution remains enabled). However, without using [top-level],
calls of parallelism primitives made explicitly in the ACL2
top-level loop, as opposed to inside function bodies, will never
cause parallel execution; see [parallelism-at-the-top-level].
Parallel execution is determined by the value of the argument to
set-parallel-execution, as follows.
Value t:
All parallelism primitives used in bodies of function definitions
are given the opportunity to execute in parallel. However, the use
of parallelism primitives directly in the ACL2 top-level loop
causes an error.
Value :bogus-parallelism-ok:
Parallel execution is enabled, as for value t. However, the use of
parallelism primitives directly in the ACL2 top-level loop does not
cause an error, but rather, simply results in serial execution for
these primitives.
Value nil:
All parallelism primitives degrade to their serial equivalents,
including their calls made directly in the ACL2 top-level loop.
Thus, uses of parallelism primitives do not in themselves cause
errors.")
(SET-PRINT-BASE
(IO ACL2-BUILT-INS)
"Control radix in which numbers are printed
Also see [set-print-base-radix] for a nice combined use of
set-print-base and [set-print-radix].
By default, integers and ratios are printed in base 10. ACL2 also
supports printing in radix 2, 8, or 16 by calling set-print-base
with the desired radix (base).
(set-print-base 10 state) ; Default printing
(set-print-base 16 state) ; Print integers and ratios in hex
Here is a sample log.
ACL2 !>(list 25 25/3)
(25 25/3)
ACL2 !>(set-print-base 16 state)
<state>
ACL2 !>(list 25 25/3)
(19 19/3)
ACL2 !>
See [set-print-radix] for how to print the radix, for example,
printing the decimal number 25 in print-base 16 as ``#x25'' rather
than ``25''. Also see [print-control] for other user-settable print
controls.
Note: ACL2 [events] and some other top-level commands (for example,
[thm], [verify], and history commands such as :pe and :pbt) set the
print base to 10 during their evaluation. So [set-print-base] has
no effect while these forms are being processed.")
(SET-PRINT-BASE-RADIX
(IO ACL2-BUILT-INS)
"Control radix in which numbers are printed and printing of the radix
See [set-print-base] and [set-print-radix] for detailed discussions
of those functions. Set-print-base-radix combines their
functionality by setting the radix (as is done by
[set-print-base]), and then causing the radix to be printed (as is
done by [set-print-radix]) exactly when the specified radix is not
10.
Here is a sample log.
ACL2 !>(list 25 25/3)
(25 25/3)
ACL2 !>(set-print-base-radix 16 state)
<state>
ACL2 !>(list 25 25/3)
(#x19 #x19/3)
ACL2 !>(set-print-base-radix 10 state)
<state>
ACL2 !>(list 25 25/3)
(25 25/3)
ACL2 !>")
(SET-PRINT-CASE
(IO ACL2-BUILT-INS)
"Control whether symbols are printed in upper case or in lower case
By default, symbols are printed in upper case when vertical bars are
not required, as specified by Common Lisp. As with Common Lisp,
ACL2 supports printing in a \"downcase\" mode, where symbols are
printed in lower case. Many printing functions (some details below)
print characters in lower case for a symbol when the ACL2 [state]
global variable print-case has value :downcase and vertical bars
are not necessary for printing that symbol. (Thus, this state
global functions in complete analogy to the Common Lisp global
*print-case*.) The value print-case is returned by (print-case),
and may be set using the function set-print-case as follows.
(set-print-case :upcase state) ; Default printing
(set-print-case :downcase state) ; Print symbols in lower case when
; vertical bars are not required
The ACL2 user can expect that the :downcase setting will have an
effect for formatted output (see [fmt] and see [fms]) when the
directives are ~p, ~P, ~q, or ~Q, for built-in functions princ$ and
prin1$, and the ppr family of functions, and not for built-in
function print-object$. For other printing functions, the effect of
:downcase is unspecified.
Also see [print-control] for other user-settable print controls.")
(SET-PRINT-CIRCLE (POINTERS)
"See [print-control].")
(SET-PRINT-CLAUSE-IDS
(PROVER-OUTPUT)
"Cause subgoal numbers to be printed when 'prove output is inhibited
General Forms:
(set-print-clause-ids t)
:set-print-clause-ids t
(set-print-clause-ids nil)
:set-print-clause-ids nil
This command affects output from the theorem prover only when 'prove
output is inhibited (see [set-inhibit-output-lst]) or gag-mode is
on (but in that case the :goals setting issues this command
automatically; see [set-gag-mode]). Calling this macro with value t
as shown above will cause subsequent proof attempts with 'prove
output inhibited to print the subgoal number, so that you can see
the progress of the proof; value nil reverts to the default
behavior, where this is not the case. On a related note, we point
out that you can cause output to be saved for later display; see
[pso] and see [pso!].
If 'prove output is inhibited or gag-mode is on, and if you issue
(set-print-clause-ids t) (either explicitly or with (set-gag-mode
:goals)), then you can restrict when subgoal numbers are printed.
In the following example we restrict to subgoals that are no more
than four inductions deep, no more than four casesplits deep, and
no more than four single-subgoals deep. For additional relevant
explanation, see [clause-identifier] and see [defattach].
(defun print-clause-id-okp-level-4 (cl-id)
(declare (xargs :mode :logic :guard (clause-id-p cl-id)))
(and (<= (length (access clause-id cl-id :pool-lst))
4)
(<= (length (access clause-id cl-id :case-lst))
4)
(<= (access clause-id cl-id :primes)
4)))
(defattach print-clause-id-okp print-clause-id-okp-level-4)")
(SET-PRINT-ESCAPE (POINTERS)
"See [print-control].")
(SET-PRINT-GV-DEFAULTS
(PRINT-GV GUARD DEBUGGING)
"Set default keyword values for [print-gv]
Example Forms:
(set-print-gv-defaults :conjunct t)
(set-print-gv-defaults :conjunct t :substitute t)
(set-print-gv-defaults :evisc-tuple
(evisc-tuple 4 ; print-level
5 ; print-length
(world-evisceration-alist state nil)
nil ; hiding-cars
))
(set-print-gv-defaults :conjunct :restore
:substitute :restore
:evisc-tuple :restore)
(set-print-gv-defaults)
General Form:
(set-print-gv-defaults :conjunct c
:substitute s
:evisc-tuple e)
where any or all of c, s, and e may be the keyword, :restore, and
otherwise: c and s are Boolean and e is an [evisc-tuple]. These
forms set the defaults for the corresponding keyword arguments of
the print-gv utility, where the value :restore restores the system
defaults; see [print-gv]. Evaluation returns an [error-triple]
whose value is an alist associating keywords with their current
defaults. In particular, the call (set-print-gv-defaults) simply
returns an error-triple with that alist as the value, without
changing any defaults.
Thus, for example, if you submit the form
(set-print-gv :substitute t
:conjunct t
:evisc-tuple (evisc-tuple 3 4 nil nil))
then subsequently, if you submit the form :print-gv or (print-gv) it
would be interpreted as follows.
(print-gv :substitute t
:conjunct t
:evisc-tuple (evisc-tuple 3 4 nil nil))
Of course, you can override your defaults, so that for example if you
subsequently submit the form (print-gv :substitute nil) or the form
(print-gv :substitute nil :evisc-tuple (print-gv-evisc-tuple)),
these would be equivalent to submitting the following forms,
respectively.
(print-gv :substitute nil
:conjunct t
:evisc-tuple (evisc-tuple 3 4 nil nil))
(print-gv :substitute nil
:conjunct t
:evisc-tuple (print-gv-evisc-tuple))")
(SET-PRINT-LENGTH (POINTERS)
"See [print-control].")
(SET-PRINT-LEVEL (POINTERS)
"See [print-control].")
(SET-PRINT-LINES (POINTERS)
"See [print-control].")
(SET-PRINT-RADIX
(IO ACL2-BUILT-INS)
"Control printing of the radix for numbers
Also see [set-print-base-radix] for a nice combined use of
[set-print-base] and set-print-radix.
See [set-print-base] for background on how the print base affects the
printing of numbers. set-print-radix affects whether a radix
indicated when a number is printed. The radix is not indicated by
default, or after evaluating (set-print-radix nil state). But if
set-print-radix is called with a first argument that evaluates to a
nonnil value --- for example, (set-print-radix t state) --- then
the radix is shown when printing. (This behavior is consistent with
the handling of Common Lisp global *print-radix*.) The following
log illustrates how this works.
ACL2 !>(list 25 25/3)
(25 25/3)
ACL2 !>(set-print-base 16 state)
<state>
ACL2 !>(list 25 25/3)
(19 19/3)
ACL2 !>(set-print-radix t state)
<state>
ACL2 !>(list 25 25/3)
(#x19 #x19/3)
ACL2 !>(set-print-base 10 state)
<state>
ACL2 !>(list 25 25/3)
(25. #10r25/3)
ACL2 !>(set-print-radix nil state)
<state>
ACL2 !>(list 25 25/3)
(25 25/3)
ACL2 !>")
(SET-PRINT-READABLY (POINTERS)
"See [print-control].")
(SET-PRINT-RIGHT-MARGIN (POINTERS)
"See [print-control].")
(SET-PROVER-STEP-LIMIT
(MISCELLANEOUS)
"Sets the step-limit used by the ACL2 prover
This event provides a way to limit the number of so-called ``prover
steps'' permitted for an event. See [with-prover-step-limit] for a
way to specify the limit on prover steps for a single event, rather
than globally. For a related utility based on time instead of
prover steps, see [with-prover-time-limit]. For examples of how
step limits work, see the community book
books/misc/misc2/step-limits.lisp. For a utility that returns an
indicator of the number of prover steps most recently taken, see
[last-prover-steps].
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Moreover, its effect is to set the [ACL2-defaults-table], and hence
its effect is [local] to the book or [encapsulate] form containing
it; see [ACL2-defaults-table].
Example Forms:
(set-prover-step-limit *default-step-limit*) ; no limit on prover steps
(set-prover-step-limit nil) ; abbreviation for the form just above
(set-prover-step-limit 10000) ; allow at most 10,000 prover steps per event
General Form:
(set-prover-step-limit expr)
where expr evaluates either to nil or else to a natural number not
exceeding the value of *default-step-limit*. If that value is nil
or the value of *default-step-limit*, then no default limit is
placed on the number of prover ``steps'' (see below) during
processing of an event. Otherwise, that value is the maximum number
of prover steps permitted before an error occurs.
This event specifies the limit on the number of ``steps'' counted by
the ACL2 prover during processing of an event. Currently, a step is
counted for each call of the system functions rewrite and
expand-abbreviations. However, the steps counted may change in
future releases of ACL2, so users would probably be well served by
avoiding the assumption that only the above two calls are counted
as prover steps.
Depending on the computer you are using, you may have less than a
half-hour of time before the number of prover steps exceeds the
maximum step-limit, which is one less than the value of
*default-step-limit*. Note however the exception stated above: if
the ``limit'' is nil or is the value of *default-step-limit*, then
no limit is imposed.
There is at best a loose connection between the counting of steps and
[with-prover-time-limit]. In particular, for a call of mfc-rw or
any mfc- function (see [extended-metafunctions]), the steps taken
during that call are forgotten when returning from that call.
The limit is relevant for every event, as well as for calls of [thm]
and [certify-book] --- and more generally, to any form that creates
a ``summary context'' to print the usual event summary. The limit
is also put in force when entering the [proof-checker]. A call of
set-prover-step-limit applies to each subsequent form unless the
call of set-prover-step-limit is within a summary context, in which
case its effect disappears when exiting that summary context.
The limit applies to each event, not just ``atomic'' events. Consider
the following example.
(set-prover-step-limit 500)
(encapsulate
()
(defthm lemma-1 ; takes 380 steps
(equal (append (append x y) z) (append x y z))
:rule-classes nil)
(defthm lemma-2 ; would take 319 steps
(equal (len (append x y)) (+ (len x) (len y)))
:rule-classes nil))
The first [defthm] event, lemma-1 takes 380 steps (as of this
writing), as shown in the summary:
Prover steps counted: 380
LEMMA-1
The second [defthm] event, lemma-2, takes 319 steps (as of this
writing) when evaluated at the top level. However, in the context
above, 380 steps of the available 500 steps (from the
set-prover-step-limit event above) have already been taken under
the above [encapsulate] event. Thus, when the number of steps would
exceed 120, the proof of lemma-2 is aborted:
ACL2 Error in STEP-LIMIT: The prover step-limit, which is 120 in the
current context, has been exceeded. See :DOC set-prover-step-limit.
The summary for lemma-2 reflects that situation:
Prover steps counted: More than 120
The summary for the [encapsulate] event then indicates that the
available steps for that event have also been exceeded:
Prover steps counted: More than 500
The discussion above applies to any event that contains other events,
hence applies similarly to [progn] events.
For those who use [make-event], we note that prover steps in the
expansion phase similarly contribute to the total number of steps
counted. For example, suppose that the limit is 500 prover steps as
above, and you submit (make-event EXPR), where 300 prover steps
take place during evaluation of EXPR, producing event EV. Then
evaluation of EV will cause an error if it takes more than 200
prover steps. This observation actually can be used to count prover
steps for sequences of forms that are not all legal [events] (see
[embedded-event-form]), such as calls of [thm]. For example, a
small built-in ACL2 test suite that includes [thm] forms can be run
by evaluating the form (mini-proveall), and the steps can be
counted as shown below. (Here we assume a fresh ACL2 session; an
error would occur if first, we evaluate the event
(set-prover-step-limit 500) displayed above.)
ACL2 !>(make-event (er-progn (mini-proveall) (value '(value-triple nil))))
[[... output omitted here ...]]
Summary
Form: ( MAKE-EVENT (ER-PROGN ...))
Rules: NIL
Warnings: Double-rewrite, Equiv, Subsume and Non-rec
Time: 0.38 seconds (prove: 0.04, print: 0.29, other: 0.05)
Prover steps counted: 41090
NIL
ACL2 !>
Subtopics
[Last-prover-steps]
The number of prover steps most recently taken")
(SET-RAW-MODE
(DEFTTAG)
"Enter or exit ``raw mode,'' a raw Lisp environment
Below we discuss raw-mode. In brief: The simplest way to turn
raw-mode on is :SET-RAW-MODE-ON!, and to turn it off, :SET-RAW-MODE
NIL. Also see [set-raw-mode-on!].
ACL2 users often find its careful syntax checking to be helpful
during code development. Sometimes it is even useful to do code
development in :[logic] mode, where ACL2 can be used to check
termination of (mutually) recursive functions, verify guards, or
even prove properties of the functions.
However, loading code using [include-book] is much slower than using
Common Lisp load in raw Lisp, and in this sense ACL2 can get in the
way of efficient execution. Unfortunately, it is error-prone to use
ACL2 sources (or their compilations) in raw Lisp, primarily because
a number of ACL2 primitives will not let you do so. Perhaps you
have seen this error message when trying to do so:
HARD ACL2 ERROR in ACL2-UNWIND-PROTECT: Apparently you have tried
to execute a form in raw Lisp that is only intended to be executed
inside the ACL2 loop.
Even without this problem it is important to enter the ACL2 loop (see
[lp]), for example in order to set the [cbd] and (to get more
technical) the readtable.
ACL2 provides a ``raw mode'' for execution of raw Lisp forms. In this
mode, [include-book] reduces essentially to a Common Lisp load.
More generally, the ACL2 logical [world] is not routinely extended
in raw mode (some sneaky tricks are probably required to make that
happen). To turn raw mode off or on:
:set-raw-mode t ; turn raw mode on
:set-raw-mode nil ; turn raw mode off
The way you can tell that you are in raw mode is by looking at the
prompt (see [default-print-prompt]), which uses a capital ``P''
(suggesting something like program mode, but more so).
ACL2 P>
Typical benefits of raw mode are fast loading of source and compiled
files and the capability to hack arbitrary Common Lisp code in an
environment with the ACL2 sources loaded (and hence with ACL2
primitives available). In addition, ACL2 hard errors will put you
into the Lisp debugger, rather than returning you to the ACL2 loop,
and this may be helpful for debugging; see [hard-error] and see
[illegal], but also see [break-on-error]. However, it probably is
generally best to avoid raw mode unless these advantages seem
important. We expect the main benefit of raw mode to be in
deployment of applications, where load time is much faster than the
time required for a full-blown [include-book], although in certain
cases the fast loading of books and treatment of hard errors
discussed above may be useful during development.
Raw mode is also useful for those who want to build extensions of
ACL2. For example, the following form can be put into a certifiable
book to load an arbitrary Common Lisp source or compiled file.
(progn (defttag my-application)
(progn! (set-raw-mode t)
(load \"some-file\")))
Also see [include-raw] and [with-raw-mode]. See [defttag], and see
[progn!].
Below are several disadvantages to raw mode. These should discourage
users from using it for general code development, as :[program]
mode is generally preferable.
* Forms are in essence executed in raw Lisp. Hence:
* Syntax checking is turned off; and
* Guard checking is completely disabled.
* Table events, including [logic], are ignored, as are many other
[events], including [defthm] and [comp].
* Soundness claims are weakened for any ACL2 session in which raw mode
was ever entered; see [defttag].
* The normal undoing mechanism (see [ubt]) is not supported.
* Unexpected behavior may occur when you return from raw-mode. For
example, if you redefine a :logic mode function whose guards
have not been verified, you will not see the change inside the
ACL2 loop because there, the raw Common Lisp definition is only
executed after guards have been verified; see
[guards-and-evaluation] and see [guard-evaluation-table].
We conclude with some details.
Printing results. The rules for printing results are unchanged for
raw mode, with one exception. If the value to be printed would
contain any Lisp object that is not a legal ACL2 object, then the
print routine is used from the host Lisp, rather than the usual
ACL2 printing routine. The following example illustrates the
printing used when an illegal ACL2 object needs to be printed.
Notice how that ``command conventions'' are observed (see
[ld-post-eval-print]); the ``[Note'' occurs one space over in the
second example, and no result is printed in the third example.
ACL2 P>(find-package \"ACL2\")
[Note: Printing non-ACL2 result.]
#<The ACL2 package>
ACL2 P>(mv nil (find-package \"ACL2\") state)
[Note: Printing non-ACL2 result.]
#<The ACL2 package>
ACL2 P>(mv t (find-package \"ACL2\") state)
ACL2 P>(mv 3 (find-package \"ACL2\"))
[Note: Printing non-ACL2 result.]
(3 #<The ACL2 package>)
ACL2 P>
If you have trouble with large structures being printed out, you
might want to execute appropriate Common Lisp forms in raw mode,
for example, (setq *print-length* 5) and (setq *print-level* 5).
Include-book. The [events] [add-include-book-dir],
[add-include-book-dir!], [delete-include-book-dir], and
[delete-include-book-dir!] have been designed to work with raw
mode. However, if you enter raw mode and then evaluate such forms,
then the effects of these forms will disappear when you exit raw
mode, in which case you can expect to see a suitable warning.
Regarding include-book itself: it should work in raw mode as you
might expect, at least if a compiled file or expansion file was
created when the book was certified; see [certify-book].
Packages. Raw mode disallows the use of [defpkg]. If you want to
create a new package, first exit raw mode with :set-raw-mode nil;
you can subsequently re-enter raw mode with :set-raw-mode t if you
wish.
Subtopics
[Add-raw-arity]
Add arity information for raw mode
[Remove-raw-arity]
Remove arity information for raw mode")
(SET-RAW-MODE-ON!
(DEFTTAG)
"Enter ``raw mode,'' a raw Lisp environment
This is the same as ([set-raw-mode] t) except that it first
introduces a so-called ``trust tag'' (``ttag'') so that
set-raw-mode will be legal. See [defttag] for a discussion of ttags
and how they affect [certify-book] and [include-book].
See [set-raw-mode] for a discussion of raw-mode.")
(SET-RAW-PROOF-FORMAT
(PROVER-OUTPUT)
"Print runes as lists in proof output from simplification
General Forms:
(set-raw-proof-format t)
:set-raw-proof-format t
(set-raw-proof-format nil)
:set-raw-proof-format nil
This command affects output from the theorem prover only when 'prove
output is not inhibited (see [set-inhibit-output-lst]) and gag-mode
is off (see [set-gag-mode]). Calling this macro with value t as
shown above will cause simplification steps from proof output,
including steps from preprocess (see [simple]), to print the list
of runes used in a list format, rather than in the English proof
commentary. This ``raw'' format can be handy when you want to use
that list as a basis for [hints] that you construct for a
subsequent proof attempt.
To obtain the current raw-proof-format (t if that format is active,
nil if not), evaluate (@ raw-proof-format).")
(SET-RAW-WARNING-FORMAT
(PROVER-OUTPUT)
"Print some warnings in a ``raw'', s-expression format
General Forms:
(set-raw-warning-format t)
:set-raw-warning-format t
(set-raw-warning-format nil)
:set-raw-warning-format nil
This command affects 'warning (and 'warning!) output from the theorem
prover when not inhibited (see [set-inhibit-output-lst]). Calling
this macro with value t as shown above will cause warnings to be
printed in a ``raw'', s-expression format, of the form (:WARNING
warning-type alist). The following example shows a traditional
warning message followed by its counterpart after evaluating
(set-raw-warning-format t).
; default format
ACL2 Warning [Subsume] in ( DEFTHM APP-COMMUTES ...): A newly proposed
:REWRITE rule generated from APP-COMMUTES probably subsumes the previously
added :REWRITE rule APP-CONS, in the sense that the new rule will now
probably be applied whenever the old rule would have been.
; raw format
(:WARNING \"Subsume\"
((:CTX (DEFTHM . APP-COMMUTES))
(:NEW-RULE APP-COMMUTES)
(:RULE-CLASS-NEW :REWRITE)
(:RULE-CLASS-OLD :REWRITE)
(:SUBSUMED-RULES (APP-CONS))))
As illustrated above, it is typical that in the raw format, the :CTX
entry is first in the alist while the others are ordered
alphabetically by key (e.g., :NEW-RULE precedes :RULE-CLASS-NEW
alphabetically).
To obtain the current raw-warning-format (t if that format is active,
nil if not), evaluate (@ raw-warning-format).
NOTE: Only a few commonly-occurring classes of warnings are shown
differently in raw-warning-format.")
(SET-REWRITE-STACK-LIMIT
(REWRITE-STACK-LIMIT)
"Sets the rewrite stack depth used by the rewriter
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
Example Forms:
(set-rewrite-stack-limit 30) ; set to small limit
:set-rewrite-stack-limit 30 ; same as above
(set-rewrite-stack-limit *default-rewrite-stack-limit*) ; the default
(set-rewrite-stack-limit (1- (expt 2 28))) ; maximum legal limit
:set-rewrite-stack-limit nil ; same as above -- essentially, no limit
This event sets the maximum stack depth for calls of certain
functions that implement the ACL2 rewriter; see
[rewrite-stack-limit]. It must be a non-negative integer less than
2^28. A call (set-rewrite-stack-limit limit) is equivalent to:
(table acl2-defaults-table :rewrite-stack-limit limit).
The use of [ACL2-defaults-table] ensures that this event's effect is
implicitly [local] to the book or [encapsulate] form in which it
occurs.
For a different but somewhat related concept, see [backchain-limit].")
(SET-RULER-EXTENDERS (POINTERS)
"See [ruler-extenders].")
(SET-RW-CACHE-STATE
(REWRITE)
"Set the default rw-cache-state
The ACL2 rewriter uses a data structure, called the rw-cache
(rewriter cache), to save failed attempts to apply conditional
[rewrite] rules. The regression suite has taken approximately 11%
less time with this mechanism. The rw-cache is active by default
but this event allows it to be turned off or modified. Note that
this event is [local] to its context (from [encapsulate] or
[include-book]). For a non-local version, use
[set-rw-cache-state!].
Example forms:
(set-rw-cache-state :atom) ; default: rw-cache cleared for each literal
; (i.e., hypothesis or conclusion of a goal)
(set-rw-cache-state nil) ; rw-cache is inactive
(set-rw-cache-state t) ; rw-cache persists beyond each literal
(set-rw-cache-state :disabled) ; rw-cache is inactive, but the rw-cache-state
; transitions to state t after
; simplification takes place
General Form:
(set-rw-cache-state val)
where val evaluates to one of the four values shown in ``Example
forms'' above. The default is :atom, which enables the rw-cache but
clears it before rewriting a hypothesis or conclusion of any goal.
The value t is provides more aggresive use of the rw-cache,
basically preserving the rw-cache when there is a single subgoal.
The value :disabled is the same as t, except that the rw-cache is
initially inactive and only becomes active when some simplification
has taken place. We have seen a few cases where value t will make a
proof fail but :disabled does not.
The following example illustrates the rw-cache in action. You will
see a break during evaluation of the [thm] form. Type :eval and you
will see a failed rewriting attempt. Type :go to continue, and at
the next break type :eval again. This time you will see the same
failed rewriting attempt, but this time labeled with a notation
saying that the failure was cached earlier, which indicates that
this time the rewriter did not even attempt to prove the hypothesis
of the [rewrite] rule f1->f2.
(defstub f1 (x) t)
(defstub f2 (x) t)
(defaxiom f1->f2
(implies (f1 x) (equal (f2 x) t)))
:brr t
:monitor (:rewrite f1->f2) t
(thm (equal (car (f2 a)) (cdr (f2 a))))
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
It is [local] to the book or [encapsulate] form in which it occurs
(see [set-rw-cache-state!] for a corresponding non-[local] event).
We also note that rw-cache-state changes may also be caused at the
subgoal level; see [hints].
We welcome you to experiment with different rw-cache states. If the
more aggressive values of t and :disabled cause proofs to fail,
then you can revert to the default of :atom or even turn off the
rw-cache using (set-rw-cache-state nil). We don't expect users to
need a deep knowledge of the rw-cache in order to do such
experiments, but readers interested in details of the rw-cache
implementation are invited to read the ``Essay on Rw-cache'' in the
ACL2 source code.")
(SET-RW-CACHE-STATE!
(REWRITE)
"Set the default rw-cache-state non-[local]ly
Please see [set-rw-cache-state], which is the same as
set-rw-cache-state! except that the latter is not [local] to the
[encapsulate] or the book in which it occurs.")
(SET-SAVED-OUTPUT
(SET-GAG-MODE)
"Save proof output for later display with :[pso] or :[pso!]
Examples:
(set-saved-output t t) ; save proof output for later, but inhibit it now
(set-saved-output t :all) ; save proof output for later, but inhibit all
; output (except WARNING!, for critical warnings,
; and ERROR, unless these are already inhibited)
:set-saved-output t :all ; same as the line above
(set-saved-output t nil) ; save proof output for later, but print it now too
(set-saved-output nil t) ; do not save proof output, and inhibit it
(set-saved-output nil nil); do not save proof output or inhibit output
(set-saved-output nil :same), (set-saved-output t :same)
; save proof output or not, as indicated, but do
; not change which output is inhibited
(set-saved-output nil :normal)
; the behavior when ACL2 first starts up: do not
; save output, and only inhibit proof-tree output
(set-saved-output t '(warning observation proof-tree prove))
; save proof output for later, and inhibit the
; indicated kinds of output
General Form:
(set-saved-output save-flg inhibit-flg)
Parameter save-flg is t to cause output to be saved for later display
using pso or pso!; see [pso] and see [pso!], and see the
documentation for [proof-checker] commands of the same names. Set
save-flg to nil to turn off this feature; except, it always stays
on in proof-checker sessions entered with [verify]. The other
argument, inhibit-flg, controls whether output should be inhibited
when it is created (normally, during a proof attempt). So a common
combination is to set both arguments to t, to indicate that output
should be suppressed for now but saved for printing with [pso] or
[pso!]. The examples above give a good summary of the functionality
for the second argument.
Saved output is cleared at the start of every event, and also at the
start of every [proof-checker] commands that invoke the prover.
Note that interactive [proof-checker] commands, that is, from a
proof-checker session entered with [verify], are always run with
output saved.
Also see [set-gag-mode]; and see [set-print-clause-ids], which causes
subgoal numbers to be printed during proof attempts when output is
inhibited.
See [set-inhibit-output-lst] if you want to inhibit certain output
from the prover but not other output (e.g., not the summary), and
you don't want to save any output.")
(SET-SERIALIZE-CHARACTER (POINTERS)
"See [with-serialize-character].")
(SET-SKIP-META-TERMP-CHECKS
(META CLAUSE-PROCESSOR)
"Skip output checks for [meta] functions and [clause-processor]s
WARNING: Use of this macro may render ACL2 unsound, which is why it
requires a trust tag. If you obtained an error during application
of a [meta]function, a hypothesis metafunction, or a
[clause-processor], it might well be best to rewrite that function
to avoid generating terms with the ``forbidden'' function calls
described in that error message. However, judicious use of this
macro can be useful during development; the rest of this topic
describes its usage.
The result of applying a [meta]function (or a hypothesis
metafunction) must be a term. Similarly, the result of applying a
[clause-processor] must be a list of clauses, where a clause is a
list of terms. If these conditions fail, then an error occurs; see
[term-table] for how one obtains some assistance towards avoiding
such errors.
By default, ACL2 actually enforces a stronger requirement: the
resulting term or clause-list cannot contain any calls of
``forbidden'' function symbols: ones that would be illegal when
submitting a theorem. These include function symbols that are
untouchable (see [remove-untouchable]) as well as those that are
keys of the alist *ttag-fns-and-macros*.
These two checks --- that the results are terms and that they contain
no calls of forbidden function symbols --- can be expensive for
large terms. The macro set-skip-meta-termp-checks provides a way to
avoid both checks. Since these checks can be critical for
soundness, a trust tag (see [defttag]) must be active in order to
invoke this macro unless the argument is nil. It might be best to
avoid using this macro except to skip such checks that you have
identified to be expensive, and to skip them only when using ACL2
interactively (as opposed to doing batch certification jobs) ---
though this macro might also be useful in determining when such
checks are indeed expensive.
There are two legal ways to call this macro, as follows. Note that
the arguments are not evaluated.
; Skip all such checks:
(set-skip-meta-termp-checks t)
; Skip such checks for functions fn1, ..., fnk (each of which is presumably a
; metafunction, hypothesis metafunction, or clause-processor):
(set-skip-meta-termp-checks (fn1 ... fnk))
A special case of the second form above is to perform all such
checks: (set-skip-meta-termp-checks nil). No trust tag is required
in this case.
This macro actually generates a [local] [table] event, for the table
skip-meta-termp-checks-table and its unique key, t. The macro
[set-skip-meta-termp-checks] generates a corresponding non-[local]
[table] event.
ACL2 !>:trans1 (set-skip-meta-termp-checks (f g))
(LOCAL (SET-SKIP-META-TERMP-CHECKS! (F G)))
ACL2 !>:trans1 (set-skip-meta-termp-checks! (f g))
(TABLE SKIP-META-TERMP-CHECKS-TABLE T '(F G))
ACL2 !>
It is probably good practice to use set-skip-meta-termp-checks rather
than set-skip-meta-termp-checks!, except when there is a compelling
reason to do otherwise.")
(SET-SKIP-META-TERMP-CHECKS!
(META CLAUSE-PROCESSOR)
"Skip output checks non-[local]ly for [meta] functions and
[clause-processor]s
See [set-skip-meta-termp-checks].")
(SET-SPLITTER-OUTPUT
(SPLITTER)
"Turn on or off reporting of rules that may have caused case splits
Examples:
(set-splitter-output t) ; enable reports of ``splitter'' rules (default)
(set-splitter-output nil) ; disable reports of ``splitter'' rules
After evaluation of the form (set-splitter-output t) (the default),
then whenever prove output is not inhibited (see
[set-inhibit-output-lst]), ACL2 will report [rewrite] and
[definition] rules that may have reduced a goal to more than one
subgoal. See [splitter] for how to interpret such reports. We call
such rules ``splitter rules'' for the goal that is being split.
This information can be useful in deciding how to eliminate large
splits, for example of Goal into Subgoal 1000 through Subgoal 1, by
disabling some splitter rules. If you want to avoid the printing of
such information, you can put the form (set-splitter-output t) in
your customization file; see [ACL2-customization].
Note that this command does not change the ACL2 [world]; it only
modifies the [state]. More precisely, it sets a state global to the
indicated value. (See [state] for discussion of the
``global-table'' of the state.) When prove output is enabled (see
[set-inhibit-output-lst]), the value of that state global is the
value of the form ([splitter-output]); otherwise the value of that
form is nil.
Again, see [splitter] for the effects of turning on the reporting of
splitter rules.")
(SET-STATE-OK
(STATE)
"Allow the use of STATE as a formal parameter
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
In brief: The variable symbol [state] has an unusual status in ACL2.
In order to use it, you either need to issue :set-state-ok t, as we
explain below, or you need to declare it to be a [stobj], as
explained elsewhere (see [declare-stobjs]). Now we explain in more
detail.
Because the variable symbol [state] denotes the ``current ACL2
state,'' ACL2 treats the symbol very restrictively when it occurs
as a formal parameter of a defined function. The novice user, who
is unlikely to be aware of the special status of that symbol, is
likely to be confused when error messages about STATE are printed
in response to the innocent choice of that symbol as a formal
variable. Therefore the top-level ACL2 loop can operate in a mode
in which [state] is simply disallowed as a formal parameter.
For a discussion of STATE, See [state] and see [stobj]. Roughly
speaking, at the top-level, the ``current ACL2 state'' is denoted
by the variable symbol STATE. Only the current state may be passed
into a function expecting a state as an argument. Furthermore, the
name of the formal parameter into which the current state is passed
must be STATE and nothing but the current state may be passed into
a formal of that name. Therefore, only certain access and change
functions can use that formal --- namely those with a STATE formal
--- and if any such function produces a new state it becomes the
``current state'' and must be passed along in the STATE position
thereafter. Thus, ACL2 requires that the state be single-threaded.
This, in turn, allows us to represent only one state at a time and
to produce new states from it destructively in a von Neumaneque
fashion. The syntactic restrictions on the variable STATE are
enforced by the translate mechanism (see [trans] and see [term])
when terms are read.
To prevent the novice user from seeing messages prohibiting certain
uses of the variable symbol STATE ACL2 has a mode in which it
simply disallows the use of that symbol as a formal parameter. Use
of the symbol causes a simple error message. The system is
initially in that mode.
To get out of that mode, execute:
:set-state-ok t ;;; or, (set-state-ok t)
It is not recommended that you do this until you have read the
documentation of [state].
To enter the mode in which use of state is prohibited as a formal
parameter, do:
:set-state-ok nil
The mode is stored in the defaults table, See [ACL2-defaults-table].
Thus, the mode may be set [local]ly in books.")
(SET-TAU-AUTO-MODE
(TAU-SYSTEM)
"Turn on or off automatic (``greedy'') generation of :tau-system rules
Examples:
(set-tau-auto-mode t) ; select automatic (``greedy'') mode
(set-tau-auto-mode nil) ; select manual mode
This event is equivalent to (table acl2-defaults-table
:tau-auto-modep <t-or-nil>), and hence is [local] to any [books]
and [encapsulate] [events] in which it occurs; see
[ACL2-defaults-table]. See [introduction-to-the-tau-system] for
background details.
The tau system gathers rules for its database in one of two ways:
greedily or only at the explicit command of the user. ``Greedy''
mode is officially called ``automatic mode'' and is the default.
The other mode is called ``manual mode.''
In automatic mode, all rules processed by ACL2 are also considered
for inclusion in the tau database: if the :corollary of some proved
theorem happens to fit into one of the forms described in
:[tau-system], that rule is quietly added to the tau database
regardless of what :[rule-classes] the user named for the
:corollary. Of course, such rules are also stored in the ways named
by the user. See the Design Philosophy section of
[introduction-to-the-tau-system] for a discussion of why the tau
system is greedy by default. More details are given on automatic
mode after we explain manual mode.
To more tightly control the rules available to the tau system, the
user may select manual mode by executing (set-tau-auto-mode nil).
In manual mode, the only events that create :tau-system rules are
defthm events explicitly specifying the :[tau-system] rule class in
the :[rule-classes] argument. Of course, for a :tau-system rule to
be created from a proved formula (or its specified :corollary), the
formula must be of the appropriate shape (syntactic form). See
[tau-system]. In manual mode, if the :tau-system rule class is
specified but the formula is not of an appropriate form an error is
signalled. (Note: even in manual mode, monadic functions that are
recognized as Boolean are classified as tau predicates; but no
rules are created for them.)
Returning to our discussion of automatic mode, a :[tau-system] rule
may be created by any of the events below, provided the definition
or formula proved is of an appropriate shape:
(1) defun events introducing ``big switch'' or ``mv-nth synonyms,''
(2) defun events creating type-prescription rules that may be also
represented as ``signature rules'' of form 1, and
(3) any defthm event with a non-nil :rule-classes argument if no
:tau-system rule is among the rule classes and the formula proved
is in the shape of any tau-system rule.
Of course, events such as [defstobj] and [defevaluator] may also add
rules to the tau database when they execute the [defun] and
[defthm] events implicit in their descriptions. See [tau-system]
for a description of the various shapes mentioned above.
Note that any rule (of any rule class) created when the tau system is
in manual mode is also created in automatic mode. For example, if
an event would create a :DEFINITION, :TYPE-PRESCRIPTION,
FORWARD-CHAINING, or :REWRITE rule when the tau system is in manual
mode, then the event will create that same rule when the tau system
is in automatic mode. Automatic mode just means that some
additional :tau-system rules may be created.
Of course, if a defthm event explicitly specifies a :tau-system rule
class, then even if the tau system is in automatic mode, that tau
rule is created from the proved formula (or the specified
:corollary) or else an error is caused. But if the tau system is in
automatic mode and a defthm event doesn't explicitly specify a
:tau-system rule class, then the system quietly checks each
specified :corollary --- or, in the absence of any :corollary, it
checks the proved formula --- for whether it can be stored as a tau
rule. If so, then the system stores a tau rule, in addition to
storing the specified rule. Of course, no error is signalled if a
proved formula of some non-:tau-system rule class fails to be of an
appropriate shape for the tau system.
In automatic mode, if the :rule-classes specified for defthm included
several corollaries and any one of them is of class :tau-system
then the only tau system rules created are those explicitly classed
as :tau-system rules. For example, suppose a defthm has one
:corollary stored as a :rewrite rule and another :corollary stored
as a :tau-system rule. But suppose the :rewrite rule happens to
also to fit the form of a :tau-system rule. Is it added to the tau
database or not? The answer is no. If you have taken the trouble to
specify :tau-system corollaries for an event, then those
corollaries are the only ones stored as tau sytem rules from that
event. Note that had both corollaries been classed as :rewrite
rules (and been of acceptable :tau-system form) both would have
also been made :tau-system rules. This also allows you be in
automatic mode and state a :rewrite or other non-:tau-system rule
and prevent it from being also made a tau system rule: just add a
frivolous :tau-system :corollary like (booleanp (integerp x)).
Recall that the use of tau rules is controlled by the rune
(:EXECUTABLE-COUNTERPART TAU-SYSTEM). When that rune is disabled,
no tau rules are used in proofs. However, the tau system continues
to collect tau rules if the system is in automatic mode. Thus, if
and when the tau system is re-enabled, rules automatically
generated while the tau system was disabled will be used as usual
by the tau system.
Finally, note that defthm events with :rule-classes nil do not create
:tau-system rules even if the formula proved is of an appropriate
shape, regardless of whether the tau system is in automatic or
manual mode.
The macro [tau-status] provides a convenient way to enable/disable
the :[executable-counterpart] of tau-system and/or to switch
between manual and automatic modes. It may also be used to
determine the current settings of those two flags.")
(SET-TOTAL-PARALLELISM-WORK-LIMIT
(PARALLELISM)
"For ACL2(p): set thread limit for parallelism primitives
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
While the most common use of the limit described below is in
parallel proof (see [parallel-proof]), it also applies to all
parallelism primitives (see [parallel-programming]) except
[spec-mv-let] --- though we expect that rather few programming
applications will encouter this limit.
General Forms:
(set-total-parallelism-work-limit :none) ; disable the limit
(set-total-parallelism-work-limit <integer>) ; set limit to <integer>
See [parallelism-tutorial], Section ``Another Granularity Issue
Related to Thread Limitations'', for an explanation of how the host
Lisp can run out of threads. Also see
[set-total-parallelism-work-limit-error].
If the underlying runtime system (the Operating System, the host
Lisp, etc.) is unable to provide enough threads to finish executing
the parallelism work given to it, the runtime system can crash in a
very unpleasant manner (ranging from a Lisp error to completely
freezing the machine). To avoid this unpleasantness, ACL2(p) will
attempt to avoid creating so much parallelism that the runtime
system crashes.
ACL2 initially uses a conservative estimate to limit the number of
threads. To tell ACL2(p) to use a different limit, call
set-total-parallelism-work-limit with the new limit. For example,
if the current default limit is 10,000, then to allow 13,000
threads to exist, issue the following form at the top level.
(set-total-parallelism-work-limit 13000)
To disable this limit altogether, evaluate the following form:
(set-total-parallelism-work-limit :none)
The default value of total-parallelism-work-limit can be found by
calling function default-total-parallelism-work-limit. If the
default value is too high for your system please notify the ACL2
maintainers with a limit that does work for your system, as they
might then lower the default limit.")
(SET-TOTAL-PARALLELISM-WORK-LIMIT-ERROR
(PARALLELISM)
"For ACL2(p): control the action taken when the thread limit is
exceeded
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
General Forms:
(set-total-parallelism-work-limit-error t) ; cause error (default)
(set-total-parallelism-work-limit-error nil) ; disable error and
; continue serially
See [parallelism-tutorial], Section ``Another Granularity Issue
Related to Thread Limitations'', for an explanation of how the host
Lisp can run out of threads. See [set-total-parallelism-work-limit]
for further details, including an explanation of how to manage the
limit that triggers this error.
The value of state global total-parallelism-work-limit-error dictates
what occurs when the underlying runtime system runs reaches a limit
on the number of threads for parallel computation. By default, when
this limit is reached, the ACL2(p) user will receive an error and
computation will halt. At this point, the ACL2(p) user has the
following options.
(1) Remove the limit by evaluating the following form.
(set-total-parallelism-work-limit :none)
(2) Disable the error so that execution continues serially once the
available thread resources have been exhausted.
(set-total-parallelism-work-limit-error nil)
(3) Increase the limit on number of threads that ACL2(p) is willing
to create, in spite of potential risk (see
[set-total-parallelism-work-limit]). In this case, the following
query returns the current limit.
(f-get-global 'total-parallelism-work-limit)
Then to increase that limit, evaluate the following form:
(set-total-parallelism-work-limit <new-integer-value>)
For example, suppose that the value of total-parallelism-work-limit
was originally 10,000. Then evaluation of the following form
increases that limit to 13,000.
(set-total-parallelism-work-limit 13000)")
(SET-TRACE-EVISC-TUPLE
(TRACE)
"Set the trace evisc tuple
A trace evisc-tuple, which is set by this utility, provides a means
to restrict printing during tracing. See [evisc-tuple] for an
introduction to evisc-tuples; also see [set-evisc-tuple] and see
[set-iprint].
By default the ACL2 [trace] mechanism, [trace$], automatically deals
with stobjs, the logical world, and certain other large structures.
See [trace$], in particular the documentation of trace$ option
:hide. However, even with that default behavior you may want to
restrict what is printed according to the print-level and
print-length of an evisc-tuple; see [evisc-tuple].
Examples:
; Set trace evisc tuple to a standard value, using current Lisp *print-level*
; and *print-length* variables:
(set-trace-evisc-tuple t state)
; Set trace evisc tuple back to its default:
(set-trace-evisc-tuple nil state)
; Set trace evisc tuple to restrict print-level to 3 and print-length to 4,
; while hiding the logical world and suitably printing stobjs even if trace$
; option ``:hide nil'' is used. (Note: calling trace-evisceration-alist
; directly requires removing this function as `untouchable', which requires a
; trust tag; see [remove-untouchable].)
(set-trace-evisc-tuple
(evisc-tuple 3 4 (trace-evisceration-alist state) nil)
state)
General Forms:
(set-trace-evisc-tuple nil state) ; trace evisc-tuple set to standard value
(set-trace-evisc-tuple t state) ; trace evisc-tuple set to hide the logical
; world and deal with stobjs even when
; trace$ option ``:hide nil'' is supplied
(set-trace-evisc-tuple evisc-tuple state)
; tracing set to use indicated evisc-tuple
See [trace$] for a discussion of ACL2 tracing. The [evisc-tuple] used
by that trace utility is the one last installed by
set-trace-evisc-tuple (or by [set-evisc-tuple] for the
trace-evisc-tuple) --- initially to the default of nil --- unless
overriden by trace option :evisc-tuple.
Remark. If you use value t, then ACL2 will ensure that the logical
world and stobjs are kept up-to-date in the trace evisc-tuple.")
(SET-VERIFY-GUARDS-EAGERNESS
(GUARD)
"The eagerness with which [guard] verification is tried.
Example Forms: try guard verification?
(set-verify-guards-eagerness 0) ; no, unless :verify-guards t
(set-verify-guards-eagerness 1) ; yes if a guard or type is supplied
(set-verify-guards-eagerness 2) ; yes, unless :verify-guards nil
Note: This is an event! It does not print the usual event summary but
nevertheless changes the ACL2 logical [world] and is so recorded.
General Form:
(set-verify-guards-eagerness n)
where n is a variable-free term that evaluates to 0, 1, or 2. This
macro is essentially equivalent to
(table acl2-defaults-table :verify-guards-eagerness n)
and hence is [local] to any [books] and [encapsulate] [events] in
which it occurs; see [ACL2-defaults-table]. However, unlike the
above simple call of the [table] event function (see [table]), no
output results from a set-verify-guards-eagerness event.
Set-verify-guards-eagerness may be thought of as an event that merely
sets a flag to 0, 1, or 2. The flag is used by certain [defun]
[events] to determine whether [guard] verification is tried. The
flag is irrelevant to those [defun] [events] in :[program] mode and
to those [defun] [events] in which an explicit :[verify-guards]
setting is provided among the [xargs]. In the former case, [guard]
verification is not done because it can only be done when logical
functions are being defined. In the latter case, the explicit
:[verify-guards] setting determines whether [guard] verification is
tried. So consider a :[logic] mode [defun] in which no
:[verify-guards] setting is provided. Is [guard] verification
tried? The answer depends on the eagerness setting as follows. If
the eagerness is 0, [guard] verification is not tried. If the
eagerness is 1, it is tried if and only if a guard is explicitly
specified in the [defun], in the following sense: there is an xargs
keyword :guard or :stobjs or a [type] declaration. If the eagerness
is 2, [guard] verification is tried.
The above remarks apply to [verify-termination] [events], according
to whether guards are explicitly specified in the existing,
corresponding :[program] mode definitions.
The default behavior of the system is as though the
:verify-guards-eagerness is 1. The current behavior can be
ascertained by evaluating the form (default-verify-guards-eagerness
(w state)).")
(SET-WATERFALL-PARALLELISM
(PARALLELISM)
"For ACL2(p): configuring the parallel execution of the waterfall
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
General Forms:
(set-waterfall-parallelism nil) ; never parallelize (serial execution)
(set-waterfall-parallelism :full) ; always parallelize
(set-waterfall-parallelism :top-level) ; parallelize top-level subgoals
(set-waterfall-parallelism ; parallelize if sufficient resources
:resource-based) ; (recommended setting)
(set-waterfall-parallelism t) ; alias for :resource-based
(set-waterfall-parallelism ; parallelize if sufficient resources
:resource-and-timing-based ; and suggested by prior attempts
(set-waterfall-parallelism ; never parallelize but use parallel
:pseudo-parallel) ; code base (a debug mode)
Set-waterfall-parallelism evaluates its argument, which specifies the
enabling or disabling of the [parallel] execution of ACL2's main
proof process, the waterfall.
It also sets [state] global waterfall-printing to an appropriate
value. See [set-waterfall-printing].
Note that not all ACL2 features are supported when
waterfall-parallelism is set to non-nil (see
[unsupported-waterfall-parallelism-features]).
A value of t is treated the same as a value of :resource-based and is
provided for user convenience.
:Resource-based waterfall parallelism typically achieves the best
performance in ACL2(p), while maintaining system stability, so
:resource-based (or equivalently, t) is the recommended value.
A value of nil indicates that ACL2(p) should never prove subgoals in
parallel.
A value of :full indicates that ACL2(p) should always prove
independent subgoals in parallel.
A value of :top-level indicates that ACL2(p) should prove each of the
top-level subgoals in parallel but otherwise prove subgoals in a
serial manner. This mode is useful when the user knows that there
are enough top-level subgoals, many of which take a non-trivial
amount of time to be proved, such that proving them in parallel
will result in a useful reduction in overall proof time.
A value of :resource-based (or equivalently, t) indicates that
ACL2(p) should use its built-in heuristics to determine whether CPU
core resources are available for parallel execution. Note that
ACL2(p) does not hook into the operating system to determine the
workload on the machine. ACL2(p) works off the assumption that it
is the only process using significant CPU resources, and it
optimizes the amount of parallelism based on the number of CPU
cores in the system. (Note that ACL2(p) knows how to obtain the
number of CPU cores from the operating system in CCL, but that, in
SBCL and in Lispworks, a constant is used instead).
During the first proof attempt of a given conjecture, a value of
:resource-and-timing-based results in the same behavior as with
:resource-based. However, on subsequent proof attempts, the time it
took to prove each subgoal will be considered when deciding whether
to parallelize execution. If a particular theorem's proof is
already achieving satisfactory speedup via :resource-based
parallelism, there is no reason to try this setting. However, if
the user wishes to experiment, the :resource-and-timing-based
setting may improve performance. Note that since the initial run
does not have the subgoal proof times available, this mode will
never be better than the :resource-based setting for
non-interactive theorem proving.
A value of :pseudo-parallel results in using the parallel waterfall
code, but with serial execution. This setting is useful for
debugging the code base that supports parallel execution of the
waterfall. For example, you may wish to use this mode if you are an
``ACL2 Hacker'' who would like to see comprehensible output from
tracing (see [trace$]) the @par versions of the waterfall
functions.
Since [memoization] is not supported when waterfall parallelism is
enabled (see [unsupported-waterfall-parallelism-features]), then
when set-waterfall-parallelism is called with a non-nil value, all
memoized functions are unmemoized. When set-waterfall-parallelism
is again called with a nil value, those memoization settings are
restored.
Set-waterfall-parallelism is an embedded event form. However, a call
of this macro will not affect waterfall-parallelism when including
a certified book that contains that call. For such an effect, you
may use the following [make-event] form; also see
[non-parallel-book].
(make-event (er-progn (set-waterfall-parallelism :full)
(value '(value-triple nil)))
:check-expansion t)
To enable waterfall parallelism for book certification using ACL2(p),
see [waterfall-parallelism-for-book-certification].")
(SET-WATERFALL-PARALLELISM-HACKS-ENABLED
(PARALLELISM)
"For ACL2(p): enable waterfall-parallelism hacks
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
General Forms:
(set-waterfall-parallelism-hacks-enabled t)
(set-waterfall-parallelism-hacks-enabled nil)
Some features (e.g., [override-hints] and [clause-processor]s) of
serial ACL2 are by default not available in ACL2(p) with waterfall
parallelism enabled, because they offer a mechanism to modify
[state] that is unsound. To allow or (once again) disallow the use
the these features in ACL2(p), call
set-waterfall-parallelism-hacks-enabled with argument t or nil,
respectively.
Set-waterfall-parallelism-hacks-enabled requires the use of a trust
tag (see [defttag]). One can call
[set-waterfall-parallelism-hacks-enabled!] instead, which will
automatically install a trust tag named
:waterfall-parallelism-hacks.
See [error-triples-and-parallelism] for further related discussion.")
(SET-WATERFALL-PARALLELISM-HACKS-ENABLED!
(PARALLELISM)
"For ACL2(p): enabling waterfall parallelism hacks
See [set-waterfall-parallelism-hacks-enabled].")
(SET-WATERFALL-PRINTING
(PARALLELISM)
"For ACL2(p): configuring the printing that occurs within the
parallelized waterfall
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
General Forms:
(set-waterfall-printing :full) ; print everything
(set-waterfall-printing :limited) ; print a subset that's thought to be useful
(set-waterfall-printing :very-limited) ; print an even smaller subset
Set-waterfall-printing evaluates its argument, which indicates how
much printing should occur when executing ACL2 with the
parallelized version of the waterfall. It only affects the printing
that occurs when parallelism mode is enabled for the waterfall (see
[set-waterfall-parallelism]).
A value of :full is intended to print the same output as in serial
mode. This output will be interleaved unless the
waterfall-parallelism mode is one of nil or :pseudo-parallel.
A value of :limited omits most of the output that occurs in the
serial version of the waterfall. Instead, the proof attempt prints
key checkpoints (see [ACL2p-key-checkpoints]). The value of
:limited also prints messages that indicate which subgoal is
currently being proved, along with the wall-clock time elapsed
since the theorem began its proof; and if state global
'waterfall-printing-when-finished has a non-nil value, then such a
message will also be printed at the completion of each subgoal. The
function print-clause-id-okp may receive an attachment to limit
such printing; see [set-print-clause-ids]. Naturally, these subgoal
numbers can appear out of order, because the subgoals can be proved
in parallel.
A value of :very-limited is treated the same as :limited, except that
instead of printing subgoal numbers, the proof attempt prints a
period (`.') each time it starts a new subgoal.
Note that this form cannot be used at the top level of a book, or of
a [progn] or [encapsulate] event. Here is a workaround for use in
such contexts; of course, you may replace :very-limited with any
other legal argument for set-waterfall-printing.
(make-event (er-progn (set-waterfall-printing :very-limited)
(value '(value-triple nil))))
(For more about event contexts and the use of make-event, see
[make-event], in particular the section ``Restriction to Event
Contexts.'')
The following form has the effect described above, except that it
will affect waterfall-printing even when including a certified book
that contains it.
(make-event (er-progn (set-waterfall-printing :very-limited)
(value '(value-triple nil)))
:check-expansion t)
Note that set-waterfall-printing is automatically called by
[set-waterfall-parallelism].
To enable the printing of information when a subgoal is finished,
assign a non-nil value to global waterfall-printing-when-finished.
This can be accomplished by entering the following at the top
level:
(f-put-global 'waterfall-printing-when-finished t state)")
(SET-WELL-FOUNDED-RELATION
(DEFUN)
"Set the default well-founded relation
Examples:
(set-well-founded-relation lex2)
provided lex2 has been proved to be a well-founded relation (see
[well-founded-relation]). Note: This is an event! It does not print
the usual event summary but nevertheless changes the ACL2 logical
[world] and is so recorded.
General Form:
(set-well-founded-relation rel)
where rel has been proved to be a well-founded relation on objects
satisfying some predicate, mp; see [well-founded-relation]. This
macro is equivalent to (table acl2-defaults-table
:well-founded-relation 'rel), and hence is [local] to any [books]
and [encapsulate] [events] in which it occurs; see
[ACL2-defaults-table].
This event sets the default well-founded relation to be that imposed
on mp-measures by the relation rel. Subsequently, if a recursively
defined function is submitted to [defun] with no explicitly given
:[well-founded-relation] argument, [defun] uses the default
relation, rel, and the associated domain predicate mp used in its
well-foundedness theorem. That is, the termination conditions
generated will require proving that the measure used by the [defun]
is an mp-measure and that in every recursive call the measure of
the arguments decreases according to rel.")
(SET-WORMHOLE-DATA
(WORMHOLE)
"Sets the wormhole data object in a wormhole status object
General Form: (set-wormhole-data whs data)
See [wormhole]. Whs should be a well-formed wormhole status; data is
arbitrary. This function returns a new status with the same entry
code as whs but with the new data. It avoids unnecessary consing if
the data for whs is already set to data. This function does not
affect state or a wormhole's hidden status. It just returns a
(possibly) new status object suitable as the value of the lambda
expressions in [wormhole-eval] and [wormhole].")
(SET-WORMHOLE-ENTRY-CODE
(WORMHOLE)
"Sets the wormhole entry code in a wormhole status object
General Form: (set-wormhole-entry-code whs code)
See [wormhole]. Whs should be a well-formed wormhole status and code
should be :ENTER or :SKIP. This function returns a new status with
the specified entry code but the same data as whs. It avoids
unnecessary consing if the entry code for whs is already set to
code. This function does not affect state or a wormhole's hidden
status. It just returns a (possibly) new status object suitable as
the value of the lambda expressions in [wormhole-eval] and
[wormhole].")
(SET-WRITE-ACL2X
(BOOKS-REFERENCE)
"Cause [certify-book] to write out a .acl2x file
Example Forms:
(set-write-acl2x nil state)
(set-write-acl2x t state)
(set-write-acl2x '(nil) state) ; same as just above, but allow inclusion of
; uncertified books during certify-book
(set-write-acl2x '(t) state)
(set-write-acl2x '(include-book-with-locals) state)
General Form:
(set-write-acl2x val state)
where val evaluates to t, nil, or a one-element list whose element is
a legal value for the global 'ld-skip-proofsp; see
[ld-skip-proofsp]. The value returned is an error triple, which in
the non-error case is (mv nil v state), where v is the value of val
and state is the result of updating the input [state] by assigning
state global 'write-acl2x the value v.
The command (set-write-acl2x val state) assigns the value of val to
the [state] global variable 'write-acl2x, affecting whether or not
[certify-book] writes out a file with extension acl2x, called a
``.acl2x file'' and pronounced ``dot-acl2x file''. Such a file is
read or written by [certify-book] when it is supplied with keyword
argument :acl2x t. By default, such a call of certify-book reads a
.acl2x file; but if the value of state global variable 'write-acl2x
is not nil, then certify-book writes a .acl2x file (in which case
it is illegal to specify a non-nil value for [certify-book] keyword
argument :pcert). Consider for example (certify-book \"foo\" 0 nil
:acl2x t). By default, this command reads file foo.acl2x, which
supplies replacements for some forms in foo.lisp, as described
later below. But if the value of state global 'write-acl2x is not
nil, then instead, this certify-book command writes such a file
foo.acl2x.
Before we discuss the function of .acl2x files, we first explain more
about how a non-nil value of [state] global 'write-acl2x affects
the behavior of a command (certify-book ... :acl2x t ...). A
significant effect on the behavior is that after processing events
in the given book, ACL2 writes out a .acl2x file and then returns,
skipping the other subsequent actions typically performed by
[certify-book]: a [local-incompatibility] check, writing of a
[certificate] file, and possibly [compilation]. Another effect is
that proofs may be skipped when processing [events] assuming that
the the certify-book command does not explicitly specify
:skip-proofs-okp nil, as we now explain. A non-nil value of
'write-acl2x should either be t or a one-element list (x), where x
is a legal value for the [state] global 'ld-skip-proofsp (see
[ld-skip-proofsp]). In both cases, certify-book will process
[events] to write out a .acl2x file as described above. But in the
latter (list) case, event processing will take place according to
the value of x: in particular, proofs will be skipped when x is not
nil, and if moreover x is the symbol include-book-with-locals, then
only one pass will be made through each [encapsulate] form. A third
effect of a non-nil value of 'write-acl2x, which is restricted to
the list case, is that [include-book] events encountered during
event processing are allowed to succeed on uncertified books,
something that is prohibited during most calls of [certify-book].
When [certify-book] is used to write out a .acl2x file, there is
typically a subsequent run of [certify-book] that reads that file.
Consider how this can work with a book foo.lisp. In the first call
of certify-book, a file foo.acl2x is written that contains all
[make-event] expansions, but foo.cert is not written. In the second
call of certify-book, no [make-event] expansion typically takes
place, because foo.acl2x supplies the expansions. The command
(set-write-acl2x t state) should be evaluated before the first
certification (though another legal non-nil value may be used in
place of t), setting the value of [state] global 'write-acl2x to t,
to enable writing of foo.acl2x; and the command (set-write-acl2x
nil state) may be evaluated before the second run (though this is
not necessary in a fresh ACL2 session) in order to complete the
certification (writing out foo.cert) using foo.acl2x to supply the
[make-event] expansions.
When [Certify-book] is supplied with keyword argument :acl2x t it
will read or write the book's .acl2x file; when supplied with
:acl2x nil, it will not read or write that .acl2x file. The value
of :acl2x is nil by default. The interaction of [certify-book] with
the corresponding .acl2x file is as follows.
o If :acl2x is t, then:
- If set-write-acl2x has been (most recently) called with a value of
t for its first argument,then ACL2 writes the corresponding
.acl2x file.
- If set-write-acl2x has been (most recently) called with a value of
nil for its first argument, or not called at all, then ACL2 insists
on a corresponding .acl2x file that is at least as recent as the
corresponding .lisp file, causing an error otherwise.
o If :acl2x is nil,then:
- If set-write-acl2x has been (most recently) called with a value
t for its first argument, or if argument :ttagsx is supplied,
then an error occurs.
- If the .acl2x file exists, then regardless of whether or how
set-write-acl2x has been called, ACL2 ignores the .acl2x file
but issues a warning about it.
Suppose you use the two-runs approach: first write a .acl2x file,
then certify using (reading) that .acl2x file. Then with scripts
such as makefiles, then you may wish to provide a single
[certify-book] command to use for both runs. For that purpose,
[certify-book] supports the keyword argument :ttagsx. If this
argument is supplied and write-acl2x is true, then this argument is
treated as the :ttags argument, overriding a :ttags argument if
present. That is, for the two runs, :ttagsx may be used to specify
the trust tags used in the first certification while :ttags
specifies the trust tags, if any (else :ttags may be omitted), used
in the second certification. Note: If the argument :ttagsx is not
supplied, then its value defaults to the (explicit or default)
value of the :ttags argument.
The built-in ACL2 Makefile support automatically generates suitable
dependencies if you create a .acl2 file with a [certify-book] call
matching the following regular expression, case-independent:
(certify-book[^;]*:acl2x t
For an example .acl2 file with a certify-book call matching the above
pattern, see community books file
books/make-event/double-cert-test-1.acl2.
Note that [include-book] is generally not affected by
set-write-acl2x, other than through the indirect effect on
[certify-book]. More precisely: All expansions are stored in the
[certificate] file, so when [include-book] is applied to a
certified book, the .acl2x file is not consulted.
An example of how to put this all together may be found in community
book books/make-event/double-cert-test-1.lisp. There, we see the
following form.
(make-event
(progn (defttag :my-ttag)
(progn! (let ((val (sys-call \"pwd\" nil)))
(value (list 'defun 'foo () val))))))
Imagine that in place of the binding computed using [sys-call], which
by the way requires a trust tag, is some computation of your choice
(such as reading forms from a file) that is used to construct your
own event, in place of the [defun] event constructed above. The
Makefile in that directory contains the following added dependency,
so that file double-cert-test-1.acl2x will be created:
double-cert-test-1.cert: double-cert-test-1.acl2x
There is also the file double-cert-test-1.acl2 in that directory,
which contains a single form as follows.
(certify-book \"double-cert-test-1\" ? t :ttagsx :all :ttags nil)
Thus, a call of `make' first creates file double-cert-test-1.acl2x,
which uses the above :ttagsx argument in order to support the use
of [defttag] during [make-event] expansion. Then, `make' goes on to
cause a second certification in which no trust tags are involved.
As a result, the parent book double-cert-test.lisp is ultimately
certified without requiring any trust tags.
The discussion above is probably sufficient for most users of the
two-run approach it describes. We conclude with further details for
those who want more information. Those who wish to see a yet
lower-level explanation of how all this works are invited to read
the comment in the ACL2 source code entitled ``Essay on .acl2x
Files (Double Certification).
Consider the .acl2x file produced by the first run as described
above. It contains a single expression, which is an association
list whose keys are all positive integers, which occur in
increasing order. When the .acl2x file is present and at least as
recent as the corresponding .lisp file, then for a subsequent
[certify-book] with argument :acl2x t and the (default) value of
nil for [state] global 'write-acl2x, that association list will be
applied to the top-level events in the book, as follows. Suppose
the entry (n . ev) belongs to the association list in the .acl2x
file. Then n is a positive integer, and the nth top-level event in
the book --- where the 0th event is the initial [in-package] form
--- will be replaced by ev. In practice, ev is the [make-event]
expansion created during certification for the nth top-level event
in the book; and this will always be the case if the .acl2x file is
created by [certify-book] after execution of the form
(set-write-acl2x t state). However, you are welcome to associate
indices manually with any [events] you wish into the alist stored
in the .acl2x file.
Note: Also see the community book make-event/acl2x-help.lisp for a
useful utility that can be used to skip proofs during the writing
of .acl2x files.")
(SETENV$
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Set an environment variable
(Setenv$ str val), where str and val are strings, sets the
environment variable str to have value val, for subsequent read by
getenv$ (see [getenv$]), and returns nil. Or, if this operation is
not implemented for the host Common Lisp, an error will occur.
Example:
(setenv$ \"FOO\" \"BAR\")
It may be surprising that setenv$ returns nil; indeed, it neither
takes nor returns the ACL2 [state]. The reason is that [getenv$]
takes responsibility for trafficking in [state]; it is defined in
the logic using the function [read-ACL2-oracle], which (again, in
the logic) does modify state, by popping an entry from its
acl2-oracle field. [getenv$].
As suggested above, a call of [getenv$] takes into account the most
recent call of setenv$ on the same environment variable. It may
also be the case that setenv$ modifies the environment of the
underlying process; for example, we think this is probably the case
for most invocations of ACL2 built on a host Lisp that is CCL,
SBCL, or CMUCL, as well as others perhaps. If you want to rely on
such behavior, however, we advise you to look at source code.
Function: <setenv$>
(defun setenv$ (str val)
(declare (xargs :guard (and (stringp str) (stringp val))))
(declare (ignore str val))
nil)")
(SEVENTH
(NTH ACL2-BUILT-INS)
"Seventh member of the list
See any Common Lisp documentation for details.")
(SHARP-BANG-READER
(READER PACKAGES)
"Package prefix that is not restricted to symbols
Examples:
ACL2 !>(defpkg \"FOO\" nil)
Summary
Form: ( DEFPKG \"FOO\" ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
\"FOO\"
ACL2 !>'#!foo(a b)
(FOO::A FOO::B)
ACL2 !>'#!foo(a #!acl2 b)
(FOO::A B)
ACL2 !>'#!foo(#!acl2 a b)
(A FOO::B)
ACL2 !>'#!foo(#!\"ACL2\" a b)
(A FOO::B)
ACL2 !>
The ACL2 reader supports the syntax #!pkg-name expr where pkg-name is
a string or symbol that names a package known to ACL2. As
illustrated above, this syntax nests as one might expect. In the
special case that expr is a symbol, #!pkg-name expr is equivalent
to pkg-name::expr.")
(SHARP-DOT-READER
(READER DEFCONST)
"Read-time evaluation of constants
Example:
ACL2 !>(defconst *a* '(a b c))
Summary
Form: ( DEFCONST *A* ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
*A*
ACL2 !>(quote (1 2 #.*a* 3 4))
(1 2 (A B C) 3 4)
ACL2 !>
The ACL2 reader supports the syntax #.*a* where *a* was defined by
[defconst]. In this case, the reader treats #.*a* as though it were
reading the value of *a*. This feature can be useful in conjunction
with the use of [evisc-table] to abbreviate large constants, so
that the abbreviation can be read back in; see [evisc-table].
Remarks.
(1) The ACL2 reader only supports `#.' as described above, unlike
Common Lisp. Older versions (preceding 3.5) used `#.' to abort, but
that functionality is now carried out by (a!); see [a!]. For a
related feature that only pops up one level, see [p!].
(2) If you call [certify-book] on a book that contains a form
`#.*foo*', the *foo* must already be defined in the [world] in
which you issue the certify-book command. The reason is that
certify-book reads the entire book before evaluating its forms.")
(SHARP-U-READER
(READER NUMBERS)
"Allow underscore characters in numbers
Example:
ACL2 !>#ub1000_1000_1000_
2184
ACL2 !>#b100010001000
2184
ACL2 !>#uo1_1
9
ACL2 !>#o11
9
ACL2 !>#u34_5
345
ACL2 !>#u345
345
ACL2 !>345
345
ACL2 !>#ux12_a
298
ACL2 !>#ux12a
298
ACL2 !>#u x12a
298
ACL2 !>#x12a
298
ACL2 !>#u123_456/7_919
123456/7919
ACL2 !>
The ACL2 reader supports the use of #ub, #uo, and #ux where one would
otherwise write #b, #o, and #x, respectively (for binary, octal,
and hexadecimal numerals), but where underscore characters (`_')
are allowed but ignored. Also supported is the prefix #u in front
of a an expression that is a decimal numeral except that underscore
characteres are allowed but ignored.
The precise specification of #u is as follows. The Lisp reader reads
one expression after the #u. If the result is a number, then that
number is returned by the reader. Otherwise the result must be a
symbol whose name begins with one of the characters `B', `O', or
`X', or else a decimal digit (one of the characters `0, 1, ...,
9'). All underscores are removed from the name of that symbol to
obtain a string and in the first three cases only, a `#' character
is prepended to that string. The resulting string is then handed to
the Lisp reader in order to obtain the final result, which must be
a number or else an error occurs.")
(SHOW-ACCUMULATED-PERSISTENCE (POINTERS)
"See [accumulated-persistence].")
(SHOW-BDD
(BDD)
"Inspect failed BDD proof attempts
Attempts to use BDDs (see [bdd]), using :[bdd] [hints], can fail for
various reasons. Sometimes it is useful to explore such failures.
To do so, one may simply execute the form
(show-bdd)
inside the ACL2 loop. The system's response is generally
self-explanatory. Perhaps you have already seen show-bdd used in
some examples (see [bdd-introduction] and see [if*]). Here we give
some details about show-bdd.
(Show-bdd) prints the goal to which the BDD procedure was applied and
reports the number of nodes created during the [bdd] computation,
followed by additional information depending on whether or not the
computation ran to completion or aborted (for reasons explained
elsewhere; see [bdd-algorithm]). If the computation did abort, a
backtrace is printed that should be useful in understanding where
the problem lies. Otherwise, (show-bdd) prints out ``falsifying
constraints.'' This list of pairs associates [term]s with values
and suggests how to construct a binding list for the variables in
the conjecture that will falsify the conjecture. It also prints out
the [term] that is the result of simplifying the input [term]. In
each of these cases, parts of the object may be hidden during
printing, in order to avoid creating reams of uninteresting output.
If so, the user will be queried about whether he wishes to see the
entire object (alist or [term]), which may be quite large. The
following responses are legal:
w --- Walk around the object with a structure editor
t --- Print the object in full
nil --- Do not print any more of the object
Show-bdd actually has four optional arguments, probably rarely used.
The general form is
(show-bdd goal-name goal-ans falsifying-ans term-ans)
where goal-name is the name of the goal on which the :[bdd] hint was
used (or, nil if the system should find such a goal), goal-ans is
the answer to be used in place of the query for whether to print
the input goal in full, falsifying-ans is the answer to be used in
place of the query for whether to print the falsifying constraints
in full, and term-ans is the answer to be used in place of the
query for whether to print the resulting [term] in full.")
(SHOW-BODIES
(DEFINITION)
"Show the potential definition bodies
Examples:
(show-bodies foo)
:show-bodies foo
A definition made using [defun] installs a so-called ``body'' of a
function symbol, as do certain :[definition] rules. Such bodies are
used in a number of ways, including the application of :expand
[hints]; see [definition], in particular the discussion of ``body''
there, and see [hints] for a discussion of the :expand hint. Also
see [set-body] for how to change which of the available definitions
(among the original definition and appropriate :[definition] rules)
is the one that provides the body. The show-bodies command displays
the available such bodies in an appropriate format, starting with
the one that is currently used as the body.
General Forms:
(show-bodies function-symbol)
:show-bodies function-symbol")
(SHOW-CUSTOM-KEYWORD-HINT-EXPANSION
(CUSTOM-KEYWORD-HINTS)
"Print out custom keyword hints when they are expanded
Examples:
(show-custom-keyword-hint-expansion t)
(show-custom-keyword-hint-expansion nil)
General Form:
(show-custom-keyword-hint-expansion flg)
If the value of flg is non-nil, then when custom keyword hints are
expanded, the system prints the results of each expansion. This is
sometimes useful for debugging custom keyword hints and, from time
to time, may be useful in understanding how a custom hint affects
some proof attempt.
The default setting is nil.
For an explanation of how custom keyword hints are processed, see
[custom-keyword-hints].")
(SHOW-FC-CRITERIA
(FORWARD-CHAINING-REPORTS)
"Print the forward-chaining tracking criteria
Example: (show-fc-criteria)
This function prints the list of triples being used to determine what
is tracked during forward chaining.
See [forward-chaining-reports] for details.")
(SIGNATURE
(ENCAPSULATE)
"How to specify the arity of a constrained function
We start with a gentle introduction to signatures, where we pretend
that there are no single-threaded objects (more on that below ---
for now, if you don't know anything about single-threaded objects,
that's fine!). Here are some simple examples of signatures.
((hd *) => *)
((pair * *) => *)
((foo * *) => (mv * * *))
The first of these says that hd is a function of one argument, while
the other two say that pair and foo are functions that each take
two arguments. The first two say that hd and pair return a single
value. The third says that foo returns three values, much as the
following definition returns three values:
(defun bar (x y)
(mv y x (cons x y)))
Corresponding ``old-style'' signatures are as follows. In each case,
a function symbol is followed by a list of formal parameters and
then either t, to denote a single value return, or (mv t t t), to
denote a multiple value return (in this case, returning three
values).
(hd (x) t)
(pair (x y) t)
(foo (x y) (mv t t t))
That concludes our gentle introduction. The documentation below is
more general, for example covering single-threaded objects and
keyword values such as :guard. When reading what follows below, it
is sufficient to know about single-threaded objects (or ``stobjs'')
that each has a unique symbolic name and that [state] is the name
of the only built-in single-threaded object. All other stobjs are
introduced by the user via [defstobj] or [defabsstobj]. An object
that is not a single-threaded object is said to be ``ordinary.''
For a discussion of single-threaded objects, see [stobj].
Examples:
((hd *) => *)
((hd *) => * :formals (x) :guard (consp x))
((printer * state) => (mv * * state))
((mach * mach-state * state) => (mv * mach-state))
General Form:
((fn ...) => *)
((fn ...) => stobj)
or
((fn ...) => (mv ...))
or for part1 and part2 as above,
(part1 => part2 :kwd1 val1 ... :kwdn valn)
where fn is the constrained function symbol, ... is a list of
asterisks and/or the names of single-threaded objects, stobj is a
single-threaded object name, and the optional :kwdi and :vali are
as described below. ACL2 also supports an older style of signature,
described below after we describe the preferred style.
Signatures specify three syntactic aspects of a function symbol: (1)
the ``arity'' or how many arguments the function takes, (2) the
``multiplicity'' or how many results it returns via MV, and (3)
which of those arguments and results are single-threaded objects
and which objects they are.
A signature typically has the form ((fn x1 ... xn) => val). Such a
signature has two parts, separated by the symbol ``=>''. The first
part, (fn x1 ... xn), is suggestive of a call of the constrained
function. The number of ``arguments,'' n, indicates the arity of
fn. Each xi must be a symbol. If a given xi is the symbol ``*''
then the corresponding argument must be ordinary. If a given xi is
any other symbol, that symbol must be the name of a single-threaded
object and the corresponding argument must be that object. No stobj
name may occur twice among the xi.
The second part, val, of a signature is suggestive of a term and
indicates the ``shape'' of the output of fn. If val is a symbol
then it must be either the symbol ``*'' or the name of a
single-threaded object. In either case, the multiplicity of fn is 1
and val indicates whether the result is ordinary or a stobj.
Otherwise, val is of the form (mv y1 ... yk), where k > 1. Each yi
must be either the symbol ``*'' or the name of a stobj. Such a val
indicates that fn has multiplicity k and the yi indicate which
results are ordinary and which are stobjs. No stobj name may occur
twice among the yi, and a stobj name may appear in val only if
appears among the xi.
A signature may have the form ((fn x1 ... xn) => val . k), where k is
a [keyword-value-listp], i.e., an alternating list of keywords and
values starting with a keyword. In this case ((fn x1 ... xn) =>
val) must be a legal signature as described above. The legal
keywords in k are :GUARD and :FORMALS (except that for ACL2(r),
also see the remark about :CLASSICALP later in this topic). The
value following :FORMALS is to be the list of formal parameters of
fn, which must be consistent with the parameters specified in (fn
x1 ... xn): they must both specify the same arity (number of formal
parameters) and the same [stobj] inputs. The value following :GUARD
is a term that is to be the [guard] of fn. Note that this guard is
never actually evaluated, and is not subject to the guard
verification performed on functions introduced by [defun] (see
[verify-guards]). Said differently: this guard need not itself have
a guard of t. Indeed, the guard is only used for attachments; see
[defattach]. Note that if :GUARD is supplied then :FORMALS must
also be supplied (in order to relate the variables occurring in the
guard to the parameters of fn). One final observation about guards:
if the :GUARD keyword is omitted, then the guard defaults to T.
Before ACL2 supported user-declared single-threaded objects there was
only one single-threaded object: ACL2's built-in notion of [state].
The notion of signature supported then gave a special role to the
symbol state and all other symbols were considered to denote
ordinary objects. ACL2 still supports the old form of signature,
but it is limited to functions that operate on ordinary objects or
ordinary objects and state.
Old-Style General Form:
(fn formals result . k)
where fn is the constrained function symbol, formals is a suitable
list of formal parameters for it, k is an optional
[keyword-value-listp] (see below), and result is either a symbol
denoting that the function returns one result or else result is an
[mv] expression, (mv s1 ... sn), where n>1, each si is a symbol,
indicating that the function returns n results. At most one of the
formals may be the symbol STATE, indicating that corresponding
argument must be ACL2's built-in [state]. If state appears in
formals then state may appear once in result. All ``variable
symbols'' other than state in old style signatures denote ordinary
objects, regardless of whether the symbol has been defined to be a
single-threaded object name!
The optional k is as described above for newer-style signatures,
except that the user is also allowed to declare which symbols
(besides state) are to be considered single-threaded object names.
Thus :STOBJS is also a legal keyword. The form
(fn formals result ... :stobjs names ...)
specifies that names is either the name of a single-threaded object
or else is a list of such names. Every name in names must have been
previously defined as a stobj via [defstobj] or [defabsstobj].
As promised above, we conclude with a remark about an additional
keyword, :CLASSICALP, that is legal for ACL2(r) (see [real]). The
value of this keyword must be t (the default) or nil, indicating
respectively whether fn is classical or not.")
(SIGNED-BYTE-P
(NUMBERS ACL2-BUILT-INS)
"Recognizer for signed integers that fit in a specified bit width
(Signed-byte-p bits x) is T when bits is a positive integer and x is
a signed integer whose 2's complement representation fits in a
bit-width of bits, i.e., -2^(bits-1) <= x < 2^(bits-1).
Note that a [type-spec] of (signed-byte i) for a variable x in a
function's [declare] form translates to a [guard] condition of
(signed-byte-p i x).
The [guard] for signed-byte-p is T.
Function: <signed-byte-p>
(defun signed-byte-p (bits x)
(declare (xargs :guard t))
(and (integerp bits)
(< 0 bits)
(integer-range-p (- (expt 2 (1- bits)))
(expt 2 (1- bits))
x)))")
(SIGNUM
(NUMBERS ACL2-BUILT-INS)
"Indicator for positive, negative, or zero
(Signum x) is 0 if x is 0, -1 if x is negative, and is 1 otherwise.
The [guard] for signum requires its argument to be rational ([real],
in ACL2(r)) number.
Signum is a Common Lisp function. See any Common Lisp documentation
for more information.
From ``Common Lisp the Language'' page 206, we see a definition of
signum in terms of [abs]. As explained elsewhere (see [abs]), the
[guard] for [abs] requires its argument to be a rational ([real],
in ACL2(r)) number; hence, we make the same restriction for signum.
Function: <signum>
(defun signum (x)
(declare (xargs :guard (real/rationalp x)))
(if (zerop x) 0 (if (minusp x) -1 1)))")
(SIMPLE
(REWRITE DEFINITION)
":[definition] and :[rewrite] rules used in preprocessing
Example of simple rewrite rule:
(equal (car (cons x y)) x)
Examples of simple definition:
(defun file-clock-p (x) (integerp x))
(defun naturalp (x)
(and (integerp x) (>= x 0)))
The theorem prover output sometimes refers to ``simple'' definitions
and rewrite rules. These rules can be used by the preprocessor,
which is one of the theorem prover's ``processes'' understood by
the :do-not hint; see [hints].
The preprocessor expands certain definitions and uses certain rewrite
rules that it considers to be ``fast''. There are two ways to
qualify as fast. One is to be an ``abbreviation'', where a rewrite
rule with no hypotheses or loop stopper is an ``abbreviation'' if
the right side contains no more variable occurrences than the left
side, and the right side does not call the functions [if], [not] or
[implies]. Definitions and rewrite rules can both be abbreviations;
the criterion for definitions is similar, except that the
definition must not be recursive. The other way to qualify applies
only to a non-recursive definition, and applies when its body is a
disjunction or conjunction, according to a perhaps subtle criterion
that is intended to avoid case splits.")
(SINGLE-THREADED-OBJECTS (POINTERS)
"See [stobj].")
(SIXTH
(NTH ACL2-BUILT-INS)
"Sixth member of the list
See any Common Lisp documentation for details.")
(SKIP-PROOFS
(EVENTS)
"Skip proofs for a given form --- a quick way to introduce unsoundness
Example Form:
(skip-proofs
(defun foo (x)
(if (atom x) nil (cons (car x) (foo (reverse (cdr x)))))))
General Form:
(skip-proofs form)
where form is processed as usual except that the proof obligations
usually generated are merely assumed.
Normally form is an event; see [events]. If you want to put
skip-proofs around more than one event, consider the following (see
[progn]): (skip-proofs (progn event1 event2 ... eventk)).
WARNING: Skip-proofs allows inconsistent [events] to be admitted to
the logic. Use it at your own risk!
Sometimes in the development of a formal model or proof it is
convenient to skip the proofs required by a given event. By
embedding the event in a skip-proofs form, you can avoid the proof
burdens generated by the event, at the risk of introducing
unsoundness. Below we list four illustrative situations in which
you might find skip-proofs useful.
1. The termination argument for a proposed function definition is
complicated. You presume you could admit it, but are not sure that
your definition has the desired properties. By embedding the
[defun] event in a skip-proofs you can ``admit'' the function and
experiment with theorems about it before undoing (see [ubt]) and
then paying the price of its admission. Note however that you might
still have to supply a measure. The set of formals used in some
valid measure, known as the ``measured subset'' of the set of
formals, is used by ACL2's induction heuristics and therefore needs
to be suitably specified. You may wish to specify the special
measure of (:? v1 ... vk), where (v1 ... vk) enumerates the
measured subset.
2. You intend eventually to verify the [guard]s for a definition but
do not want to take the time now to pursue that. By embedding the
[verify-guards] event in a skip-proofs you can get the system to
behave as though the [guard]s were verified.
3. You are repeatedly recertifying a book while making many
experimental changes. A certain [defthm] in the book takes a very
long time to prove and you believe the proof is not affected by the
changes you are making. By embedding the [defthm] event in a
skip-proofs you allow the theorem to be assumed without proof
during the experimental recertifications.
4. You are constructing a proof top-down and wish to defer the proof
of a [defthm] until you are convinced of its utility. You can embed
the defthm in a skip-proofs. Of course, you may find later (when
you attempt prove the theorem) that the proposed defthm is not a
theorem.
Unsoundness or Lisp errors may result if the presumptions underlying
a use of skip-proofs are incorrect. Therefore, skip-proofs must be
considered a dangerous (though useful) tool in system development.
Roughly speaking, a [defthm] embedded in a skip-proofs is essentially
a [defaxiom], except that it is not noted as an axiom for the
purposes of functional instantiation (see [lemma-instance]). But a
skipped [defun] is much more subtle since not only is the
definitional equation being assumed but so are formulas relating to
termination and type. The situation is also difficult to
characterize if the skip-proofs [events] are within the scope of an
[encapsulate] in which constrained functions are being introduced.
In such contexts no clear logical story is maintained; in
particular, constraints aren't properly tracked for definitions. A
proof script involving skip-proofs should be regarded as
work-in-progress, not as a completed proof with some unproved
assumptions. A skip-proofs event represents a promise by the author
to admit the given event without further axioms. In other words,
skip-proofs should only be used when the belief is that the proof
obligations are indeed theorems in the existing ACL2 logical
[world].
ACL2 allows the certification of [books] containing skip-proofs
[events] by providing the keyword argument :skip-proofs-okp t to
the [certify-book] command. This is contrary to the spirit of
certified [books], since one is supposedly assured by a valid
[certificate] that a book has been ``blessed.'' But certification,
too, takes the view of skip-proofs as ``work-in-progress'' and so
allows the author of the book to promise to finish. When such
[books] are certified, a warning to the author is printed,
reminding him or her of the incurred obligation. When [books]
containing skip-proofs are included into a session, a warning to
the user is printed, reminding the user that the book is in fact
incomplete and possibly inconsistent. This warning is in fact an
error if :skip-proofs-okp is nil in the [include-book] form; see
[include-book].
We conclude with a technical note. Skip-proofs works by binding the
[ld] special [ld-skip-proofsp] to t unless it is already bound to a
non-nil value; see [ld-skip-proofsp].")
(SLEEP
(PROGRAMMING)
"Sleep for some number of seconds
The call (sleep n) returns nil. However, it takes approximately n
seconds of real time for this call to return.
The [guard] for sleep requires its argument to be a non-negative
rational number.
Sleep is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <sleep>
(defun sleep (n)
(declare (xargs :guard (and (rationalp n) (<= 0 n))))
(declare (ignore n))
nil)")
(SLOW-ALIST-WARNING
(FAST-ALISTS)
"Warnings issued when [fast-alists] are used inefficiently
Obtaining hash-table performance from [hons-get] requires one to
follow a certain discipline. If this discipline is violated, you
may see a \"slow alist warning\". This warning means that the alist
you are extending or accessing does not have a valid hash table
associated with it, and hence any accesses must be carried out with
[hons-assoc-equal] instead of gethash.
You can control whether or not you get a warning and, if so, whether
or not a break (an error from which you can continue) ensues. For
instance:
(set-slow-alist-action :warning) ; warn on slow access (default)
(set-slow-alist-action :break) ; warn and also call break$
(set-slow-alist-action nil) ; do not warn or break
The above forms expand to [table] [events], so they can be embedded
in [encapsulate]s and [books], wrapped in [local], and so on.")
(SLOW-ARRAY-WARNING
(ARRAYS)
"A warning or error issued when [arrays] are used inefficiently
If you use ACL2 [arrays] you may sometimes see a slow array warning.
We explain below what that warning means and some likely
``mistakes'' it may signify.
First, we note that you can control whether or not you get a warning
and, if so, whether or not a break (error from which you can
continue; see [break$]) ensues:
(assign slow-array-action :warning) ; warn on slow array access (default)
(assign slow-array-action :break) ; warn as above, and then call break$
(assign slow-array-action nil) ; do not warn or break on slow array access
If you are using ACL2 arrays, then you probably care about
performance, in which case it is probably best to avoid the nil
setting. Below we assume the default behavior: a warning, but no
break.
The discussion in the documentation for [arrays] defines what we mean
by the semantic value of a name. As noted there, behind the scenes
ACL2 maintains the invariant that with some names there is
associated a pair consisting of an ACL2 array alist, called the
semantic value of the name, and an equivalent raw lisp array.
Access to ACL2 array elements, as in (aref1 name alist i), is
executed in constant time when the array alist is the semantic
value of the name, because we can just use the corresponding raw
lisp array to obtain the answer. [Aset1] and [compress1] modify the
raw lisp array appropriately to maintain the invariant.
If [aref1] is called on a name and alist, and the alist is not the
then-current semantic value of the name, the correct result is
computed but it requires linear time because the alist must be
searched. When this happens, [aref1] prints a slow array warning
message to the comment window. [Aset1] behaves similarly because
the array it returns will cause the slow array warning every time
it is used.
From the purely logical perspective there is nothing ``wrong'' about
such use of [arrays] and it may be spurious to print a warning
message. But because [arrays] are generally used to achieve
efficiency, the slow array warning often means the user's
intentions are not being realized. Sometimes merely performance
expectations are not met; but the message may mean that the
functional behavior of the program is different than intended.
Here are some ``mistakes'' that might cause this behavior. In the
following we suppose the message was printed by [aset1] about an
array named name. Suppose the alist supplied [aset1] is alist.
(1) [Compress1] was never called on name and alist. That is, perhaps
you created an alist that is an [array1p] and then proceeded to
access it with [aref1] but never gave ACL2 the chance to create a
raw lisp array for it. After creating an alist that is intended for
use as an array, you must do (compress1 name alist) and pass the
resulting alist' as the array.
(2) Name is misspelled. Perhaps the array was compressed under the
name 'delta-1 but accessed under 'delta1?
(3) An [aset1] was done to modify alist, producing a new array,
alist', but you subsequently used alist as an array. Inspect all
(aset1 name ...) occurrences and make sure that the alist modified
is never used subsequently (either in that function or any other).
It is good practice to adopt the following syntactic style. Suppose
the alist you are manipulating is the value of the local variable
alist. Suppose at some point in a function definition you wish to
modify alist with [aset1]. Then write
(let ((alist (aset1 name alist i val))) ...)
and make sure that the subsequent function body is entirely within
the scope of the [let]. Any uses of alist subsequently will refer
to the new alist and it is impossible to refer to the old alist.
Note that if you write
(foo (let ((alist (aset1 name alist i val))) ...) ; arg 1
(bar alist)) ; arg 2
you have broken the rules, because in arg 1 you have modified alist
but in arg 2 you refer to the old value. An appropriate rewriting
is to lift the [let] out:
(let ((alist (aset1 name alist alist i val)))
(foo ... ; arg 1
(bar alist))) ; arg 2
Of course, this may not mean the same thing.
(4) A function which takes alist as an argument and modifies it with
[aset1] fails to return the modified version. This is really the
same as (3) above, but focuses on function interfaces. If a
function takes an array alist as an argument and the function uses
[aset1] (or a subfunction uses [aset1], etc.), then the function
probably ``ought'' to return the result produced by [aset1]. The
reasoning is as follows. If the array is passed into the function,
then the caller is holding the array. After the function modifies
it, the caller's version of the array is obsolete. If the caller is
going to make further use of the array, it must obtain the latest
version, i.e., that produced by the function.")
(SOLUTION-TO-SIMPLE-EXAMPLE
(ANNOTATED-ACL2-SCRIPTS)
"Solution to a simple example
To see a statement of the problem solved below, see
[annotated-ACL2-scripts] (in particular the end of that topic).
Here is a sequence of ACL2 [events] that illustrates the use of ACL2
to make definitions and prove theorems. We will introduce the
notion of the fringe of a tree, as well as the notion of a leaf of
a tree, and then prove that the members of the fringe are exactly
the leaves.
We begin by defining the fringe of a tree, where we identify trees
simply as [cons] structures, with [atom]s at the leaves. The
definition is recursive, breaking into two cases. If x is a [cons],
then the fringe of x is obtained by appending together the fringes
of the [car] and [cdr] (left and right child) of x. Otherwise, x is
an [atom] and its fringe is the one-element list containing only x.
(defun fringe (x)
(if (consp x)
(append (fringe (car x))
(fringe (cdr x)))
(list x)))
Now that fringe has been defined, let us proceed by defining the
notion of an atom appearing as a ``leaf'', with the goal of proving
that the leaves of a tree are exactly the members of its fringe.
(defun leaf-p (atm x)
(if (consp x)
(or (leaf-p atm (car x))
(leaf-p atm (cdr x)))
(equal atm x)))
The main theorem is now as follows. Note that the rewrite rule below
uses the equivalence relation [iff] (see [equivalence]) rather than
[equal], since [member] returns the tail of the given list that
begins with the indicated member, rather than returning a Boolean.
(Use :pe member to see the definition of [member].)
(defthm leaf-p-iff-member-fringe
(iff (leaf-p atm x)
(member-equal atm (fringe x))))")
(SPEC-MV-LET
(PARALLEL-PROGRAMMING ACL2-BUILT-INS)
"Modification of [mv-let] supporting speculative and parallel
execution
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism],
and see [parallel-programming], which has a disclaimer.
Example Form:
(defun pfib-with-step-count (x)
(declare (xargs :mode :program))
(if (or (zp x) (< x 33))
(fib-with-step-count x)
(spec-mv-let
(a cnt1)
(pfib-with-step-count (- x 1))
(mv-let (b cnt2)
(pfib-with-step-count (- x 2))
(if t
(mv (+ a b)
(+ 1 cnt1 cnt2))
(mv \"speculative result is always needed\"
-1))))))
General Form:
(spec-mv-let
(v1 ... vn) ; bind distinct variables
<spec> ; evaluate speculatively; return n values
(mv-let ; or, use mv?-let if k=1 below
(w1 ... wk) ; bind distinct variables
<eager> ; evaluate eagerly
(if <test> ; use results from <spec> if true
<typical-case> ; may mention v1 ... vn
<abort-case>))) ; does not mention v1 ... vn
Our design of spec-mv-let is guided by its use in ACL2 source code to
parallelize part of ACL2's proof process, in the experimental
parallel extension of ACL2. The user can think of spec-mv-let as a
speculative version of [mv-let]. (In ordinary ACL2, the semantics
agree with this description but without speculative or parallel
execution.)
Evaluation of the above general form proceeds as suggested by the
comments. First, <spec> is executed speculatively. Control then
passes immediately to the [mv-let] call, without waiting for the
result of evaluating <spec>. The variables (w1 ... wk) are bound to
the result of evaluating <eager>, and then <test> is evaluated. If
the value of <test> is true, then the values of (v1 ... vn) are
needed, and <typical-case> blocks until they are available. If the
value of <test> is false, then the values of (v1 ... vn) are not
needed, and the evaluation of <spec> may be aborted.
The calls to mv-let and to if displayed above in the General Form are
an essential part of the design of spec-mv-let, and are thus
required.
The following definition of fib-with-step-count completes the example
above:
(defun fib-with-step-count (x)
(declare (xargs :mode :program))
(cond ((<= x 0)
(mv 0 1))
((= x 1) (mv 1 1))
(t (mv-let (a cnt1)
(fib-with-step-count (- x 1))
(mv-let (b cnt2)
(fib-with-step-count (- x 2))
(mv (+ a b)
(+ 1 cnt1 cnt2)))))))")
(SPECIAL-CASES-FOR-REWRITE-RULES
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Convenient short forms for rewrite rule formulas
In principle, every rewrite rule is made from a formula of this
shape:
(IMPLIES (AND hyp1 ... hypk)
(eqv lhs rhs))
where eqv is either EQUAL or IFF and the result of expanding any
abbreviations in lhs is the application of some function symbol
other than IF.
* In the special case where there is only one hyp term, i.e., k=1,
the (AND hyp1) can be written hyp1.
* In the special case where there are no hyp terms, k=0, the (AND)
term is logically just T and the whole IMPLIES can be dropped; such
a formula may be written as an unconditional EQUAL or IFF term.
* If you build a rewrite rule from a formula that concludes with (NOT
x), it is treated as though it were (EQUAL x NIL), which is
logically equivalent to what you typed.
* If you build a rewrite rule from a formula that concludes with an
AND, ACL2 will build a rewrite rule for each conjunct of the AND.
This is because
(IMPLIES hyp (AND concl1 concl2))
is propositionally equivalent to
(AND (IMPLIES hyp concl1)
(IMPLIES hyp concl2)).
However, if you use an OR-expression as a hypothesis, ACL2 does not
do the dual transformation. Thus, (IMPLIES (OR hyp1 hyp2) concl)
generates one rewrite rule.
* Finally, if you build a rewrite rule from a formula that does not
conclude with an EQUAL, an IFF, a NOT, or an AND, but with some
other term, say, lhs, then ACL2 acts like you typed (IFF lhs T),
which is logically equivalent to what you typed.
Thus, regardless of what you type, every rule has k hypotheses. For
unconditional rules, k is 0 and the hypotheses are vacuously true.
Whether or not you write an EQUAL or an IFF in the conclusion,
every rule is either an equality or a propositional equivalence,
every rule has a left-hand side, and every rule has a right-hand
side.
Use your browser's Back Button now to return to
[introduction-to-rewrite-rules-part-1].")
(SPECIFIC-KINDS-OF-FORMULAS-AS-REWRITE-RULES
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Advice about how to handle commonly occurring formulas as rewrite
rules
Below we give you some guidelines for handling specific, commonly
occurring situations.
* Associativity: If a function f is associative, prove
(equal (f (f x y) z) (f x (f y z)))
ACL2 will use this to flatten f-nests ``to the right.''
* Commutativity: If a function f is commutative, prove both
(equal (f x y) (f y x))
and
(equal (f x (f y z)) (f y (f x z)))
ACL2's heuristics will use these rules to order the arguments
alphabetically, so that (f B (f D (f A C))) becomes (f A (f B (f C
D))).
* Distributivity: If you have a pair of functions f and g so that (f
x (g y z)) is (g (f x y) (f x z)) or some other form of
distributivity is provable, arrange your rules to move the lighter
function symbol up and the heavier one toward the variable symbols.
For example, our arithmetic libraries drive multiplication through
addition, producing sums of products rather than products of sums.
* Identity and Other Laws: Prove the obvious identity and zero laws
(or at least anticipate that you might need them down the road) so
as to eliminate operators.
* Get Rid of Tail Recursive Functions: A corollary to the above
advice concerns tail recursive functions that use auxiliary
variables. New users often define concepts using tail recursions,
accumulating partial results in auxiliary variables, because
creating such functions is similar to programming with while loops.
Expert users will use tail recursion when necessary for execution
efficiency. But tail recursive functions are messy to reason about:
their auxiliary variables have to be properly initialized to make
the functions compute the expected results, but to state
inductively provable properties of tail recursive functions you
must identify the invariants on those auxiliary variables. This
problem tends not to happen with primitive recursive functions. A
primitive recursive function is one that recurs down one variable
and holds all the other variables constant in recursion. Most
tail-recursive functions can be written elegantly as primitive
recursive functions, though one might have to ignore the
programmer's desire to make things efficient and define auxiliary
functions to appropriately transform the value returned by the
recursive call. The classic example is reverse defined in terms of
the auxiliary function append versus reverse defined tail
recursively with an accumulator. By introducing append you
introduce a concept about which you can state lemmas and decompose
the proofs of properties of reverse. So if your problem involves
tail recursive functions with auxiliary variables, define the
primitive recursive version, prove that the tail recursive function
is equivalent to the primitive recursive one, and arrange the
rewrite rule to eliminate the tail recursive function.
* Get Rid of Mutually Recursive Functions: Similarly, if you have
used mutual-recursion to introduce a clique of mutually recursive
functions, f1, f2, ..., you will find that to reason about any one
function in the nest you have to reason about all of them. Any
mutually recursive function can be defined in a singly recursive
way. So do that and then prove a rewrite rule that gets rid of all
the mutually recursive functions by proving
(and (equal (f1 ...) (g1 ...))
(equal (f2 ...) (g2 ...))
...)
where the gi are singly recursive. You may need to appeal to a trick
to define the gi: define a singly recursive function that takes a
flag argument and mimics whichever mutually recursive function the
flag specifies. See [mutual-recursion] [{ICON}] and see
[mutual-recursion-proof-example] [{ICON}].
If you got to this documentation page from the tutorial discussion of
rewrite rules, use your browser's Back Button now to return to
[introduction-to-rewrite-rules-part-2].")
(SPECIOUS-SIMPLIFICATION
(MISCELLANEOUS)
"Nonproductive proof steps
Occasionally the ACL2 theorem prover reports that the current goal
simplifies to itself or to a set including itself. Such
simplifications are said to be ``specious'' and are ignored in the
sense that the theorem prover acts as though no simplification were
possible and tries the next available proof technique. Specious
simplifications are almost always caused by forcing.
The simplification of a formula proceeds primarily by the local
application of :[rewrite], :[type-prescription], and other rules to
its various subterms. If no rewrite rules apply, the formula cannot
be simplified and is passed to the next ACL2 proof technique, which
is generally the elimination of destructors. The experienced ACL2
user pays special attention to such ``maximally simplified''
formulas; the presence of unexpected terms in them indicates the
need for additional rules or the presence of some conflict that
prevents existing rules from working harmoniously together.
However, consider the following interesting possibility: local
rewrite rules apply but, when applied, reproduce the goal as one of
its own subgoals. How can rewrite rules apply and reproduce the
goal? Of course, one way is for one rule application to undo the
effect of another, as when commutativity is applied twice in
succession to the same term. Another kind of example is when two
rules conflict and undermine each other. For example, under
suitable hypotheses, (length x) might be rewritten to (+ 1 (length
(cdr x))) by the :[definition] of [length] and then a :[rewrite]
rule might be used to ``fold'' that back to (length x). Generally
speaking the presence of such ``looping'' rewrite rules causes
ACL2's simplifier either to stop gracefully because of heuristics
such as that described in the documentation for [loop-stopper] or
to cause a stack overflow because of indefinite recursion.
A more insidious kind of loop can be imagined: two rewrites in
different parts of the formula undo each other's effects ``at a
distance,'' that is, without ever being applied to one another's
output. For example, perhaps the first hypothesis of the formula is
simplified to the second, but then the second is simplified to the
first, so that the end result is a formula propositionally
equivalent to the original one but with the two hypotheses
commuted. This is thought to be impossible unless forcing or
case-splitting occurs, but if those features are exploited (see
[force] and see [case-split]) it can be made to happen relatively
easily.
Here is a simple example. Declare foo to be a function of one
argument returning one result:
(defstub p1 (x) t)
Prove the following silly rule:
(defthm bad
(implies (case-split (p1 x))
(p1 x)))
Now suppose we try the following.
(thm (p1 x))
The [rewrite] rule bad will rewrite (p1 x) to t, but it will be
unable to prove the hypothesis (case-split (p1 x)). As a result,
the prover will spawn a new goal, to prove (p1 x). However, since
this new goal is the same as the original goal, ACL2 will recognize
the simplification as specious and consider the attempted
simplification to have failed.
In other words, despite the rewriting, no progress was made! In more
common cases, the original goal may simplify to a set of subgoals,
one of which includes the original goal.
If ACL2 were to adopt the new set of subgoals, it would loop
indefinitely. Therefore, it checks whether the input goal is a
member of the output subgoals. If so, it announces that the
simplification is ``specious'' and pretends that no simplification
occurred.
``Maximally simplified'' formulas that produce specious
simplifications are maximally simplified in a very technical sense:
were ACL2 to apply every applicable rule to them, no progress would
be made. Since ACL2 can only apply every applicable rule, it cannot
make further progress with the formula. But the informed user can
perhaps identify some rule that should not be applied and make it
inapplicable by disabling it, allowing the simplifier to apply all
the others and thus make progress.
When specious simplifications are a problem it might be helpful to
[disable] all forcing (including [case-split]s) and resubmit the
formula to observe whether forcing is involved in the loop or not.
See [force]. The commands
ACL2 !>:disable-forcing
and
ACL2 !>:enable-forcing
[disable] and [enable] the pragmatic effects of both force and
case-split. If the loop is broken when forcing is [disable]d, then
it is very likely some [force]d hypothesis of some rule is
``undoing'' a prior simplification. The most common cause of this
is when we [force] a hypothesis that is actually false but whose
falsity is somehow temporarily hidden (more below). To find the
offending rule, compare the specious simplification with its
non-specious counterpart and look for rules that were speciously
applied that are not applied in the non-specious case. Most likely
you will find at least one such rule and it will have a [force]d
hypothesis. By disabling that rule, at least for the subgoal in
question, you may allow the simplifier to make progress on the
subgoal.")
(SPLIT-TYPES (POINTERS)
"See [xargs] for keyword :split-types.")
(SPLITTER
(DEBUGGING)
"Reporting of rules whose application may have caused case splits
The application of a rule to a term may cause a goal to simplify to
more than one subgoal. A rule with such an application is called a
``splitter''. Here, we explain the output produced for splitters
when proof output is enabled (see [set-inhibit-output-lst]) and
such reporting is turned on (as it is by default) --- that is, when
the value of ([splitter-output]) is true.
See [set-splitter-output] for how to turn off, or on, the reporting
of splitters. Also see [set-case-split-limitations] for information
on how to control case splits. Note that since splitters are rule
applications, splitter output is not generated for case splits that
are caused by other than rules, such as the mere presence of calls
of the function symbol, [if], in the goal.
We begin by describing three types of splitters.
if-intro: The rule application may have introduced a call of IF, in
the sense discussed at the end below.
case-split: For the application of a rule with hypothesis of the form
(case-split <hyp>), <hyp> did not simplify to true or false.
immed-forced: For the application of a rule with hypothesis of the
form (force <hyp>), <hyp> did not simplify to true or false,
where immediate-force-modep is enabled (see
[immediate-force-modep]).
These three annotations --- if-intro, case-split, and immed-forced
--- may be used in proof output and summaries for describing rule
applications, as discussed below. A fourth annotation, forced, may
also be used in proof output to indicate the application of a rule
with hypothesis of the form (force <hyp>) when <hyp> did not
simplify to true or false, where immediate-force-modep is disabled
(see [immediate-force-modep]). We don't consider such uses of
[force] to be splitters, because they do not cause case splits
(though they do produce goals to prove after lower-case ``q.e.d.''
is printed); see [force].
There are three kinds of output affected by splitters, illustrated in
turn below using examples.
(a) During the proof, [gag-mode] and raw proof format (see
[set-raw-proof-format]) off
(b) During the proof, [gag-mode] or raw proof format on
(c) Summary
Of course, (a) and (b) are skipped if proof output is inhibited, and
(c) is skipped if summary output is inhibited; see
[set-inhibit-output-lst].
(a) During the proof, [gag-mode] and raw proof format (see
[set-raw-proof-format]) off
With [gag-mode] off (or when using :[pso], :[psof], or :[psog]) one
normally gets an English commentary. The following output indicates
that at least one application of each rule F and G is of type
if-intro, at least one application of rules G and R1 are of type
case-split, and at least one application of rule R3 is of type
immed-forced. If [immediate-force-modep] is off then
``immed-forced'' would be replaced by ``forced''.
This simplifies, using the :definitions F (if-intro), G (case-split and
if-intro) and H and the :rewrite rules R1, R2 (case-split), and
R3 (immed-forced), to the following two conjectures.
Note that any such printing of ``forced'' is done even if
(splitter-output) is false.
(b) During the proof, [gag-mode] or raw proof format on
With [gag-mode] or raw proof format (see [set-raw-proof-format]) on,
the proof output is abbreviated. However, in these cases ``Splitter
Notes'' are printed so that one can still get important information
to help control large case splits (by disabling splitter rules as
appropriate). These are printed at the point when a goal splits
into subgoals. Here, for example, is the Splitter Note that
corresponds to the output shown in (a) above. It shows the goal
whose simplification has produced a split into more than one
subgoal, and it shows how many subgoals have been created.
Splitter note (see :DOC splitter) for Subgoal *1/2.2.1' (2 subgoals).
case-split: ((:DEFINITION G) (:REWRITE R2))
immed-forced: ((:REWRITE R3))
if-intro: ((:DEFINITION G) (:DEFINITION F))
No such splitter notes are printed for the use of [force] (when
[immediate-force-modep] is off).
(c) Summary
Here is a possible summary corresponding to our running example. In
the summary, ``Splitter rules'' is omitted if there are no splitter
rules, and a splitter type is only mentioned if there is at least
one corresponding splitter rule.
Summary
Form: ( THM ...)
Rules: ((:DEFINITION F)
(:DEFINITION G)
(:DEFINITION H)
(:REWRITE R1)
(:REWRITE R2)
(:REWRITE R3))
Splitter rules (see :DOC splitter):
case-split: ((:DEFINITION G) (:REWRITE R2))
immed-forced: ((:REWRITE R3))
if-intro: ((:DEFINITION G) (:DEFINITION F))
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.00)
Prover steps counted: 145
No indication for ``forced'' is given for ``Splitter rules''. (As
discussed earlier above, the [force]d hypotheses are not considered
relevant for determining splitter rule applications unless
[immediate-force-modep] is on.)
We conclude by giving the criteria for a [rewrite] or [definition]
rule application to be a splitter of type if-intro.
* Reporting of splitter rules is on, i.e., the value of
([splitter-output]) is true.
* At least two subgoals are created, even before considering subgoals
generated by hypotheses that are calls of [case-split] or
[force].
* The term to which the rule is applied is at the top level, rather
than being encountered when trying to establish the hypothesis
of a rule.
* The rule is a [rewrite] rule, a [definition] rule, or a [meta] rule.
* There is a call of the function symbol IF in the right-hand side of
the [rewrite] rule; or, in the case of a [definition] rule, in
the body of the definition; or, in the case of a [meta] rule,
in the result of applying the metafunction.
* There is a call of the function symbol IF in the result of rewriting:
the right-hand side (for a [rewrite] rule), the definition body
(for a [definition] rule), or the metafunction application (for
a [meta] rule).
Any rule application meeting the above criteria will be considered a
splitter of type if-intro, even if the call does not actually cause
a case split. For example, if you are proving (implies (hyp x)
(conc x)) and rule R rewrites (hyp x) to (if (h1 x) (h2 x) nil),
which is really the term (and (h1 x) (h2 x)), then R may be
labelled as a splitter rule. If you want to find the causes of
case-splitting, the list of if-intro splitters can help you narrow
your search, but may include irrelevant rules as well.
Finally, note that you may see splits not attributed to splitters. We
believe that this will be uncommon during simplification, though it
can occur for example when a call of IF is in the body of a [let]
expression, i.e., in a call of a [lambda] expression. But splits
caused by other processes, notably destructor elimination (see
[elim]), will typically not be attributed to splitters.
Subtopics
[Set-splitter-output]
Turn on or off reporting of rules that may have caused case splits
[Splitter-output]
Status for reporting of [splitter] rules")
(SPLITTER-OUTPUT
(SPLITTER)
"Status for reporting of [splitter] rules
See [splitter] for a discussion of splitter rules. See
[set-splitter-output] for how to turn off, or on, the reporting of
splitter rules. When splitter-output is off, because either prove
output is inhibited (see [set-inhibit-output-lst]) or
([set-splitter-output] nil) has been invoked, then the value of
(splitter-output) is nil. Otherwise, such reporting is on and the
value is non-nil.")
(STABLE-UNDER-SIMPLIFICATIONP (POINTERS)
"See [computed-hints].")
(STANDARD-CHAR-LISTP
(CHARACTERS LISTS ACL2-BUILT-INS)
"Recognizer for a true list of standard characters
(standard-char-listp x) is true if and only if x is a null-terminated
list all of whose members are standard [characters]. See
[standard-char-p].
Standard-char-listp has a [guard] of t.
Function: <standard-char-listp>
(defun standard-char-listp (l)
(declare (xargs :guard t))
(cond ((consp l)
(and (characterp (car l))
(standard-char-p (car l))
(standard-char-listp (cdr l))))
(t (equal l nil))))")
(STANDARD-CHAR-P
(CHARACTERS ACL2-BUILT-INS)
"Recognizer for standard characters
(Standard-char-p x) is true if and only if x is a ``standard''
character, i.e., a member of the list *standard-chars*. This list
includes #\\Newline and #\\Space [characters], as well as the usual
punctuation and alphanumeric [characters].
Standard-char-p has a [guard] requiring its argument to be a
character.
Standard-char-p is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <standard-char-p>
(defun standard-char-p (x)
(declare (xargs :guard (characterp x)))
(if (member x *standard-chars*) t nil))")
(STANDARD-CO
(IO ACL2-BUILT-INS)
"The character output channel to which [ld] prints
Standard-co is an [ld] special (see [ld]). The accessor is
(standard-co state) and the updater is (set-standard-co val state).
Standard-co must be an open character output channel. It is to this
channel that [ld] prints the [prompt], the form to be evaluated,
and the results. The event [command]s such as [defun], [defthm],
etc., which print extensive commentary do not print to standard-co
but rather to a different channel, [proofs-co], so that you may
redirect this commentary while still interacting via standard-co.
See [proofs-co].
``Standard-co'' stands for ``standard character output.'' The initial
value of standard-co is the same as the value of [*standard-co*]
(see [*standard-co*]).")
(STANDARD-OI
(IO ACL2-BUILT-INS)
"The standard object input ``channel''
Standard-oi is an [ld] special (see [ld]). The accessor is
(standard-oi state) and the updater is (set-standard-oi val state).
Standard-oi must be an open object input channel, a true list of
objects, or a list of objects whose last [cdr] is an open object
input channel. It is from this source that [ld] takes the input
forms to process. When [ld] is called, if the value specified for
standard-oi is a string or a list of objects whose last [cdr] is a
string, then [ld] treats the string as a file name and opens an
object input channel from that file, where the connected book
directory (see [cbd]) is used to resolve relative pathnames. The
channel opened by [ld] is closed by [ld] upon termination.
``Standard-oi'' stands for ``standard object input.'' The
read-eval-print loop in [ld] reads the objects in standard-oi and
treats them as forms to be evaluated. The initial value of
standard-oi is the same as the value of [*standard-oi*] (see
[*standard-oi*]).")
(STANDARD-PART
(REAL)
"ACL2(r) function mapping limited numbers to standard numbers
(Standard-part x) is, for a given [i-limited] number x, the unique
real number infinitesimally close (see [i-close]) to x. This
function is only defined in ACL2(r) (see [real]).")
(STANDARD-STRING-ALISTP
(ALISTS ACL2-BUILT-INS)
"Recognizer for association lists with standard strings as keys
(Standard-string-alistp x) is true if and only if x is a list of
pairs of the form (cons key val) where key is a string all of whose
characters are standard (see [standard-char-p]).
Standard-string-alistp has a [guard] of t.
Function: <standard-string-alistp>
(defun
standard-string-alistp (x)
(declare (xargs :guard t))
(cond ((atom x) (eq x nil))
(t (and (consp (car x))
(stringp (car (car x)))
(standard-char-listp (coerce (car (car x)) 'list))
(standard-string-alistp (cdr x))))))")
(STANDARDP
(REAL)
"ACL2(r) recognizer for standard objects
(Standardp x) is true if and only if x is a ``standard'' object. This
notion of ``standard'' comes from non-standard analysis and is
discussed in Ruben Gamboa's dissertation. In brief, all the
familiar objects are standard: e.g., the familiar real numbers are
standard, but non-zero infinitesimals are not standard, and the
familiar integers are standard, but not those that exceed every
integer that you can express in the usual way (1, 2, 3, and so on).
Similarly, the familiar lists are standard, but not so a list that
contains a large number of integers, where ``large'' means more
than the standard integers. The set of standard numbers is closed
under the usual arithmetic operations, hence the sum of a standard
number and a non-zero infinitesimal is not standard, though it is
what is called ``limited'' (see [i-limited]).
This predicate is only defined in ACL2(r) (see [real]).")
(START-PROOF-TREE
(PROOF-TREE)
"Start displaying proof trees during proofs
Also see [proof-tree] and see [stop-proof-tree]. Note that
:start-proof-tree works by removing '[proof-tree] from the
inhibit-output-lst; see [set-inhibit-output-lst].
Explanations of proof tree displays may be found elsewhere: see
[proof-tree]. In a nutshell: :start-proof-tree causes proof tree
display to be turned on, once it has been turned off by
:[stop-proof-tree].
Do not attempt to invoke start-proof-tree during an interrupt in the
middle of a proof.")
(STARTUP
(ACL2-TUTORIAL)
"How to start using ACL2; the ACL2 [command] loop
When you start up ACL2, you'll probably find yourself inside the ACL2
[command] loop, as indicated by the following [prompt].
ACL2 !>
If not, you should type (LP). See [lp], which has a lot more
information about the ACL2 [command] loop.
You should now be in ACL2. The current ``[default-defun-mode]'' is
:[logic]; the other mode is :[program], which would cause the
letter p to be printed in the [prompt]. :[Logic] means that any
function we define is not only executable but also is axiomatically
defined in the ACL2 logic. See [defun-mode] and see
[default-defun-mode]. For example we can define a function my-cons
as follows. (You may find it useful to start up ACL2 and submit
this and other [command]s below to the ACL2 [command] loop, as we
won't include output below.)
ACL2 !>(defun my-cons (x y) (cons x y))
An easy theorem may then be proved: the [car] of (my-cons a b) is A.
ACL2 !>(defthm car-my-cons (equal (car (my-cons a b)) a))
You can place raw Lisp forms to evaluate at start-up into file
acl2-init.lsp in your home directory, except on Windows systems.
For example, if you put the following into acl2-init.lsp, then ACL2
will print \"HI\" when it starts up.
(print \"HI\")
But be careful; all bets are off when you submit forms to raw Lisp,
so this capability should only be used when you are hacking or when
you are setting some Lisp parameters (e.g., (setq si::*notify-gbc*
nil) to turn off garbage collection notices in GCL).
Notice that unlike Nqthm, the theorem [command] is [defthm] rather
than prove-lemma. See [defthm], which explains (among other things)
that the default is to turn theorems into [rewrite] rules.
Various keyword commands are available to query the ACL2 ``[world]'',
or database. For example, we may view the definition of my-cons by
invoking a command to print [events], as follows.
ACL2 !>:pe my-cons
Also see [pe]. We may also view all the lemmas that [rewrite] [term]s
whose top function symbol is [car] by using the following command,
whose output will refer to the lemma car-my-cons proved above.
ACL2 !>:pl car
Also see [pl]. Finally, we may print all the [command]s back through
the initial [world] as follows.
ACL2 !>:pbt 0
See [history] for a list of commands, including these, for viewing
the current ACL2 [world].
Continue with the [documentation] for [annotated-ACL2-scripts] to see
a simple but illustrative example in the use of ACL2 for reasoning
about functions.")
(STATE
(PROGRAMMING)
"The von Neumannesque ACL2 state object
Note: If you are interested in programming with state, see
[programming-with-state] after reading the information below.
The ACL2 state object is used extensively in programming the ACL2
system, and has been used in other ACL2 programs as well. However,
most users, especially those interested in specification and
verification (as opposed to programming per se), need not be aware
of the role of the state object in ACL2, and will not write
functions that use it explicitly. We say more about this point at
the end of this documentation topic.
The ACL2 state object is an example of a single-threaded object or
[stobj]. ACL2 allows the user to define new single-threaded
objects. Generally, ACL2 may need to access the ACL2 state but
should not (cannot) change it except via a certain set of approved
functions such as [defun] and [defthm]. If you need a state-like
object to which you have complete rights, you may want a [stobj].
Key to the idea of our state is the notion of single-threadedness.
For an explanation, see [stobj]. The upshot of it is that state is
a variable symbol with severe restrictions on its use, so that it
can be passed into only certain functions in certain slots, and
must be returned by those functions that ``modify'' it. Henceforth,
we do not discuss single-threaded objects in general (which the
user can introduce with [defstobj] and [defabsstobj]) but one in
particular, namely ACL2's state object.
The global table is perhaps the most visible portion of the state
object. Using the interface functions @ and assign, a user may bind
global variables to the results of function evaluations (much as an
Nqthm user exploits the Nqthm utility r-loop). See [@], and see
[assign]. A particularly interesting global is 'current-acl2-world,
whose value is the ACL2 logical [world].
ACL2 supports several facilities of a truly von Neumannesque state
machine character, including file [io] and global variables.
Logically speaking, the state is a true list of the 14 components
described below. There is a ``current'' state object at the
top-level of the ACL2 [command] loop. This object is understood to
be the value of what would otherwise be the free variable state
appearing in top-level input. When any [command] returns a state
object as one of its values, that object becomes the new current
state. But ACL2 provides von Neumann style speed for state
operations by maintaining only one physical (as opposed to logical)
state object. Operations on the state are in fact destructive. This
implementation does not violate the applicative semantics because
we enforce certain draconian syntactic rules regarding the use of
state objects. For example, one cannot ``hold on'' to an old state,
access the components of a state arbitrarily, or ``modify'' a state
object without passing it on to subsequent state-sensitive
functions.
Every routine that uses the state facilities (e.g. does [io], or
calls a routine that does [io]), must be passed a ``state object.''
And a routine must return a state object if the routine modifies
the state in any way. Rigid syntactic rules governing the use of
state objects are enforced by the function translate, through which
all ACL2 user input first passes. State objects can only be
``held'' in the formal parameter state, never in any other formal
parameter and never in any structure (excepting a multiple-value
return list field which is always a state object). State objects
can only be accessed with the primitives we specifically permit.
Thus, for example, one cannot ask, in code to be executed, for the
length of state or the [car] of state. In the statement and proof
of theorems, there are no syntactic rules prohibiting arbitrary
treatment of state objects.
Logically speaking, a state object is a true list whose members are
as follows:
Open-input-channels, an alist with keys that are symbols in package
\"ACL2-INPUT-CHANNEL\". The value ([cdr]) of each pair has the
form ((:header type file-name open-time) . elements), where
type is one of :character, :byte, or :object and elements is a
list of things of the corresponding type, i.e. characters,
integers of type (mod 255), or lisp objects in our theory.
File-name is a string. Open-time is an integer. See [io].
Open-output-channels, an alist with keys that are symbols in package
\"ACL2-OUTPUT-CHANNEL\". The value of a pair has the form
((:header type file-name open-time) . current-contents). See
[io].
Global-table, an alist associating symbols (to be used as ``global
variables'') with values. See [@], and see [assign].
T-stack, a list of arbitrary objects accessed and changed by the
functions aref-t-stack and aset-t-stack.
32-bit-integer-stack, a list of arbitrary 32-bit-integers accessed
and changed by the functions aref-32-bit-integer-stack and
aset-32-bit-integer-stack.
Big-clock-entry, an integer, that is used logically to bound the
amount of effort spent to evaluate a quoted form.
Idates, a list of dates and times, used to implement the function
print-current-idate, which prints the date and time.
Acl2-oracle, a list of objects, used for example to implement the
functions that let ACL2 report how much time was used, but
inaccessible to the user. See [read-ACL2-oracle] and also see
[with-prover-time-limit].
File-clock, an integer that is increased on every file opening and
closing, and is used to maintain the consistency of the [io]
primitives.
Readable-files, an alist whose keys have the form (string type time),
where [string] is a file name and time is an integer. The value
associated with such a key is a list of characters, bytes, or
objects, according to type. The time field is used in the
following way: when it comes time to open a file for input, we
will only look for a file of the specified name and type whose
time field is that of file-clock. This permits us to have a
``probe-file'' aspect to open-file: one can ask for a file,
find it does not exist, but come back later and find that it
does now exist.
Written-files, an alist whose keys have the form (string type time1
time2), where [string] is a file name, type is one of
:character, :byte or :object, and time1 and time2 are integers.
Time1 and time2 correspond to the file-clock time at which the
channel for the file was opened and closed. This field is
write-only; the only operation that affects this field is
close-output-channel, which [cons]es a new entry on the front.
Read-files, a list of the form (string type time1 time2), where
[string] is a file name and time1 and time2 were the times at
which the file was opened for reading and closed. This field is
write only.
Writeable-files, an alist whose keys have the form (string type
time). To open a file for output, we require that the name,
type, and time be on this list.
List-all-package-names-lst, a list of true-listps. Roughly speaking,
the [car] of this list is the list of all package names known
to this Common Lisp right now and the [cdr] of this list is the
value of this state variable after you look at its [car]. The
function, list-all-package-names, which takes the state as an
argument, returns the [car] and [cdr]s the list (returning a
new state too). This essentially gives ACL2 access to what is
provided by CLTL's list-all-packages. [Defpkg] uses this
feature to ensure that the about-to-be-created package is new
in this lisp. Thus, for example, in akcl it is impossible to
create the package \"COMPILER\" with [defpkg] because it is on
the list, while in Lucid that package name is not initially on
the list.
User-stobj-alist, an alist which associates user-defined
single-threaded objects (see [stobj]) with their values.
We recommend avoiding the use of the state object when writing ACL2
code intended to be used as a formal model of some system, for
several reasons. First, the state object is complicated and
contains many components that are oriented toward implementation
and are likely to be irrelevant to the model in question. Second,
there is currently not much support for reasoning about ACL2
functions that manipulate the state object, beyond their logical
definitions. Third, the documentation about state is not as
complete as one might wish.
User-defined single-threaded objects offer the speed of state while
giving the user complete access to all the fields. See [stobj].
Again, if you are interested in programming with state see
[programming-with-state].
Subtopics
[Io]
Input/output facilities in ACL2
[Programming-with-state]
Programming using the von Neumannesque ACL2 [state] object
[Random$]
Obtain a random value
[Set-state-ok]
Allow the use of STATE as a formal parameter
[World]
ACL2 property lists and the ACL2 logical database
[Wormhole]
[ld] without [state] --- a short-cut to a parallel universe")
(STATE-GLOBAL-LET*
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Bind [state] global variables
See [programming-with-state] for requisite background on programming
with the ACL2 [state].
Example Forms:
(state-global-let*
((inhibit-output-lst *valid-output-names*))
(thm (equal x x)))
(state-global-let*
((fmt-hard-right-margin 1000 set-fmt-hard-right-margin)
(fmt-soft-right-margin 1000 set-fmt-soft-right-margin))
(mini-proveall))
General Form:
(state-global-let* ((var1 form1) ; or (var1 form1 set-var1)
...
(vark formk) ; or (vark formk set-vark)
)
body)
where: each vari is a variable; each formi is an expression whose
value is a single ordinary object (i.e. not multiple values, and
not [state] or any other [stobj]); set-vari, if supplied, is a
function with [signature] ((set-vari * state) => state); and body
is an expression that evaluates to an [error-triple]. Each formi is
evaluated in order, starting with form1, and with each such binding
the state global variable vari is bound to the value of formi,
sequentially in the style of [let*]. More precisely, then meaning
of this form is to set (in order) the global values of the
indicated [state] global variables vari to the values of formi
using [f-put-global], execute body, restore the vari to their
previous values (but see the discussion of setters below), and
return the triple produced by body (with its state as modified by
the restoration). The restoration is guaranteed even in the face of
aborts. The ``bound'' variables may initially be unbound in state
and restoration means to make them unbound again.
Still referring to the General Form above, let old-vali be the value
of state global variable vari at the time vari is about to be
assigned the value of formi. If set-vari is not supplied, then as
suggested above, the following form is evaluated at the conclusion
of the evaluation of the state-global-let* form, whether or not an
error has occurred: (f-put-global 'vari 'old-vali state). However,
if set-vari is supplied, then instead the form evaluated will be
(set-vari 'old-vali state). This capability is particularly useful
if vari is untouchable (see [push-untouchable]), since the above
call of [f-put-global] is illegal.
Note that the scope of the bindings of a state-global-let* form is
the body of that form. This may seem obvious, but to drive the
point home, let's consider the following example (see
[set-print-base] and see [set-print-radix]).
ACL2 !>(state-global-let* ((print-base 16 set-print-base)
(print-radix t set-print-radix))
(mv nil 10 state))
10
ACL2 !>
Why wasn't the result printed as #xA? The reason is that the result
was printed after evaluation of the entire form had completed. If
you want to see #xA, do the printing in the scope of the bindings,
for example as follows.
ACL2 !>(state-global-let* ((print-base 16 set-print-base)
(print-radix t set-print-radix))
(pprogn (fms \"~x0~%\"
(list (cons #0 10))
*standard-co* state nil)
(mv nil 10 state)))
#xA
10
ACL2 !>")
(STOBJ
(PROGRAMMING)
"Single-threaded objects or ``von Neumann bottlenecks''
In ACL2, a ``single-threaded object'' is a data structure whose use
is so syntactically restricted that only one instance of the object
need ever exist and its fields can be updated by destructive
assignments.
Note: Novices are advised to avoid using single-threaded objects,
perhaps instead using [std::defaggregate] or community book
books/data-structures/structures.lisp. At the least, consider using
([set-verify-guards-eagerness] 0) to avoid [guard] verification.
The documentation in this section is laid out in the form of a tour
that visits the documented topics in a reasonable order. We
recommend that you follow the tour the first time you read about
stobjs. The list of all stobj topics is shown below. The tour
starts immediately afterwards. Also see [defstobj] and, for
so-called abstract stobjs, see [defabsstobj].
As noted, a ``single-threaded object'' is a data structure whose use
is so syntactically restricted that only one instance of the object
need ever exist. Updates to the object must be sequentialized. This
allows us to update its fields with destructive assignments without
wrecking the axiomatic semantics of update-by-copy. For this
reason, single-threaded objects are sometimes called ``von Neumann
bottlenecks.''
From the logical perspective, a single-threaded object is an ordinary
ACL2 object, e.g., composed of integers and conses. Logically
speaking, ordinary ACL2 functions are defined to allow the user to
``access'' and ``update'' its fields. Logically speaking, when
fields in the object, obj, are ``updated'' with new values, a new
object, obj', is constructed.
But suppose that by syntactic means we could ensure that there were
no more references to the ``old'' object, obj. Then we could create
obj' by destructively modifying the memory locations involved in
the representation of obj. The syntactic means is pretty simple but
draconian: the only reference to obj is in the variable named OBJ.
The consequences of this simple rule are far-reaching and require
some getting used to. For example, if OBJ has been declared as a
single-threaded object name, then the following consequences ensue
(but see the discussion of congruent stobjs below for a slight
relaxation).
* OBJ is a top-level global variable that contains the current object,
obj.
* If a function uses the formal parameter OBJ, the only ``actual
expression'' that can be passed into that slot is the variable
OBJ, not merely a term that ``evaluates to an obj''; thus, such
functions can only operate on the current object. So for
example, instead of (FOO (UPDATE-FIELD1 3 ST)) write (LET ((ST
(UPDATE-FIELD1 3 ST))) (FOO ST)).
* The accessors and updaters have a formal parameter named OBJ, so by
the rule just above, those functions can only be applied to the
current object. The recognizer is the one exception to the
rule: it may be applied either the OBJ or to an ordinary
(non-stobj) object.
* The ACL2 primitives, such as CONS, CAR and CDR, may not be applied to
the variable OBJ. Thus, for example, obj may not be consed into
a list (which would create another pointer to it) or accessed
or copied via ``unapproved'' means.
* The updaters return a ``new OBJ object'', i.e., obj'; thus, when an
updater is called, the only variable which can hold its result
is OBJ.
* If a function calls an OBJ updater, it must return an OBJ object
(either as the sole value returned, or in (mv ... OBJ ...); see
[mv]).
* When a top-level expression involving OBJ returns an OBJ object, that
object becomes the new current value of OBJ.
There are other functional languages supporting single-threadedness,
for example Haskell's ``monads'' and Clean's ``uniqueness type
system''. Of course, ACL2 provides a theorem prover that can prove
theorems that involve such constructs.
Note that the syntactic restrictions noted above are enforced only
when single-threaded objects are encountered directly in the
top-level loop or are used in function definitions; the accessor
and update functions for single-threaded objects may be used
without restriction in formulas to be proved. Since function
evaluation is sometimes necessary during proofs, ACL2 must be able
to evaluate these functions on logical constants representing the
object, even when the constant is not ``the current object.'' Thus,
ACL2 supports both the efficient von Neumann semantics and the
clean applicative semantics, and uses the first in contexts where
execution speed is paramount and the second during proofs.
[Defstobj] and [defabsstobj] [events] introduce stobjs. See
[defstobj] for more details about stobjs. In particular, a
relatively advanced notion of ``congruent stobjs'' is discussed
there. The idea is to allow a stobj, st2, of the same ``shape'' as
a given stobj, st1, to be used in place of st1. Other [defstobj]
keywords allow inlining and renaming of stobj accessors and
updaters.
But we are getting ahead of ourselves. To start the stobj tour, see
[stobj-example-1].
Subtopics
[Declare-stobjs]
Declaring a formal parameter name to be a single-threaded object
[Defabsstobj]
Define a new abstract single-threaded object
[Defstobj]
Define a new single-threaded object
[Nested-stobjs]
Using [stobj]s that contain stobjs
[Nth-aliases-table]
A [table] used to associate names for nth/update-nth printing
[Resize-list]
List resizer in support of stobjs
[Stobj-example-1]
An example of the use of single-threaded objects
[Stobj-example-1-defuns]
The defuns created by the counters stobj
[Stobj-example-1-implementation]
The implementation of the counters stobj
[Stobj-example-1-proofs]
Some proofs involving the counters stobj
[Stobj-example-2]
An example of the use of arrays in single-threaded objects
[Stobj-example-3]
Another example of a single-threaded object
[Update-nth-array]
Update a stobj array
[With-local-state]
Locally bind state
[With-local-stobj]
Locally bind a single-threaded object")
(STOBJ-EXAMPLE-1
(STOBJ)
"An example of the use of single-threaded objects
Suppose we want to sweep a tree and (1) count the number of interior
nodes, (2) count the number of tips and (3) keep a record of every
tip we encounter that is an integer. We could use a single-threaded
object as our ``accumulator''. Such an object would have three
fields, one holding the number of nodes seen so far, one holding
the number of tips, and one holding all the integer tips seen.
The following event declares counters to be a single-threaded object.
(defstobj counters
(NodeCnt :type integer :initially 0)
(TipCnt :type integer :initially 0)
(IntTipsSeen :type t :initially nil))
It has three fields, NodeCnt, TipCnt, and IntTipsSeen. (As always in
ACL2, capitalization is irrelevant in simple symbol names, so the
first name could be written nodecnt or NODECNT, etc.) Those are the
name of the accessor functions for the object. The corresponding
update functions are named update-NodeCnt, update-TipCnt and
update-IntTipsSeen.
If you do not like the default function names chosen above, there is
a feature in the [defstobj] event that allows you to specify other
names.
If you want to see the ACL2 definitions of all the functions defined
by this event, look at [stobj-example-1-defuns].
If, after this event, we evaluate the top-level ``global variable''
counters in the ACL2 read-eval-print loop we get:
ACL2 !>counters
<counters>
Note that the value printed is ``<counters>''. Actually, the value of
counters in the logic is (0 0 NIL). But ACL2 always prints
single-threaded objects in this non-informative way because they
are usually so big that to do otherwise would be unpleasant.
Had you tried to evaluate the ``global variable'' counters before
declaring it a single-threaded object, ACL2 would have complained
that it does not support global variables. So a lesson here is that
once you have declared a new single-threaded object your top-level
forms can reference it. In versions of ACL2 prior to Version 2.4
the only variable enjoying this status was STATE. single-threaded
objects are a straightforward generalization of the
long-implemented von Neumann [state] feature of ACL2.
We can access the fields of counters as with:
ACL2 !>(NodeCnt counters)
0
ACL2 !>(IntTipsSeen counters)
NIL
and we can set the fields of counters as with:
ACL2 !>(update-NodeCnt 3 counters)
<counters>
ACL2 !>(NodeCnt counters)
3
Observe that when we evaluate an expression that returns a counter
object, that object becomes the ``current value'' of counters.
Here is a function that ``converts'' the counters object to its
``ordinary'' representation:
(defun show-counters (counters)
(declare (xargs :stobjs (counters)))
(list (NodeCnt counters)
(TipCnt counters)
(IntTipsSeen counters)))
Observe that we must declare, at the top of the defun, that we mean
to use the formal parameter counters as a single-threaded object!
If we did not make this declaration, the body of show-counters
would be processed as though counters were an ordinary object. An
error would be caused because the accessors used above cannot be
applied to anything but the single-threaded object counters. If you
want to know why we insist on this declaration, see
[declare-stobjs].
When show-counters is admitted, the following message is printed:
Since SHOW-COUNTERS is non-recursive, its admission is trivial. We
observe that the type of SHOW-COUNTERS is described by the theorem
(AND (CONSP (SHOW-COUNTERS COUNTERS))
(TRUE-LISTP (SHOW-COUNTERS COUNTERS))).
We used primitive type reasoning.
(SHOW-COUNTERS COUNTERS) => *.
The guard conjecture for SHOW-COUNTERS is trivial to prove.
SHOW-COUNTERS is compliant with Common Lisp.
The line above containing the ``=>'' is called the ``signature'' of
show-counters; it conveys the information that the first argument
is the single-threaded object counters and the only result is an
ordinary object. Here is an example of another signature:
(PROCESSOR * * COUNTERS) => (MV * COUNTERS)
which indicates that the function PROCESSOR (which we haven't shown
you) takes three arguments, the third of which is the COUNTERS
stobj, and returns two results, the second of which is the modified
COUNTERS.
Returning to the admission of show-counters above, the last sentence
printed indicates that the [guard] conjectures for the function
were proved. When some argument of a function is declared to be a
single-threaded object via the xargs :stobj, we automatically add
(conjoin) to the guard the condition that the argument satisfy the
recognizer for that single-threaded object. In the case of
show-counters the guard is (countersp counters).
Here is an example of show-counters being called:
ACL2 !>(show-counters counters)
(3 0 NIL)
This is what we would see had we set the NodeCnt field of the initial
value of counters to 3, as we did earlier in this example.
We next wish to define a function to reset the counters object. We
could define it this way:
(defun reset-counters (counters)
(declare (xargs :stobjs (counters)))
(let ((counters (update-NodeCnt 0 counters)))
(let ((counters (update-TipCnt 0 counters)))
(update-IntTipsSeen nil counters))))
which ``successively'' sets the NodeCnt field to 0, then the TipCnt
field to 0, and then the IntTipsSeen field to nil and returns the
resulting object.
However, the nest of let expressions is tedious and we use this
definition instead. This definition exploits a macro, here named
``seq'' (for ``sequentially'') which evaluates each of the forms
given, binding their results successively to the stobj name given.
(defun reset-counters (counters)
(declare (xargs :stobjs (counters)))
(seq counters
(update-NodeCnt 0 counters)
(update-TipCnt 0 counters)
(update-IntTipsSeen nil counters)))
This definition is syntactically identical to the one above, after
macro expansion. Our definition of seq is shown below and is not
part of native ACL2.
(defmacro seq (stobj &rest rst)
(cond ((endp rst) stobj)
((endp (cdr rst)) (car rst))
(t `(let ((,stobj ,(car rst)))
(seq ,stobj ,@(cdr rst))))))
The signature printed for reset-counters is
(RESET-COUNTERS COUNTERS) => COUNTERS.
Here is an example.
ACL2 !>(show-counters counters)
(3 0 NIL)
ACL2 !>(reset-counters counters)
<counters>
ACL2 !>(show-counters counters)
(0 0 NIL)
Here finally is a function that uses counters as a single-threaded
accumulator to collect the desired information about the tree x.
(defun sweep-tree (x counters)
(declare (xargs :stobjs (counters)))
(cond ((atom x)
(seq counters
(update-TipCnt (+ 1 (TipCnt counters)) counters)
(if (integerp x)
(update-IntTipsSeen (cons x (IntTipsSeen counters))
counters)
counters)))
(t (seq counters
(update-NodeCnt (+ 1 (NodeCnt counters)) counters)
(sweep-tree (car x) counters)
(sweep-tree (cdr x) counters)))))
We can paraphrase this definition as follows. If x is an atom, then
increment the TipCnt field of counters and then, if x is an
integer, add x to the IntTipsSeen field, and return counters. On
the other hand, if x is not an atom, then increment the NodeCnt
field of counters, and then sweep the car of x and then sweep the
cdr of x and return the result.
Here is an example of its execution. We have displayed the input tree
in full dot notation so that the number of interior nodes is just
the number of dots.
ACL2 !>(sweep-tree '((((a . 1) . (2 . b)) . 3)
. (4 . (5 . d)))
counters)
<counters>
ACL2 !>(show-counters counters)
(7 8 (5 4 3 2 1))
ACL2 !>(reset-counters counters)
<counters>
ACL2 !>(show-counters counters)
(0 0 NIL)
The counters object has two integer fields and a field whose type is
unrestricted. single-threaded objects support other types of
fields, such as arrays. We deal with that in the [stobj-example-2].
But we recommend that you first consider the implementation issues
for the counters example (in [stobj-example-1-implementation]) and
then consider the proof issues (in [stobj-example-1-proofs]).
To continue the stobj tour, see [stobj-example-2].")
(STOBJ-EXAMPLE-1-DEFUNS
(STOBJ)
"The defuns created by the counters stobj
Consider the event shown in [stobj-example-1]:
(defstobj counters
(NodeCnt :type integer :initially 0)
(TipCnt :type integer :initially 0)
(IntTipsSeen :type t :initially nil))
Here is a complete list of the defuns added by the event.
The careful reader will note that the counters argument below is not
declared with the :stobjs xarg even though we insist that the
argument be a stobj in calls of these functions. This ``mystery''
is explained below.
(defun NodeCntp (x) ;;; Recognizer for 1st field
(declare (xargs :guard t :verify-guards t))
(integerp x))
(defun TipCntp (x) ;;; Recognizer for 2nd field
(declare (xargs :guard t :verify-guards t))
(integerp x))
(defun IntTipsSeenp (x) ;;; Recognizer for 3rd field
(declare (xargs :guard t :verify-guards t) (ignore x))
t)
(defun countersp (counters) ;;; Recognizer for object
(declare (xargs :guard t :verify-guards t))
(and (true-listp counters)
(= (length counters) 3)
(NodeCntp (nth 0 counters))
(TipCntp (nth 1 counters))
(IntTipsSeenp (nth 2 counters))
t))
(defun create-counters () ;;; Creator for object
(declare (xargs :guard t :verify-guards t))
(list '0 '0 'nil))
(defun NodeCnt (counters) ;;; Accessor for 1st field
(declare (xargs :guard (countersp counters) :verify-guards t))
(nth 0 counters))
(defun update-NodeCnt (v counters) ;;; Updater for 1st field
(declare (xargs :guard
(and (integerp v)
(countersp counters))
:verify-guards t))
(update-nth 0 v counters))
(defun TipCnt (counters) ;;; Accessor for 2nd field
(declare (xargs :guard (countersp counters) :verify-guards t))
(nth 1 counters))
(defun update-TipCnt (v counters) ;;; Updater for 2nd field
(declare (xargs :guard
(and (integerp v)
(countersp counters))
:verify-guards t))
(update-nth 1 v counters))
(defun IntTipsSeen (counters) ;;; Accessor for 3rd field
(declare (xargs :guard (countersp counters) :verify-guards t))
(nth 2 counters))
(defun update-IntTipsSeen (v counters) ;;; Updater for 3rd field
(declare (xargs :guard (countersp counters) :verify-guards t))
(update-nth 2 v counters))
Observe that there is a recognizer for each of the three fields and
then a recognizer for the counters object itself. Then, for each
field, there is an accessor and an updater.
Observe also that the functions are guarded so that they expect a
countersp for their counters argument and an appropriate value for
the new field values.
You can see all of the defuns added by a defstobj event by executing
the event and then using the :pcb! command on the stobj name. E.g.,
ACL2 !>:pcb! counters
will print the defuns above.
We now clear up the ``mystery'' mentioned above. Note, for example in
TipCnt, that the formal counters is used. From the discussion in
[stobj-example-1] it has been made clear that TipCnt can only be
called on the counters object. And yet, in that same discussion it
was said that an argument is so treated only if it it declared
among the :stobjs in the definition of the function. So why doesn't
TipCnt include something like (declare (xargs :stobjs (counters)))?
The explanation of this mystery is as follows. At the time TipCnt was
defined, during the introduction of the counters stobj, the name
``counters'' was not yet a single-threaded object. The introduction
of a new single-threaded object occurs in three steps: (1) The new
primitive recognizers, accessors, and updaters are introduced as
``ordinary functions,'' producing their logical axiomatizations.
(2) The executable counterparts are defined in raw Lisp to support
destructive updating. (3) The new name is declared a
single-threaded object to ensure that all future use of these
primitives respects the single-threadedness of the object. The
functions defined as part of the introduction of a new
single-threaded object are the only functions in the system that
have undeclared stobj formals other than state.
You may return to [stobj-example-1] here.")
(STOBJ-EXAMPLE-1-IMPLEMENTATION
(STOBJ)
"The implementation of the counters stobj
the event
(defstobj counters
(NodeCnt :type integer :initially 0)
(TipCnt :type integer :initially 0)
(IntTipsSeen :type t :initially nil))
discussed in [stobj-example-1], creates a Common Lisp object to
represent the current value of counters. That object is created by
evaluating either of the following ``raw'' (non-ACL2) Common Lisp
forms:
(create-counters)
(vector (make-array 1 :element-type 'integer
:initial-element '0)
(make-array 1 :element-type 'integer
:initial-element '0)
'nil)
and the value is stored in the Common Lisp global variable named
*the-live-counters*.
Thus, the counters object is an array of length three. The first two
elements are arrays of size 1 and are used to hold the NodeCnt and
TipCnt fields. The third element is the IntTipsSeen field. The
first two fields are represented by arrays so that we can implement
the integer type specification efficiently. Generally, integers are
``boxed'' in some Common Lisp implementations, for example, GCL.
Creating a new integer requires creating a new box to put it in.
But in some lisps, including GCL, the integers inside arrays of
integers are not boxed.
The function NodeCnt is defined in raw Lisp as:
(defun NodeCnt (counters)
(the integer
(aref (the (simple-array integer (1))
(svref counters 0))
0)))
Observe that the form (svref counters 0) is evaluated to get an array
of size 1, which is followed by a call of aref to access the 0th
element of that array.
The function update-NodeCnt is defined in raw Lisp as:
(defun update-NodeCnt (v counters)
(declare (type integer v))
(progn
(setf (aref (the (simple-array integer (1))
(svref counters 0))
0)
(the integer v))
counters))
Note that when this function is called, it does not create a new
vector of length three, but ``smashes'' the existing one.
One way to see all the raw Lisp functions defined by a given defstobj
is to evaluate the defstobj event and then evaluate, in the ACL2
loop, the expression (nth 4 (global-val 'cltl-command (w state))).
Those functions that contain (DECLARE (STOBJ-INLINE-FN T)) will
generate [defabbrev] forms because the :inline keyword of
[defstobj] was supplied the value t. The rest will generate
[defun]s.
We now recommend that you look at [stobj-example-1-proofs].")
(STOBJ-EXAMPLE-1-PROOFS
(STOBJ)
"Some proofs involving the counters stobj
Consider again the event
(defstobj counters
(NodeCnt :type integer :initially 0)
(TipCnt :type integer :initially 0)
(IntTipsSeen :type t :initially nil))
discussed in [stobj-example-1], followed by the definition
(defun reset-counters (counters)
(declare (xargs :stobjs (counters)))
(seq counters
(update-NodeCnt 0 counters)
(update-TipCnt 0 counters)
(update-IntTipsSeen nil counters)))
which, because of the seq macro in [stobj-example-1], is just
syntactic sugar for
(defun reset-counters (counters)
(declare (xargs :stobjs (counters)))
(let ((counters (update-NodeCnt 0 counters)))
(let ((counters (update-TipCnt 0 counters)))
(update-IntTipsSeen nil counters)))).
Here is a simple theorem about reset-counters.
(defthm reset-counters-is-constant
(implies (countersp x)
(equal (reset-counters x)
'(0 0 nil))))
Before we talk about how to prove this theorem, note that the theorem
is unusual in two respects.
First, it calls reset-counters on an argument other than the variable
counters! That is allowed in theorems; logically speaking, the
stobj functions are indistinguishable from ordinary functions.
Their use is syntactically restricted only in defuns, which might
be compiled and run in raw Lisp. Those restrictions allow us to
implement stobj modification destructively. But logically speaking,
reset-counters and other stobj ``modifying'' functions just create
new objects, constructively.
Second, the theorem above explicitly provides the hypothesis that
reset-counters is being applied to an object satisfying countersp.
Such a hypothesis is not always required: reset-counters is total
and will do something no matter what x is. But in this particular
case, the result is not '(0 0 nil) unless x is, at least, a
true-list of length three.
To make a long story short, to prove theorems about stobj functions
you behave in exactly the way you would to prove the same theorems
about the same functions defined without the stobj features.
How can we prove the above theorem? Unfolding the definition of
reset-counters shows that (reset-counters x) is equal to
(update-IntTipsSeen nil
(update-TipCnt 0
(update-NodeCnt 0 x)))
which in turn is
(update-nth 2 nil
(update-nth 1 0
(update-nth 0 0 x))).
Opening up the definition of update-nth reduces this to
(list* 0 0 nil (cdddr x)).
This is clearly equal to '(0 0 nil), provided we know that (cdddr x)
is nil.
Unfortunately, that last fact requires a lemma. The most specific
lemma we could provide is
(defthm special-lemma-for-counters
(implies (countersp x)
(equal (cdddr x) nil)))
but if you try to prove that lemma you will find that it requires
some reasoning about len and true-listp. Furthermore, the special
lemma above is of interest only for counters.
The following lemma about len is the one we prefer.
(defthm equal-len-n
(implies (syntaxp (quotep n))
(equal (equal (len x) n)
(if (integerp n)
(if (< n 0)
nil
(if (equal n 0)
(atom x)
(and (consp x)
(equal (len (cdr x)) (- n 1)))))
nil))))
This lemma will simplify any equality in which a len expression is
equated to any explicitly given constant n, e.g., 3, reducing the
equation to a conjunction of consp terms about the first n cdrs.
If the above lemma is available then ACL2 immediately proves
(defthm reset-counters-is-constant
(implies (countersp x)
(equal (reset-counters x)
'(0 0 nil))))
The point is presumably well made: proving theorems about
single-threaded object accessors and updaters is no different than
proving theorems about other recursively defined functions on
lists.
As we have seen, operations on [stobj]s turn into definitions
involving [nth] and [update-nth] in the logic. Here are two lemmas,
both due to Matt Wilding, that are useful for simplifying terms
involving nth and update-nth, which are therefore useful in
reasoning about single-threaded objects.
(defthm update-nth-update-nth-same
(implies (equal (nfix i1) (nfix i2))
(equal (update-nth i1 v1 (update-nth i2 v2 l))
(update-nth i1 v1 l))))
(defthm update-nth-update-nth-diff
(implies (not (equal (nfix i1) (nfix i2)))
(equal (update-nth i1 v1 (update-nth i2 v2 l))
(update-nth i2 v2 (update-nth i1 v1 l))))
:rule-classes ((:rewrite :loop-stopper ((i1 i2)))))
We now recommend that you see [stobj-example-2].")
(STOBJ-EXAMPLE-2
(STOBJ)
"An example of the use of arrays in single-threaded objects
The following event
(defstobj ms
(pcn :type integer :initially 0)
(mem :type (array integer (100000)) :initially -1)
(code :type t :initially nil))
introduces a single-threaded object named ms (which stands for
``machine state''). The object has three fields, a pcn or program
counter, a mem or memory, and a code field.
The mem field is occupied by an object initially of type (array
integer (100000)). Logically speaking, this is a list of length
100000, each element of which is an integer. But in the underlying
implementation of the ms object, this field is occupied by a raw
Lisp array, initially of size 100000.
You might expect the above defstobj to define the accessor function
mem and the updater update-mem. That does not happen!.
The above event defines the accessor function memi and the updater
update-memi. These functions do not access/update the mem field of
the ms object; they access/update the individual elements of the
array in that field.
In particular, the logical definitions of the two functions are:
(defun memi (i ms)
(declare (xargs :guard
(and (msp ms)
(integerp i)
(<= 0 i)
(< i (mem-length ms)))))
(nth i (nth 1 ms)))
(defun update-memi (i v ms)
(declare (xargs :guard
(and (msp ms)
(integerp i)
(<= 0 i)
(< i (mem-length ms))
(integerp v))))
(update-nth-array 1 i v ms))
For example, to access the 511th (0-based) memory location of the
current ms you could evaluate:
ACL2 !>(memi 511 ms)
-1
The answer is -1 initially, because that is the above-specified
initial value of the elements of the mem array.
To set that element you could do
ACL2 !>(update-memi 511 777 ms)
<ms>
ACL2 !>(memi 511 ms)
777
The raw Lisp implementing these two functions is shown below.
(defun memi (i ms)
(declare (type (and fixnum (integer 0 *)) i))
(the integer
(aref (the (simple-array integer (*))
(svref ms 1))
(the (and fixnum (integer 0 *)) i))))
(defun update-memi (i v ms)
(declare (type (and fixnum (integer 0 *)) i)
(type integer v))
(progn
(setf (aref (the (simple-array integer (*))
(svref ms 1))
(the (and fixnum (integer 0 *)) i))
(the integer v))
ms))
If you want to see the raw Lisp supporting a defstobj, execute the
defstobj and then evaluate the ACL2 form (nth 4 (global-val
'cltl-command (w state))).
To continue the stobj tour, see [stobj-example-3].")
(STOBJ-EXAMPLE-3
(STOBJ)
"Another example of a single-threaded object
The event
(defstobj $s
(x :type integer :initially 0)
(a :type (array (integer 0 9) (3)) :initially 9 :resizable t))
introduces a stobj named $S. The stobj has two fields, X and A. The A
field is an array. The X field contains an integer and is initially
0. The A field contains a list of integers, each between 0 and 9,
inclusively. (Under the hood, this ``list'' is actually implemented
as an array.) Initially, the A field has three elements, each of
which is 9.
This event introduces the following sequence of function definitions:
(DEFUN XP (X) ...) ; recognizer for X field
(DEFUN AP (X) ...) ; recognizer of A field
(DEFUN $SP ($S) ...) ; top-level recognizer for stobj $S
(DEFUN CREATE-$S NIL ...) ; creator for stobj $S
(DEFUN X ($S) ...) ; accessor for X field
(DEFUN UPDATE-X (V $S) ...) ; updater for X field
(DEFUN A-LENGTH ($S) ...) ; length of A field
(DEFUN RESIZE-A (K $S) ...) ; resizer for A field
(DEFUN AI (I $S) ...) ; accessor for A field at index I
(DEFUN UPDATE-AI (I V $S) ...) ; updater for A field at index I
Here is the definition of $SP:
(DEFUN $SP ($S)
(DECLARE (XARGS :GUARD T :VERIFY-GUARDS T))
(AND (TRUE-LISTP $S)
(= (LENGTH $S) 2)
(XP (NTH 0 $S))
(AP (NTH 1 $S))
T))
This reveals that in order to satisfy $SP an object must be a true
list of length 2 whose first element satisfies XP and whose second
satisfies AP. By printing the definition of AP one learns that it
requires its argument to be a true list, each element of which is
an integer between 0 and 9.
The initial value of stobj $S is given by zero-ary ``creator''
function CREATE-$S. Creator functions may only be used in limited
contexts. See [with-local-stobj].
Here is the definition of UPDATE-AI, the updater for the A field at
index I:
(DEFUN UPDATE-AI (I V $S)
(DECLARE (XARGS :GUARD
(AND ($SP $S)
(INTEGERP I)
(<= 0 I)
(< I (A-LENGTH $S))
(AND (INTEGERP V) (<= 0 V) (<= V 9)))
:VERIFY-GUARDS T))
(UPDATE-NTH-ARRAY 1 I V $S))
By definition (UPDATE-NTH-ARRAY 1 I V $S) is (UPDATE-NTH 1
(UPDATE-NTH I V (NTH 1 $S)) $S). This may be a little surprising
but should be perfectly clear.
First, ignore the guard, since it is irrelevant in the logic. Reading
from the inside out, (UPDATE-AI I V $S) extracts (NTH 1 $S), which
is array a of $S. (Recall that [nth] is 0-based.) The next higher
expression in the definition above, (UPDATE-NTH I V a),
``modifies'' a by setting its Ith element to V. Call this a'. The
next higher expression, (UPDATE-NTH 1 a' $S), ``modifies'' $S by
setting its 1st component to a'. Call this result $s'. Then $s' is
the result returned by UPDATE-AI.
So the first useful observation is that from the perspective of the
logic, the type ``restrictions'' on stobjs are irrelevant. They are
``enforced'' by ACL2's guard mechanism, not by the definitions of
the updater functions.
As one might also imagine, the accessor functions do not really
``care,'' logically, whether they are applied to well-formed stobjs
or not. For example, (AI I $S) is defined to be (NTH I (NTH 1 $S)).
Thus, you will not be able to prove that (AI 2 $S) is an integer.
That is,
(integerp (AI 2 $S))
is not a theorem, because $S may not be well-formed.
Now (integerp (AI 2 $S)) will always evaluate to T in the top-level
ACL2 command loop, because we insist that the current value of the
stobj $S always satisfies $SP by enforcing the guards on the
updaters, independent of whether guard checking is on or off; see
[set-guard-checking]. But in a theorem $S is just another variable,
implicitly universally quantified.
So (integerp (AI 2 $S)) is not a theorem because it is not true when
the variable $S is instantiated with, say,
'(1 (0 1 TWO))
because, logically speaking, (AI 2 '(1 (0 1 TWO))) evaluates to the
symbol TWO. That is,
(equal (AI 2 '(1 (0 1 TWO))) 'TWO)
is true.
However,
(implies (and ($SP $S) (< 2 (A-LENGTH $S))) (integerp (AI 2 $S)))
is a theorem. To prove it, you will have to prove a lemma about AP.
The following will do:
(defthm ap-nth
(implies (and (AP x)
(integerp i)
(<= 0 i)
(< i (len x)))
(integerp (nth i x)))).
Similarly,
(implies (and (integerp i)
(<= 0 i)
(< i (A-LENGTH $S))
(integerp v)
(<= 0 v)
(<= v 9))
($SP (UPDATE-AI i v $S)))
is not a theorem until you add the additional hypothesis ($SP $S). To
prove the resulting theorem, you will need a lemma such as the
following.
(defthm ap-update-nth
(implies (and (AP a)
(integerp v)
(<= 0 v)
(<= v 9)
(integerp i)
(<= 0 i)
(< i (len a)))
(AP (update-nth i v a))))
The moral here is that from the logical perspective, you must provide
the hypotheses that, as a programmer, you think are implicit on the
structure of your stobjs, and you must prove their invariance. This
is a good area for further support, perhaps in the form of a
library of macros.
Resizing Array Fields
Recall the specification of the array field, A for the stobj $S
introduced above:
(a :type (array (integer 0 9) (3)) :initially 9 :resizable t)
Logically, this field is a list, initially of length 3. Under the
hood, this field is implemented using a Common Lisp array with 3
elements. In some applications, one may wish to lengthen an array
field, or even (to reclaim space) to shrink an array field. The
[defstobj] event provides functions to access the current length of
an array field and to change the array field, with default names
obtained by suffixing the field name with ``LENGTH-'' or prefixing
it with ``RESIZE-,'' respectively. The following log shows the uses
of these fields in the above example.
ACL2 !>(A-LENGTH $S)
3
ACL2 !>(RESIZE-A 10 $S) ; change length of A to 10
<$s>
ACL2 !>(A-LENGTH $S)
10
ACL2 !>(AI 7 $S) ; new elements get value from :initially
9
ACL2 !>(RESIZE-A 2 $S) ; truncate A down to first 2 elements
<$s>
ACL2 !>(A-LENGTH $S)
2
ACL2 !>(AI 7 $S) ; error: access past array bound
ACL2 Error in TOP-LEVEL: The guard for the function symbol AI, which
is (AND ($SP $S) (INTEGERP I) (<= 0 I) (< I (A-LENGTH $S))), is violated
by the arguments in the call (AI 7 $S).
ACL2 !>
Here are the definitions of the relevant functions for the above
example; also see [resize-list].
(DEFUN A-LENGTH ($S)
(DECLARE (XARGS :GUARD ($SP $S) :VERIFY-GUARDS T))
(LEN (NTH 1 $S)))
(DEFUN RESIZE-A (K $S)
(DECLARE (XARGS :GUARD ($SP $S) :VERIFY-GUARDS T))
(UPDATE-NTH 1
(RESIZE-LIST (NTH 1 $S) K 9)
$S))
It is important to note that the implementation of array resizing in
ACL2 involves copying the entire array into a newly allocated space
and thus can be quite costly if performed often. This approach was
chosen in order to make array access and update as efficient as
possible, with the suspicion that for most applications, array
access and update are considerably more frequent than resizing
(especially if the programmer is aware of the relative costs
beforehand).
It should also be noted that computations of lengths of stobj array
fields should be fast (constant-time) in all or most Common Lisp
implementations.
Finally, if :resizable t is not supplied as shown above, then an
attempt to resize the array will result in an error. If you do not
intend to resize the array, it is better to omit the :resizable
option (or to supply :resizable nil), since then the length
function will be defined to return a constant, namely the initial
length, which can simplify guard proofs (compare with the
definition of A-LENGTH above).
This completes the tour through the documentation of [stobj]s.
However, you may now wish to read the documentation for the event
that introduces a new single-threaded object; see [defstobj].")
(STOBJ-LET (POINTERS)
"See [nested-stobjs].")
(STOBJS (POINTERS)
"See [xargs] for keyword :stobjs.")
(STOP-PROOF-TREE
(PROOF-TREE)
"Stop displaying proof trees during proofs
Also see [proof-tree] and see [start-proof-tree]. Note that
:stop-proof-tree works by adding '[proof-tree] to the
inhibit-output-lst; see [set-inhibit-output-lst].
Proof tree displays are explained in the documentation for
[proof-tree]. :Stop-proof-tree causes proof tree display to be
turned off.
It is permissible to submit the form (stop-proof-tree) during a
break. Thus, you can actually turn off proof tree display in the
middle of a proof by interrupting ACL2 and submitting the form
(stop-proof-tree) in raw Lisp.")
(STRING
(STRINGS ACL2-BUILT-INS)
"[coerce] to a string
(String x) [coerce]s x to a string.
The [guard] for string requires its argument to be a string, a
symbol, or a character.
* If x is already a string, then it is returned unchanged.
* If x is a symbol, then its [symbol-name] is returned.
* If x is a character, the corresponding one-character string is
returned.
Note: this is a rather low-level operation that doesn't support
coercing numbers or conses into strings. If you want to turn
numbers into strings, see functions such as [str::natstr], or more
generally the [str::numbers] functions. For conses, see the
[str::pretty-printing] routines such as [str::pretty].
String is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <string>
(defun string (x)
(declare (xargs :guard (or (stringp x)
(symbolp x)
(characterp x))))
(cond ((stringp x) x)
((symbolp x) (symbol-name x))
(t (coerce (list x) 'string))))")
(STRING-APPEND
(STRINGS ACL2-BUILT-INS)
"[concatenate] two strings
String-append takes two arguments, which are both strings (if the
[guard] is to be met), and returns a string obtained by
concatenating together the [characters] in the first string
followed by those in the second. Also see [concatenate], noting
that the macro call
(concatenate 'string str1 str2).
expands to the call
(string-append str1 str2).
Function: <string-append>
(defun string-append (str1 str2)
(declare (xargs :guard (and (stringp str1) (stringp str2))))
(mbe :logic (coerce (append (coerce str1 'list)
(coerce str2 'list))
'string)
:exec (concatenate 'string str1 str2)))")
(STRING-DOWNCASE
(STRINGS ACL2-BUILT-INS)
"In a given string, turn upper-case [characters] into lower-case
For a string x, (string-downcase x) is the result of applying
[char-downcase] to each character in x.
The [guard] for string-downcase requires its argument to be a string
containing only standard characters.
String-downcase is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <string-downcase>
(defun
string-downcase (x)
(declare
(xargs :guard (and (stringp x)
(standard-char-listp (coerce x 'list)))))
(coerce (string-downcase1 (coerce x 'list))
'string))")
(STRING-EQUAL
(STRINGS ACL2-BUILT-INS)
"String equality without regard to case
For strings str1 and str2, (string-equal str1 str2) is true if and
only str1 and str2 are the same except perhaps for the cases of
their [characters].
The [guard] on string-equal requires that its arguments are strings
consisting of standard characters (see [standard-char-listp]).
String-equal is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <string-equal>
(defun
string-equal (str1 str2)
(declare
(xargs :guard (and (stringp str1)
(standard-char-listp (coerce str1 'list))
(stringp str2)
(standard-char-listp (coerce str2 'list)))))
(let ((len1 (length str1)))
(and (= len1 (length str2))
(string-equal1 str1 str2 0 len1))))")
(STRING-LISTP
(STRINGS LISTS ACL2-BUILT-INS)
"Recognizer for a true list of strings
The predicate string-listp tests whether its argument is a
[true-listp] of strings.
Function: <string-listp>
(defun string-listp (x)
(declare (xargs :guard t))
(cond ((atom x) (eq x nil))
(t (and (stringp (car x))
(string-listp (cdr x))))))")
(STRING-UPCASE
(STRINGS ACL2-BUILT-INS)
"In a given string, turn lower-case [characters] into upper-case
For a string x, (string-upcase x) is the result of applying
[char-upcase] to each character in x.
The [guard] for string-upcase requires its argument to be a string
containing only standard characters.
String-upcase is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <string-upcase>
(defun
string-upcase (x)
(declare
(xargs :guard (and (stringp x)
(standard-char-listp (coerce x 'list)))))
(coerce (string-upcase1 (coerce x 'list))
'string))")
(STRING<
(STRINGS ACL2-BUILT-INS)
"Less-than test for strings
(String< str1 str2) is non-nil if and only if the string str1
precedes the string str2 lexicographically, where character
inequalities are tested using [char<]. When non-nil, (string< str1
str2) is the first position (zero-based) at which the strings
differ. Here are some examples.
ACL2 !>(string< \"abcd\" \"abu\")
2
ACL2 !>(string< \"abcd\" \"Abu\")
NIL
ACL2 !>(string< \"abc\" \"abcde\")
3
ACL2 !>(string< \"abcde\" \"abc\")
NIL
The [guard] for string< specifies that its arguments are strings.
String< is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <string<>
(defun string< (str1 str2)
(declare (xargs :guard (and (stringp str1) (stringp str2))))
(string<-l (coerce str1 'list)
(coerce str2 'list)
0))")
(STRING<=
(STRINGS ACL2-BUILT-INS)
"Less-than-or-equal test for strings
(String<= str1 str2) is non-nil if and only if the string str1
precedes the string str2 lexicographically or the strings are
equal. When non-nil, (string<= str1 str2) is the first position
(zero-based) at which the strings differ, if they differ, and
otherwise is their common length. See [string<].
The [guard] for string<= specifies that its arguments are strings.
String<= is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <string<=>
(defun string<= (str1 str2)
(declare (xargs :guard (and (stringp str1) (stringp str2))))
(if (equal str1 str2)
(length str1)
(string< str1 str2)))")
(STRING>
(STRINGS ACL2-BUILT-INS)
"Greater-than test for strings
(String> str1 str2) is non-nil if and only if str2 precedes str1
lexicographically. When non-nil, (string> str1 str2) is the first
position (zero-based) at which the strings differ. See [string<].
String> is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <string>>
(defun string> (str1 str2)
(declare (xargs :guard (and (stringp str1) (stringp str2))))
(string< str2 str1))")
(STRING>=
(STRINGS ACL2-BUILT-INS)
"Less-than-or-equal test for strings
(String>= str1 str2) is non-nil if and only if the string str2
precedes the string str1 lexicographically or the strings are
equal. When non-nil, (string>= str1 str2) is the first position
(zero-based) at which the strings differ, if they differ, and
otherwise is their common length. See [string>].
The [guard] for string>= specifies that its arguments are strings.
String>= is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <string>=>
(defun string>= (str1 str2)
(declare (xargs :guard (and (stringp str1) (stringp str2))))
(if (equal str1 str2)
(length str1)
(string> str1 str2)))")
(STRINGP
(STRINGS ACL2-BUILT-INS)
"Recognizer for strings
(stringp x) is true if and only if x is a string.")
(STRINGS
(PROGRAMMING)
"Strings are atomic objects that contain character sequences, like
\"Hello World\".
See the [std/strings] library for many additional string functions
and lemmas about the built-in string functions.
Subtopics
[Coerce]
Coerce a character list to a string and a string to a list
[Concatenate]
Concatenate lists or strings together
[Count]
Count the number of occurrences of an item in a string or true-list
[Length]
Length of a string or proper list
[Position]
Position of an item in a string or a list
[Remove-duplicates]
Remove duplicates from a string or a list
[Reverse]
Reverse a list or string
[Search]
Search for a string or list in another string or list
[String]
[coerce] to a string
[String-append]
[concatenate] two strings
[String-downcase]
In a given string, turn upper-case [characters] into lower-case
[String-equal]
String equality without regard to case
[String-listp]
Recognizer for a true list of strings
[String-upcase]
In a given string, turn lower-case [characters] into upper-case
[String<]
Less-than test for strings
[String<=]
Less-than-or-equal test for strings
[String>]
Greater-than test for strings
[String>=]
Less-than-or-equal test for strings
[Stringp]
Recognizer for strings
[Subseq]
Subsequence of a string or list
[Substitute]
Substitute into a string or a list, using [eql] as test")
(STRIP-CARS
(ALISTS ACL2-BUILT-INS)
"Collect up all first components of pairs in a list
(strip-cars x) is the list obtained by walking through the list x and
collecting up all first components ([car]s). This function is
implemented in a tail-recursive way, despite its logical
definition.
(strip-cars x) has a [guard] of (alistp x).
Function: <strip-cars>
(defun strip-cars (x)
(declare (xargs :guard (alistp x)))
(cond ((endp x) nil)
(t (cons (car (car x))
(strip-cars (cdr x))))))")
(STRIP-CDRS
(ALISTS ACL2-BUILT-INS)
"Collect up all second components of pairs in a list
(strip-cdrs x) has a [guard] of (alistp x), and returns the list
obtained by walking through the list x and collecting up all second
components ([cdr]s). This function is implemented in a
tail-recursive way, despite its logical definition.
Function: <strip-cdrs>
(defun strip-cdrs (x)
(declare (xargs :guard (alistp x)))
(cond ((endp x) nil)
(t (cons (cdr (car x))
(strip-cdrs (cdr x))))))")
(STRONG-REWRITE-RULES
(INTRODUCTION-TO-THE-THEOREM-PROVER)
"Formulating good rewrite rules
Suppose you notice the following term in a Key Checkpoint:
(MEMBER (CAR A) (REV B)).
You might think of two theorems for handling this term, which we'll
call the ``weak'' and ``strong'' version of member-rev.
(defthm member-rev-weak
(implies (member e b)
(member e (rev b)))).
(defthm member-rev-strong
(iff (member e (rev b))
(member e b))).
The ``strong'' version logically implies the ``weak'' version and so
deserves the adjective. (Recall that ``p <---> q'' is just ``p --->
q'' and ``q ---> p.'' So the strong version quite literally says
everything the weak version does and then some.)
But the ``strong'' version also produces a better rewrite rule. Here
are the rules generated from these two formulas, phrased as
directives to ACL2's simplifier:
member-rev-weak: If you ever see an instance of (MEMBER e (REV b)),
backchain to (MEMBER e b) (i.e., turn your attention to that term)
and if you can show that it is true, replace (MEMBER e (REV b)) by
T.
member-rev-strong: If you ever see an instance of (MEMBER e (REV b)),
replace it by (MEMBER e b).
Technical Note: Actually, both rules concern propositional
occurrences of the ``target'' expression, (MEMBER e (REV b)), i.e.,
occurrences of the target in which its truthvalue is the only thing
of relevance. (Recall that (MEMBER x y) returns the tail of y
starting with x! Evaluate some simple MEMBER expressions, like
(MEMBER 3 '(1 2 3 4 5)) to see what we mean.) Both theorems tell us
about circumstances in which the target is non-NIL (i.e., ``true'')
without telling us its identity. But ACL2 keeps track of when the
target is in a propositional occurrence and can use such rules to
rewrite the target to propositionally equivalent terms.
So the strong version is better because it will always eliminate
(MEMBER e (REV b)) in favor of (MEMBER e b). That simpler
expression may be further reduced if the context allows it. But in
any case, the strong version eliminates REV from the problem. The
weak version only eliminates REV when a side-condition can be
proved.
While either version may permit us to prove the Key Checkpoint that
``suggested'' the rule, the strong version is a better rule to have
in the database going forward.
For example, suppose NATS-BELOW returns the list of natural numbers
below its argument. Imagine two alternative scenarios in which a
key checkpoint is about to arise involving this term:
(MEMBER K (REV (NATS-BELOW J)))
Scenario 1 is when you've got the strong version in your database: it
will rewrite the key checkpoint term to
(MEMBER K (NATS-BELOW J))
and that's what you'll see in the printed checkpoint unless other
rules reduce it further.
Scenario 2 is when you have only the weak version in your database:
the weak rule will attempt to reduce the term above to T and will,
if there are sufficient rules and hypotheses about K's membership
in (NATS-BELOW J). But if no such rules or hypotheses are
available, you'll be confronted with a key checkpoint involving
(MEMBER K (REV (NATS-BELOW J)))
and it will not be obvious that the problem would go away if you
could establish that K is in (NATS-BELOW J). Clearly, Scenario 1 is
better.
We recommend that you now practice formulating strong versions of
rules suggested by terms you might see. See
[practice-formulating-strong-rules].
When you are finished with that, use your browser's Back Button to
return to [introduction-to-key-checkpoints].")
(SUBLIS
(ALISTS ACL2-BUILT-INS)
"Substitute an alist into a tree
(Sublis alist tree) is obtained by replacing every leaf of tree with
the result of looking that leaf up in the association list alist.
However, a leaf is left unchanged if it is not found as a key in
alist.
Leaves are looked up using the function [assoc]. The [guard] for
(sublis alist tree) requires (eqlable-alistp alist). This [guard]
ensures that the [guard] for [assoc] will be met for each lookup
generated by sublis.
Sublis is defined in Common Lisp. See any Common Lisp documentation
for more information.
Function: <sublis>
(defun sublis (alist tree)
(declare (xargs :guard (eqlable-alistp alist)))
(cond ((atom tree)
(let ((pair (assoc tree alist)))
(cond (pair (cdr pair)) (t tree))))
(t (cons (sublis alist (car tree))
(sublis alist (cdr tree))))))")
(SUBSEQ
(LISTS STRINGS ACL2-BUILT-INS)
"Subsequence of a string or list
For any natural numbers start and end, where start <= end <= (length
seq), (subseq seq start end) is the subsequence of seq from index
start up to, but not including, index end. End may be nil, in which
case it is treated as though it is (length seq), i.e., we obtain
the subsequence of seq from index start all the way to the end.
The [guard] for (subseq seq start end) is that seq is a true list or
a string, start and end are integers (except, end may be nil, in
which case it is treated as (length seq) for the rest of this
discussion), and 0 <= start <= end <= (length seq).
Subseq is a Common Lisp function. See any Common Lisp documentation
for more information. Note: In Common Lisp the third argument of
subseq is optional, but in ACL2 it is required, though it may be
nil as explained above.
Function: <subseq>
(defun
subseq (seq start end)
(declare (xargs :guard (and (or (true-listp seq) (stringp seq))
(integerp start)
(<= 0 start)
(or (null end)
(and (integerp end)
(<= end (length seq))))
(<= start (or end (length seq))))))
(if (stringp seq)
(coerce (subseq-list (coerce seq 'list)
start (or end (length seq)))
'string)
(subseq-list seq start (or end (length seq)))))")
(SUBSETP
(LISTS ACL2-BUILT-INS)
"Test if every [member] of one list is a [member] of the other
General Forms:
(subsetp x y)
(subsetp x y :test 'eql) ; same as above (eql as equality test)
(subsetp x y :test 'eq) ; same, but eq is equality test
(subsetp x y :test 'equal) ; same, but equal is equality test
(Subsetp x y) is true if and only if every [member] of the list x is
a member of the list y. The optional keyword, :TEST, has no effect
logically, but provides the test (default [eql]) used for comparing
members of the two lists.
The [guard] for a call of subsetp depends on the test. In all cases,
both arguments must satisfy [true-listp]. If the test is [eql],
then one of the arguments must satisfy [eqlable-listp]. If the test
is [eq], then one of the arguments must satisfy [symbol-listp].
See [equality-variants] for a discussion of the relation between
subsetp and its variants:
(subsetp-eq x lst) is equivalent to (subsetp x lst :test 'eq);
(subsetp-equal x lst) is equivalent to (subsetp x lst :test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function subsetp-equal.
Function: <subsetp-equal>
(defun subsetp-equal (x y)
(declare (xargs :guard (and (true-listp y) (true-listp x))))
(cond ((endp x) t)
((member-equal (car x) y)
(subsetp-equal (cdr x) y))
(t nil)))
Subsetp is defined by Common Lisp. See any Common Lisp documentation
for more information.")
(SUBSETP-EQ (POINTERS) "See [subsetp].")
(SUBSETP-EQUAL (POINTERS)
"See [subsetp].")
(SUBST
(CONSES ACL2-BUILT-INS)
"A single substitution into a tree
(Subst new old tree) is obtained by substituting new for every
occurence of old in the given tree.
Equality to old is determined using the function [eql]. The [guard]
for (subst new old tree) requires (eqlablep old), which ensures
that the [guard] for [eql] will be met for each comparison
generated by subst.
Subst is defined in Common Lisp. See any Common Lisp documentation
for more information.
Function: <subst>
(defun subst (new old tree)
(declare (xargs :guard (eqlablep old)))
(cond ((eql old tree) new)
((atom tree) tree)
(t (cons (subst new old (car tree))
(subst new old (cdr tree))))))")
(SUBSTITUTE
(LISTS STRINGS ACL2-BUILT-INS)
"Substitute into a string or a list, using [eql] as test
(Substitute new old seq) is the result of replacing each occurrence
of old in seq, which is a list or a string, with new.
The guard for substitute requires that either seq is a string and new
is a character, or else: seq is a [true-listp] such that either all
of its members are [eqlablep] or old is eqlablep.
Substitute is a Common Lisp function. See any Common Lisp
documentation for more information. Since ACL2 functions cannot
take keyword arguments (though macros can), the test used in
substitute is eql.
Function: <substitute>
(defun
substitute (new old seq)
(declare (xargs :guard (or (and (stringp seq) (characterp new))
(and (true-listp seq)
(or (eqlablep old)
(eqlable-listp seq))))))
(if (stringp seq)
(coerce (substitute-ac new old (coerce seq 'list)
nil)
'string)
(substitute-ac new old seq nil)))")
(SUBSUMPTION_OF_INDUCTION_CANDIDATES_IN_APP_EXAMPLE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Subsumption of Induction Candidates in App Example
After collecting induction suggestions from these three terms
(app a b)
(app b c)
(app a (app b c))
the system notices that the first and last suggest the same
decomposition of a: case split on whether a is empty (i.e., (endp
a)), and in the case where it is not empty, recursively process
(cdr a). So we are left with two ideas about how to induct:
Decompose a as we would to unwind (app a b).
Decompose b as we would to unwind (app b c).")
(SUBVERSIVE-INDUCTIONS
(MISCELLANEOUS)
"Why we restrict [encapsulate]d recursive functions
See [subversive-recursions].")
(SUBVERSIVE-RECURSIONS
(MISCELLANEOUS)
"Why we restrict [encapsulate]d recursive functions
Subtleties arise when one of the ``constrained'' functions, f,
introduced in the [signature] of an [encapsulate] event, is
involved in the termination argument for a non-local recursively
defined function, g, in that encapsulate. During the processing of
the encapsulated events, f is locally defined to be some witness
function, f'. Properties of f' are explicitly proved and exported
from the encapsulate as the constraints on the undefined function
f. But if f is used in a recursive g defined within the
encapsulate, then the termination proof for g may use properties of
f' --- the witness --- that are not explicitly set forth in the
constraints stated for f.
Such recursive g are said be ``subversive'' because if naively
treated they give rise to unsound induction schemes or (via
functional instantiation) recurrence equations that are impossible
to satisfy. We illustrate what could go wrong below.
Subversive recursions are not banned outright. Instead, they are
treated as part of the constraint. That is, in the case above, the
definitional equation for g becomes one of the constraints on f.
This is generally a severe restriction on future functional
instantiations of f. In addition, ACL2 removes from its knowledge
of g any suggestions about legal inductions to ``unwind'' its
recursion.
What should you do? Often, the simplest response is to move the
offending recursive definition, e.g., g, out of the encapsulate.
That is, introduce f by constraint and then define g as an
``independent'' event. You may need to constrain ``additional''
properties of f in order to admit g, e.g., constrain it to reduce
some ordinal measure. However, by separating the introduction of f
from the admission of g you will clearly identify the necessary
constraints on f, functional instantiations of f will be simpler,
and g will be a useful function which suggests inductions to the
theorem prover.
Note that the functions introduced in the [signature] should not even
occur ancestrally in the termination proofs for non-local recursive
functions in the encapsulate. That is, the constrained functions of
an encapsulate should not be reachable in the dependency graph of
the functions used in the termination arguments of recursive
functions in encapsulate. If they are reachable, their definitions
become part of the constraints.
The following event illustrates the problem posed by subversive
recursions.
(encapsulate (((f *) => *))
(local (defun f (x) (cdr x)))
(defun g (x)
(if (consp x) (not (g (f x))) t)))
Suppose, contrary to how ACL2 works, that the encapsulate above were
to introduce no constraints on f on the bogus grounds that the only
use of f in the encapsulate is in an admissible function. We
discuss the plausibility of this bogus argument in a moment.
Then it would be possible to prove the theorem:
(defthm f-not-identity
(not (equal (f '(a . b)) '(a . b)))
:rule-classes nil
:hints ((\"Goal\" :use (:instance g (x '(a . b))))))
simply by observing that if (f '(a . b)) were '(a . b), then (g '(a .
b)) would be (not (g '(a . b))), which is impossible.
But then we could functionally instantiate f-not-identity, replacing
f by the identity function, to prove nil! This is bad.
(defthm bad
nil
:rule-classes nil
:hints
((\"Goal\" :use (:functional-instance f-not-identity (f identity)))))
This sequence of events was legal in versions of ACL2 prior to
Version 1.5. When we realized the problem we took steps to make it
illegal. However, our steps were insufficient and it was possible
to sneak in a subversive function (via mutual recursion) as late as
Version 2.3.
We now turn to the plausibility of the bogus argument above. Why
might one even be tempted to think that the definition of g above
poses no constraint on f? Here is a very similar encapsulate.
(encapsulate (((f *) => *))
(local (defun f (x) (cdr x)))
(defun map (x)
(if (consp x)
(cons (f x) (map (cdr x)))
nil)))
Here map plays the role of g above. Like g, map calls the constrained
function f. But map truly does not constrain f. In particular, the
definition of map could be moved ``out'' of the encapsulate so that
map is introduced afterwards. The difference between map and g is
that the constrained function plays no role in the termination
argument for the one but does for the other.
As a ``user-friendly'' gesture, ACL2 implicitly moves map-like
functions out of encapsulations; logically speaking, they are
introduced after the encapsulation. This simplifies the constraint.
When the constraint cannot be thus simplfied the user is advised,
via the ``infected'' warning, to phrase the encapsulation in the
simplest way possible.
The lingering bug between Versions 1.5 and 2.3 mentioned above was
due to our failure to detect the g-like nature of some functions
when they were defined in mutually recursively cliques with other
functions. The singly recursive case was recognized. The bug arose
because our detection ``algorithm'' was based on the ``suggested
inductions'' left behind by successful definitions. We failed to
recall that mutually-recursive definitions do not, as of this
writing, make any suggestions about inductions and so did not leave
any traces of their subversive natures.
We conclude by elaborating on the criterion ``involved in the
termination argument'' mentioned at the outset. Suppose that
function f is recursively defined in an [encapsulate], where the
body of f has no ``ancestor'' among the functions introduced in the
signature of that [encapsulate], i.e.: the body contains no call of
a signature function, no call of a function whose body calls a
signature function, and so on. Then ACL2 treats f as though it is
defined in front of that encapsulate form; so f is not constrained
by the encapsulate, and its definition is hence certainly not
subversive in the sense discussed above. But suppose to the
contrary that some function introduced in the signature is an
ancestor of the body of f. Then the definition of f is subversive
if moreover, its termination proof obligation has an ancestor among
the signature functions. Now, that proof obligation involves terms
from the first argument of selected calls of IF, as well as
recursive calls; for a detailed discussion, see [ruler-extenders].
The important point here is that for the recursive calls, only the
arguments in ``measured'' positions are relevant to the termination
proof obligation. Consider the following example.
(encapsulate
(((h *) => *))
(local (defun h (n) n))
(defun f (i n)
(if (zp i)
n
(f (1- i) (h n)))))
ACL2 heuristically picks the measure (acl2-count i) for the
definition of f; thus, i is the only ``measured formal'' of f.
Since i is the first formal of f, then for the recursive call of f,
only the first argument contributes to the termination proof
obligation: in this case, (1- i) but not (h n). Thus, even though h
is a signature function, the definition of f is not considered to
be subversive; an induction scheme is thus stored for f. (This
restriction to measured formal positions of recursive calls, for
determining subversive definitions, is new in Version_3.5 of ACL2.)")
(SUGGESTED_INDUCTIONS_IN_THE_ASSOCIATIVITY_OF_APP_EXAMPLE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Suggested Inductions in the Associativity of App Example
To find a plausible induction argument, the system studies the
recursions exhibited by the terms in the conjecture.
Roughly speaking, a call of a recursive function ``suggests'' an
induction if the argument position decomposed in recursion is
occupied by a variable.
In this conjecture, three terms suggest inductions:
(app a b)
(app b c)
(app a (app b c))
The variable recursively decomposed is indicated in bold.")
(SYMBOL-<
(SYMBOLS ACL2-BUILT-INS)
"Less-than test for symbols
(symbol-< x y) is non-nil if and only if either the [symbol-name] of
the symbol x lexicographially precedes the [symbol-name] of the
symbol y (in the sense of [string<]) or else the [symbol-name]s are
equal and the [symbol-package-name] of x lexicographically precedes
that of y (in the same sense). So for example, (symbol-< 'abcd
'abce) and (symbol-< 'acl2::abcd 'foo::abce) are true.
The [guard] for symbol specifies that its arguments are symbols.
Function: <symbol-<>
(defun symbol-< (x y)
(declare (xargs :guard (and (symbolp x) (symbolp y))))
(let ((x1 (symbol-name x))
(y1 (symbol-name y)))
(or (string< x1 y1)
(and (equal x1 y1)
(string< (symbol-package-name x)
(symbol-package-name y))))))")
(SYMBOL-ALISTP
(ALISTS ACL2-BUILT-INS)
"Recognizer for association lists with symbols as keys
(Symbol-alistp x) is true if and only if x is a list of pairs of the
form (cons key val) where key is a [symbolp].
Function: <symbol-alistp>
(defun symbol-alistp (x)
(declare (xargs :guard t))
(cond ((atom x) (eq x nil))
(t (and (consp (car x))
(symbolp (car (car x)))
(symbol-alistp (cdr x))))))")
(SYMBOL-LISTP
(SYMBOLS LISTS ACL2-BUILT-INS)
"Recognizer for a true list of symbols
The predicate symbol-listp tests whether its argument is a true list
of symbols.
Function: <symbol-listp>
(defun symbol-listp (lst)
(declare (xargs :guard t))
(cond ((atom lst) (eq lst nil))
(t (and (symbolp (car lst))
(symbol-listp (cdr lst))))))")
(SYMBOL-NAME
(SYMBOLS ACL2-BUILT-INS)
"The name of a symbol (a string)
Completion Axiom (completion-of-symbol-name):
(equal (symbol-name x)
(if (symbolp x)
(symbol-name x)
\"\"))
[Guard] for (symbol-name x):
(symbolp x)")
(SYMBOL-PACKAGE-NAME
(SYMBOLS PACKAGES ACL2-BUILT-INS)
"The name of the package of a symbol (a string)
WARNING: While symbol-package-name behaves properly on all ACL2
objects, it may give surprising results when called in raw Lisp.
For more details see [pkg-imports], in particular the discussion
there of the \"COMMON-LISP\" package.
Completion Axiom (completion-of-symbol-package-name):
(equal (symbol-package-name x)
(if (symbolp x)
(symbol-package-name x)
\"\"))
[Guard] for (symbol-package-name x):
(symbolp x)
Note: Symbol-package-name may diverge from the name of the symbol's
package in raw Lisp, in the case that this package is the main Lisp
package. For example, in GCL (symbol-package-name 'car) evaluates
to \"COMMON-LISP\" even though the actual package name for the
symbol, car, is \"LISP\".")
(SYMBOLIC_EXECUTION_OF_MODELS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Symbolic Execution of Models
[{IMAGE}]
But ACL2 is more than a programming language.
Initialize x to 5 and let y be any legal value.
{IMAGE}
Because ACL2 is a mathematical language, we can simplify the
expression
(lookup 'z (mc (s 'mult 5 y) 29))
and get (+ y y y y y). This is symbolic execution because not all of
the parameters are known.
[{IMAGE}]")
(SYMBOLP
(SYMBOLS ACL2-BUILT-INS)
"Recognizer for symbols
(symbolp x) is true if and only if x is a symbol.
Subtopics
[Intern]
Create a new symbol in a given package
[Intern$]
Create a new symbol in a given package
[Intern-in-package-of-symbol]
Create a symbol with a given name")
(SYMBOLS
(PROGRAMMING)
"Symbols in ACL2 and operations on them
Symbols are a basic datatype in ACL2 and Common Lisp. Every symbol
has two components: its name (see [symbol-name]) and its package
name (see [symbol-package-name]).
Subtopics
[Add-to-set]
Add a symbol to a list
[Keywordp]
Recognizer for keywords
[Symbol-<]
Less-than test for symbols
[Symbol-listp]
Recognizer for a true list of symbols
[Symbol-name]
The name of a symbol (a string)
[Symbol-package-name]
The name of the package of a symbol (a string)
[Symbolp]
Recognizer for symbols")
(SYNTAX
(MISCELLANEOUS)
"The syntax of ACL2 is that of Common Lisp
For the details of ACL2 syntax, see CLTL. For examples of ACL2
syntax, use :[pe] to print some of the ACL2 system code. For
example:
:pe assoc-equal
:pe dumb-occur
:pe var-fn-count
:pe add-linear-variable-to-alist
There is no comprehensive description of the ACL2 syntax yet, except
that found in CLTL. Also see [term].")
(SYNTAXP
(REWRITE DEFINITION LINEAR META)
"Attach a heuristic filter on a rule
A call of syntaxp in the hypothesis of a :[rewrite], :[definition],
or :[linear] rule is treated specially, as described below. Similar
treatment is given to the evaluation of a :[meta] rule's hypothesis
function call.
For example, consider the :[rewrite] rule created from the following
formula.
Example:
(IMPLIES (SYNTAXP (NOT (AND (CONSP X)
(EQ (CAR X) 'NORM))))
(EQUAL (LXD X)
(LXD (NORM X)))).
The syntaxp hypothesis in this rule will allow the rule to be applied
to (lxd (trn a b)) but will not allow it to be applied to (lxd
(norm a)).
General Form:
(SYNTAXP test)
Syntaxp always returns t and so may be added as a vacuous hypothesis.
However, when relieving the hypothesis, the test ``inside'' the
syntaxp form is actually treated as a meta-level proposition about
the proposed instantiation of the rule's variables and that
proposition must evaluate to true (non-nil) to ``establish'' the
syntaxp hypothesis.
Note that the test of a syntaxp hypothesis does not, in general, deal
with the meaning or semantics or values of the terms, but rather
with their syntactic forms. In the example above, the syntaxp
hypothesis allows the rule to be applied to every target of the
form (lxd u), provided u is not of the form (norm v). Observe that
without this syntactic restriction the rule above could loop,
producing a sequence of increasingly complex targets (lxd a), (lxd
(norm a)), (lxd (norm (norm a))), etc. An intuitive reading of the
rule might be ``norm the argument of lxd unless it has already been
normed.''
Note also that a syntaxp hypothesis deals with the syntactic form
used internally by ACL2, rather than that seen by the user. In some
cases these are the same, but there can be subtle differences with
which the writer of a syntaxp hypothesis must be aware. You can use
:[trans] to display this internal representation.
There are two types of syntaxp hypotheses. The simpler type may be a
hypothesis of a :[rewrite], :[definition], or :[linear] rule
provided test contains at least one variable but no free variables
(see [free-variables]). In particular, test may not use [stobj]s;
any stobj name will be treated as an ordinary variable. The case of
:[meta] rules is similar to the above, except that it applies to
the result of applying the hypothesis metafunction. (Later below we
will describe the second type, an extended syntaxp hypothesis,
which may use [state].)
We illustrate the use of simple syntaxp hypotheses by slightly
elaborating the example given above. Consider a :[rewrite] rule:
(IMPLIES (AND (RATIONALP X)
(SYNTAXP (NOT (AND (CONSP X)
(EQ (CAR X) 'NORM)))))
(EQUAL (LXD X)
(LXD (NORM X))))
How is this rule applied to (lxd (trn a b))? First, we form a
substitution that instantiates the left-hand side of the conclusion
of the rule so that it is identical to the target term. In the
present case, the substitution replaces x with (trn a b).
(LXD X) ==> (LXD (trn a b)).
Then we backchain to establish the hypotheses, in order. Ordinarily
this means that we instantiate each hypothesis with our
substitution and then attempt to rewrite the resulting instance to
true. Thus, in order to relieve the first hypothesis above, we
rewrite
(RATIONALP (trn a b)).
If this rewrites to true, we continue.
Of course, many users are aware of some exceptions to this general
description of the way we relieve hypotheses. For example, if a
hypothesis contains a ``free-variable'' --- one not bound by the
current substitution --- we attempt to extend the substitution by
searching for an instance of the hypothesis among known truths. See
[free-variables]. [Force]d hypotheses are another exception to the
general rule of how hypotheses are relieved.
Hypotheses marked with syntaxp, as in (syntaxp test), are also
exceptions. We instantiate such a hypothesis; but instead of
rewriting the instantiated instance, we evaluate the instantiated
test. More precisely, we evaluate test in an environment in which
its variable symbols are bound to the quotations of the terms to
which those variables are bound in the instantiating substitution.
So in the case in point, we (in essence) evaluate
(NOT (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))).
This clearly evaluates to t. When a syntaxp test evaluates to true,
we consider the syntaxp hypothesis to have been established; this
is sound because logically (syntaxp test) is t regardless of test.
If the test evaluates to nil (or fails to evaluate because of
[guard] violations) we act as though we cannot establish the
hypothesis and abandon the attempt to apply the rule; it is always
sound to give up.
The acute reader will have noticed something odd about the form
(NOT (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))).
When relieving the first hypothesis, (RATIONALP X), we substituted
(trn a b) for X; but when relieving the second hypothesis, (SYNTAXP
(NOT (AND (CONSP X) (EQ (CAR X) 'NORM)))), we substituted the
quotation of (trn a b) for X. Why the difference? Remember that in
the first hypothesis we are talking about the value of (trn a b)
--- is it rational --- while in the second one we are talking about
its syntactic form. Remember also that Lisp, and hence ACL2,
evaluates the arguments to a function before applying the function
to the resulting values. Thus, we are asking ``Is the list (trn a
b) a [consp] and if so, is its [car] the symbol NORM?'' The quotes
on both (trn a b) and NORM are therefore necessary. One can verify
this by defining trn to be, say [cons], and then evaluating forms
such as
(AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))
(AND (CONSP (trn a b)) (EQ (CAR (trn a b)) NORM))
(AND (CONSP (trn 'a 'b)) (EQ (CAR (trn 'a 'b)) NORM))
(AND (CONSP '(trn a b)) (EQ '(CAR (trn a b)) ''NORM))
at the top-level ACL2 prompt.
See [syntaxp-examples] for more examples of the use of syntaxp.
An extended syntaxp hypothesis is similar to the simple type
described above, but it uses two additional variables, mfc and
state, which must not be bound by the left hand side or an earlier
hypothesis of the rule. They must be the last two variables
mentioned by form; first mfc, then state. These two variables give
access to the functions mfc-xxx; see [extended-metafunctions]. As
described there, mfc is bound to the so-called metafunction-context
and state to ACL2's [state]. See [syntaxp-examples] for an example
of the use of these extended syntaxp hypotheses.
We conclude with an example illustrating an error that may occur if
you forget that a syntaxp hypothesis will be evaluated in an
environment where variables are bound to syntactic terms, not to
values. Consider the following [stobj] introduction (see
[defstobj]).
(defstobj st
(fld1 :type (signed-byte 3) :initially 0)
fld2)
The following syntaxp hypothesis is ill-formed for evaluation.
Indeed, ACL2 causes an error because it anticipates that when
trying to relieve the syntaxp hypothesis of this rule, ACL2 would
be evaluating (fld1 st) where st is bound to a term, not to an
actual stobj as required by the function fld1. The error message is
intended to explain this problem.
ACL2 !>(defthm bad
(implies (syntaxp (quotep (fld1 st)))
(equal (stp st)
(and (true-listp st)
(equal (len st) 2)
(fld1p (car st))))))
ACL2 Error in ( DEFTHM BAD ...): The form (QUOTEP (FLD1 ST)), from
a SYNTAXP hypothesis, is not suitable for evaluation in an environment
where its variables are bound to terms. See :DOC SYNTAXP. Here is
further explanation:
The form ST is being used, as an argument to a call of FLD1, where
the single-threaded object of that name is required. But in the current
context, the only declared stobj name is STATE. Note: this error
occurred in the context (FLD1 ST).
Summary
Form: ( DEFTHM BAD ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
ACL2 Error in ( DEFTHM BAD ...): See :DOC failure.
******** FAILED ********
ACL2 !>
Presumably the intention was to rewrite the term (stp st) when the
fld1 component of st is seen to be an explicit constant. As
explained elsewhere (see [free-variables]), we can obtain the
result of rewriting (fld1 st) by binding a fresh variable to that
term using EQUAL, as follows.
(defthm good
(implies (and (equal f (fld1 st))
(syntaxp (quotep f)))
(equal (stp st)
(and (true-listp st)
(equal (len st) 2)
(fld1p (car st))))))
The event above is admitted by ACL2. We can see it in action by
disabling the definition of stp so that only the rule above, good,
is available for reasoning about stp.
(in-theory (disable stp))
Then the proof fails for the following, because the syntaxp
hypothesis of the rule, good, fails: (quotep f) evaluates to nil
when f is bound to the term (fld1 st).
(thm (stp st))
However, the proof succeeds for the next form, as we explain below.
(thm (stp (list 3 rest)))
Consider what happens in that case when rule good is applied to the
term (stp (list 3 rest)). (See [free-variables] for relevant
background.) The first hypothesis of good binds the variable f to
the result of rewriting (fld1 st), where st is bound to the
(internal form of) the term (list 3 rest) --- and that result is
clearly the term, '3. Then the syntaxp hypothesis is successfully
relieved, because the evaluation of (quotep f) returns t in the
environment that binds f to '3.
Subtopics
[Syntaxp-examples]
Examples pertaining to syntaxp hypotheses")
(SYNTAXP-EXAMPLES
(SYNTAXP)
"Examples pertaining to syntaxp hypotheses
See [syntaxp] for a basic discussion of the use of syntaxp to control
rewriting.
A common syntactic restriction is
(SYNTAXP (AND (CONSP X) (EQ (CAR X) 'QUOTE)))
or, equivalently,
(SYNTAXP (QUOTEP X)).
A rule with such a hypothesis can be applied only if x is bound to a
specific constant. Thus, if x is 23 (which is actually represented
internally as (quote 23)), the test evaluates to t; but if x prints
as (+ 11 12) then the test evaluates to nil (because (car x) is the
symbol [binary-+]). We see the use of this restriction in the rule
(implies (and (syntaxp (quotep c))
(syntaxp (quotep d)))
(equal (+ c d x)
(+ (+ c d) x))).
If c and d are constants, then the [executable-counterpart] of
[binary-+] will evaluate the sum of c and d. For instance, under
the influence of this rule
(+ 11 12 foo)
rewrites to
(+ (+ 11 12) foo)
which in turn rewrites to (+ 23 foo). Without the syntactic
restriction, this rule would loop with the built-in rules
ASSOCIATIVITY-OF-+ or COMMUTATIVITY-OF-+.
We here recommend that the reader try the affects of entering
expressions such as the following at the top level ACL2 prompt.
(+ 11 23)
(+ '11 23)
(+ '11 '23)
(+ ''11 ''23)
:trans (+ 11 23)
:trans (+ '11 23)
:trans (+ ''11 23)
:trans (+ c d x)
:trans (+ (+ c d) x)
We also recommend that the reader verify our claim above about
looping by trying the affect of each of the following rules
individually.
(defthm good
(implies (and (syntaxp (quotep c))
(syntaxp (quotep d)))
(equal (+ c d x)
(+ (+ c d) x))))
(defthm bad
(implies (and (acl2-numberp c)
(acl2-numberp d))
(equal (+ c d x)
(+ (+ c d) x))))
on (the false) theorems:
(thm
(equal (+ 11 12 x) y))
(thm
(implies (and (acl2-numberp c)
(acl2-numberp d)
(acl2-numberp x))
(equal (+ c d x) y))).
One can use :[brr], perhaps in conjunction with [cw-gstack], to
investigate any looping.
Here is a simple example showing the value of rule good above.
Without good, the thm form below fails.
(defstub foo (x) t)
(thm (equal (foo (+ 3 4 x)) (foo (+ 7 x))))
The next three examples further explore the use of quote in [syntaxp]
hypotheses.
We continue the examples of [syntaxp] hypotheses with a rule from
community book books/finite-set-theory/set-theory.lisp. We will not
discuss here the meaning of this rule, but it is necessary to point
out that (ur-elementp nil) is true in this book.
(defthm scons-nil
(implies (and (syntaxp (not (equal a ''nil)))
(ur-elementp a))
(= (scons e a)
(scons e nil)))).
Here also, [syntaxp] is used to prevent looping. Without the
restriction, (scons e nil) would be rewritten to itself since
(ur-elementp nil) is true.
Question: Why the use of two quotes in ''nil?
Hints: Nil is a constant just as 23 is. Try :trans (cons a nil),
:trans (cons 'a 'nil), and :trans (cons ''a ''nil). Also, don't
forget that the arguments to a function are evaluated before the
function is applied.
The next two rules move negative constants to the other side of an
inequality.
(defthm |(< (+ (- c) x) y)|
(implies (and (syntaxp (quotep c))
(syntaxp (< (cadr c) 0))
(acl2-numberp y))
(equal (< (+ c x) y)
(< (fix x) (+ (- c) y)))))
(defthm |(< y (+ (- c) x))|
(implies (and (syntaxp (quotep c))
(syntaxp (< (cadr c) 0))
(acl2-numberp y))
(equal (< y (+ c x))
(< (+ (- c) y) (fix x)))))
Questions: What would happen if (< (cadr c) '0) were used? What about
(< (cadr c) ''0)?
One can also use syntaxp to restrict the application of a rule to a
particular set of variable bindings as in the following taken from
the [ihs] library.
(encapsulate ()
(local
(defthm floor-+-crock
(implies
(and (real/rationalp x)
(real/rationalp y)
(real/rationalp z)
(syntaxp (and (eq x 'x) (eq y 'y) (eq z 'z))))
(equal (floor (+ x y) z)
(floor (+ (+ (mod x z) (mod y z))
(* (+ (floor x z) (floor y z)) z)) z)))))
(defthm floor-+
(implies
(and (force (real/rationalp x))
(force (real/rationalp y))
(force (real/rationalp z))
(force (not (equal z 0))))
(equal (floor (+ x y) z)
(+ (floor (+ (mod x z) (mod y z)) z)
(+ (floor x z) (floor y z))))))
)
We recommend the use of :brr to investigate the use of floor-+-crock.
Another useful restriction is defined by
(defun rewriting-goal-literal (x mfc state)
;; Are we rewriting a top-level goal literal, rather than rewriting
;; to establish a hypothesis from a rewrite (or other) rule?
(declare (ignore x state))
(null (access metafunction-context mfc :ancestors))).
We use this restriction in the rule
(defthm |(< (* x y) 0)|
(implies (and (syntaxp (rewriting-goal-literal x mfc state))
(rationalp x)
(rationalp y))
(equal (< (* x y) 0)
(cond ((equal x 0)
nil)
((equal y 0)
nil)
((< x 0)
(< 0 y))
((< 0 x)
(< y 0))))))
which has been found to be useful, but which also leads to excessive
thrashing in the linear arithmetic package if used
indiscriminately.
See [extended-metafunctions] for information on the use of mfc and
metafunction-context.")
(SYS-CALL
(INTERFACING-TOOLS ACL2-BUILT-INS)
"Make a system call to the host operating system
Example Forms:
(sys-call \"cp\" '(\"foo.lisp\" \"foo-copied.lisp\"))
(prog2$ (sys-call \"cp\" '(\"foo.lisp\" \"foo-copied.lisp\"))
(sys-call-status state))
The first argument of sys-call is a command for the host operating
system, and the second argument is a list of strings that are the
arguments for that command. In GCL and perhaps some other lisps,
you can put the arguments with the command; but this is not the
case, for example, in Allegro CL running on Linux.
For a related utility, see [sys-call+].
The use of [prog2$] above is optional, but illustrates a typical sort
of use when one wishes to get the return status. See
[sys-call-status].
General Form:
(sys-call cmd args)
This function logically returns nil. However, it makes the indicated
call to the host operating system, as described above, using a
function supplied ``under the hood'' by the underlying Lisp system.
On occasions where one wishes to obtain the numeric status returned
by the host operating system (or more precisely, by the Lisp
function under the hood that passes the system call to the host
operating system), one may do so; see [sys-call-status]. The status
value is the value returned by that Lisp function, which may well
be the same numeric value returned by the host operating system for
the underlying system call.
Note that sys-call does not touch the ACL2 [state]; however,
[sys-call-status] updates the acl2-oracle field of the state.
Be careful if you use sys-call! It can be used for example to
overwrite files, or worse! We view a use of sys-call as a call to
the operating system that is made outside ACL2. The following
example from Bob Boyer shows how to use sys-call to execute, in
effect, arbitrary Lisp forms. ACL2 provides a ``trust tag''
mechanism that requires execution of a [defttag] form before you
can use sys-call; see [defttag]. (Note: The setting of the raw Lisp
variable *features* below is just to illustrate that any such
mischief is possible. Normally *features* is a list with more than
a few elements.)
% cat foo
print *0x85d2064=0x838E920
detach
q
% acl2
... boilerplate deleted
ACL2 !>(sys-call \"gdb -p $PPID -w < foo >& /dev/null \" nil)
NIL
ACL2 !>:q
Exiting the ACL2 read-eval-print loop. To re-enter, execute (LP).
ACL2>*features*
(:AKCL-SET-MV)
ACL2>
Finally, we note that sys-call does not provide some features that
one may expect of a shell. In particular, sys-call does not
generally support shell expansion of its arguments (such as ~/). It
also does not directly support output redirection. If you want to
run a program, P, and redirect its output, one option is to create
a wrapper script, W to call instead. Thus W might be a shell script
containing the line:
P $* >& foo.out
For a different, more direct solution, see [sys-call+].
Subtopics
[Sys-call+]
Make a system call to the host OS, returning status and output
[Sys-call-status]
Exit status from the preceding system call")
(SYS-CALL+
(SYS-CALL ACL2-BUILT-INS)
"Make a system call to the host OS, returning status and output
Example Form:
; The following returns (mv nil s state), where s is the standard output
; from the command: ls -l ./
(sys-call+ \"ls\" '(\"-l\" \"./\") state)
General Form:
(sys-call+ cmd args state)
where cmd is a command to the host operating system and args is a
list of strings. Also see [sys-call]; but there are two differences
between [sys-call] and sys-call+. First, the latter takes an extra
argument, state. Second, while sys-call returns nil, sys-call+
returns an [error-triple], (mv erp val state). While execution
returns values as described just below, further below we explain
the logical return values. In the following, please keep in mind
that the exact behavior depends on the platform; the description is
only a guide. For example, on some platforms erp might always be
nil, even if in the error case, and val might or might not include
error output. (For details, look at the ACL2 source code for
function system-call+, whose output is converted by replacing an
erp of nil by 0.)
Erp is either nil or a non-zero integer. Normally, nil indicates that
the command ran without error, and otherwise erp is the exit
status.
Val is a string, typically the output generated by the call of cmd.
State is an ACL2 [state].
While the description above pertains to the values returned by
executing sys-call+, the logical values are as follows. For a
discussion of the acl2-oracle field of an ACL2 state, see
[read-ACL2-oracle] and [state].
Erp is the first element of the acl2-oracle of the input state if
that element is a nonzero integer, and otherwise is nil.
Val is the second element of the acl2-oracle of the input state if it
is a string, else the empty string, \"\".
State is the result of popping the acl2-oracle field twice from the
input state.
Note that unlike [sys-call], a call of [sys-call+] has no effect on
subsequent calls of [sys-call-status].
As is the case for sys-call, a trust tag is required to call
sys-call+. For discussion of this and more, see [sys-call].")
(SYS-CALL-STATUS
(SYS-CALL ACL2-BUILT-INS)
"Exit status from the preceding system call
This function returns two values, (mv status state). The first is the
status resulting from the most recent invocation of function
sys-call; see [sys-call]. The second is the ACL2 [state] object,
which is also the input to this function.
The function [sys-call] makes a system call to the host operating
system using a function supplied ``under the hood'' by the
underlying Lisp system. The status value is the value returned by
that Lisp function, which may well be the numeric value returned by
the host operating system for the underlying system call. For more
information, see [sys-call].")
(SYSTEM-UTILITIES
(PROGRAMMING)
"List of system-level programming utilities
Since the ACL2 system is written in itself, the source code defines
many utilities that support the ACL2 implementation. Some of these
have been found to be useful not only to the ACL2 developers, but
to those who use ACL2 to perform tasks other than the traditional
ones: writing and submitting definitions, and proving theorems
about the functions defined.
This topic provides a summary, initially very short, of some of those
system-level utilities. It is intended to be a growing document,
with contributions from those in the community who find such
utilities that benefit them. Although the ACL2 implementors have
created this topic initially, we expect that others will add to it
over time.
The ACL2 system comes with substantial comments. As of Version_7.1
(May, 2015), out of slightly under 10 MB of source code (not
including 4.8 MB of [documentation] topics), nearly 400 KB (just
over 40%) were comment lines. This topic is not intended to
supplant or duplicate those comments, but rather, only to note
system utilities of interest to the community. If you find the
source comments inadquate, please feel free to ask the system
implementors to make corresponding additions to the source code
comments. Note that if you execute the command
grep '^; Essay on' *.lisp
in your ACL2 sources directory, you will see the names of more than
80 long source comments, or ``Essays'', that can provide additional
background.
Also see [programming] and its subtopics, in particular
[programming-with-state], which describes many system-level
utilities. For example, a subsection of [programming-with-state],
entitled ``SEQUENTIAL PROGRAMMING'', introduces handy utilities
[pprogn] and [er-progn] along with links to their documentation.
Here is another option for finding a system utility: As ACL2
developers sometimes do, use meta-. or meta-x tags-apropos in Emacs
to find utilities with given substrings in their names. For
example, if in Emacs you submit the command meta-x tags-apropos and
reply pwd at the prompt, you'll find a raw Lisp function our-pwd
that ACL2 defines as an analogue to the Linux pwd command; and,
with meta-x tags-search applied to (pwd, you can see how ACL2
source code uses this utility.
List of a few ACL2 system utilities:
* (alist-to-doublets alist): Return the result of replacing each pair
(x . y) in the given alist by the two-element list (x y). The
order is preserved, i.e., the following is a theorem.
(implies (and (natp i) (< i (len alist)))
(equal (nth i (alist-to-doublets alist))
(let ((pair (nth i alist)))
(list (car pair) (cdr pair)))))
* (all-vars x): For a [pseudo-termp] x, return the list of variables in
x in reverse print order of first occurrence. For example,
all-vars of '(f (g a b) c) is '(c b a).
* (arity fn w): For a function symbol or lambda expression fn of
[world] w, return the number of its formal parameters.
* (body fn normalp w): For a function symbol or lambda expression fn of
[world] w, return its body (normalized iff normalp is true).
* (cons-count-bounded x): The number of cons nodes in x (without
accounting for sharing), but truncated above by the value of
(fn-count-evg-max-val), which is 200,000 as of this writing.
* (defined-constant name w): If name is t, nil, or defined using
[defconst], return the quoted term that is the value of name,
which is not nil; otherwise return nil.
* (defun-mode fn): If fn is a function symbol, return the [defun-mode]
of fn: :program if fn is in :[program] mode, :logic if fn is in
:[logic] mode. If fn is not a function symbol, return nil.
* (disabledp name): The list of [rune]s introduced with name that are
currently [disable]d.
* (fargn x n): For a [pseudo-termp] x that is a function call and for a
positive integer n, return the n-nth argument of x.
* (fargs x): For a [pseudo-termp] x that is a function call, return its
arguments.
* (fdefun-mode fn): For a function symbol fn, return the [defun-mode]
of fn: :program if fn is in :[program] mode, :logic if fn is in
:[logic] mode.
* (ffn-symb x): For a [pseudo-termp] x that is a function call, return
its called function or lambda expression.
* (ffn-symb-p x sym): For a [pseudo-termp] x, return t if it is a
function call whose function symbol is sym, else return nil.
* (flambda-applicationp x): For a [pseudo-termp] x that is not a
variable, return t if it is a function call whose function
symbol is a lambda expression, else return nil.
* (flambdap fn): True when fn is a lambda expression.
* (fn-symb x): For a [pseudo-termp] x, return its called function or
lambda expression if x is a function call, otherwise return
nil.
* (formals fn w): For a function symbol fn of [world] w, return its
list of formal parameters.
* (formula name normalp w): For an event name or [rune], name, of
[world] w, return the corresponding formula if any (normalized
iff normalp is true), else nil. See [formula].
* (fquotep x): For a [pseudo-termp] x that is not a variable, return
true iff x is a quoted constant.
* (function-symbolp sym w): True when the symbol sym is a function
symbol in the [world] w.
* (genvar pkg-witness prefix n avoid-lst): Generate a new variable
name.
* (get-brr-local var state): The value of brr-local variable var; this
is the utility used by [brr@].
* (get-event name w): For the given name of an event in the current
ACL2 [world] w, return that event.
* (get-skipped-proofs-p name w): For the given name of an event in the
current ACL2 [world] w, return t if proofs were skipped when
introducing that event, as with [skip-proofs] or using
[set-ld-skip-proofsp] --- that is, with proofs skipped other
than by the system (as with [include-book]); else return nil.
Exception: if name is a function symbol in :[program] mode,
always return nil.
* (guard fn stobj-optp w): For a function symbol or lambda expression
fn of [world] w, return its [guard]. Optimize the [stobj]
recognizers away iff stobj-optp is true.
* (lambda-applicationp x): For a [pseudo-termp] x, return t if it is a
function call whose function symbol is a lambda expression,
else return nil.
* (lambda-body x): For a lambda expression x, return its body.
* (lambda-formals x): For a lambda expression x, return its formal
parameters.
* (logicalp fn w): Returns t when the symbol-class of fn in w is not
:program, else nil. (See symbol-class, below.)
* (make-lambda args body): Return lambda expression with formal
parameters args and body body.
* (merge-sort-lexorder l): Sort the list l using a non-strict total
order, [lexorder], on the ACL2 universe.
* (nvariablep x): For a [pseudo-termp] x, return true iff x is not a
variable (i.e. it is a quoted constant or a function call).
* (plist-worldp alist): Recognizer for when alist is syntactically
well-formed as an ACL2 logical [world], sometimes suitable for
use in [guard]s. Note: for a somewhat deeper check, see
community book books/system/pseudo-good-worldp.lisp.
* (prettyify-clause cl let*-abstractionp wrld): Returns an untranslated
(user-level) term that is equivalent to the clause, cl.
* (programp fn w): Returns t when the symbol-class of fn in w is
:program, else nil. (See symbol-class, below.)
* (quotep x): For a [pseudo-termp] x, return true iff x is a quoted
constant.
* (recursivep fn w): For a function symbol fn of [world] w, return the
list of mutually recursive functions of which fn is a member.
The list is empty iff fn is not recursive. The list contains
just fn iff fn is singly recursive.
* (subcor-var vars terms form): For a list vars of symbols, a list
terms of [pseudo-termp]s, and a [pseudo-termp] form,
substitute, in form, the i-th variable from vars with the i-th
term from terms. Note that vars and terms should have the same
length. (\"subcor\" stands for \"substitute corresponding
elements\".)
* (sublis-var alist form): Substitute alist into the [term], form.
* (subst-expr new old term): Substitute new for old in term; all are
assumed to be [term]s.
* (subst-var new old term): Substitute new for old in term; all are
assumed to be [term]s, but moreover, old is assumed to be a
variable.
* (symbol-class name w): For a function symbol, name, of the ACL2
[world] w, return :program if name is in :[program] mode,
:common-lisp-compliant is name is [guard]-verified, and
otherwise, :ideal. If name is the name of a theorem (more
specifically, has a 'theorem property; see [getprop]), return
:ideal. Otherwise return :program.
* (termp x w): Is x a [term] in logical [world] w?
* (trans-eval form ctx state aok): Translate and then evaluate form.
Also see simple-translate-and-eval-cmp.
* translate, translate1, translate11, translate-cmp, and
translate1-cmp: Functions that translate user-level input to
translated [term]s, as recognized by termp.
* (untranslate term iff-flg w): Turn the translated [pseudo-termp] term
into a user-level input [term], in the context of the logical
world w. When the flag iff-flg is true, the resulting term is
allowed to be iff-equivalent, e.g., (if x1 t x2) can be
untranslated to (or x1 x2).
* (variablep x): For a [pseudo-termp] x, return true iff x is a
variable, i.e., a symbol.
Subtopics
[Get-event-data]
Obtain data stored after at the conclusion of an event")
(TABLE
(EVENTS)
"User-managed tables
Examples:
(table tests 1 '(...)) ; set contents of tests[1] to '(...)
(table tests 25) ; get contents of tests[25]
(table tests) ; return table tests as an alist
(table tests nil nil :clear) ; clear table tests
(table tests nil '((foo . 7)) :clear) ; set table tests to ((foo . 7))
(table tests nil nil :guard) ; fetch the table guard
(table tests nil nil :guard term) ; set the table guard
General Form:
(table table-name key-term value-term op term)
where table-name is a symbol that is the name of a (possibly new)
table, key-term and value-term, if present, are arbitrary terms
involving (at most) the single variable [world], op, if present, is
one of the table operations below, and term, if present, is a term.
Table returns an ACL2 [error-triple]. The effect of table on
[state] depends on op and how many arguments are presented. Some
invocations actually have no effect on the ACL2 [world] and hence
an invocation of table is not always an ``event''. We explain
below, after giving some background information.
Important Note: The table forms above are calls of a macro that
expand to involve the special variable [state]. This will prevent
you from accessing a table from within a hint or theory where you
do not have the [state] variable. However, the form
(table-alist 'tests world)
returns the alist representation of the table named test in the given
world. Often you have access to world.
The ACL2 system provides ``tables'' by which the user can associate
one object with another. Tables are in essence just conventional
association lists --- lists of pairs --- but the ACL2 environment
provides a means of storing these lists in the ``ACL2 world'' of
the current [state]. The ACL2 user could accomplish the same ends
by using ACL2 ``global variables;'' however, limitations on global
variable names are imposed to ensure ACL2's soundness. Some
features of the system use tables, and the user is invited to make
free use of tables. By convention, no user-defined table is
important to ACL2's soundness. Because tables are stored in the
ACL2 [world] they are restored by [include-book] and undone by
:[ubt]. Many users of Nqthm requested a facility by which user data
could be saved in Nqthm ``lib files'' and tables are ACL2's answer
to that request.
Abstractly, each table is an association list mapping ``keys'' to
``values.'' In addition, each table has a ``:guard,'' which is a
term that must be true of any key and value used. By setting the
:guard on a table you may enforce an invariant on the objects in
the table, e.g., that all keys are positive integers and all values
are symbols. Each table has a ``name,'' which must be a symbol.
Given a table name, the following operations can be performed on
the table.
:put --- associate a value with a key (possibly changing the value
currently associated with that key).
:get --- retrieve the value associated with a key (or nil if no value
has been associated with that key).
:alist --- return an alist showing all keys and non-nil values in the
table.
:clear --- clear the table (so that every value is nil), or if val is
supplied then set table to that value (which must be an alist).
:guard --- fetch or set the :guard of the table.
When the operations above suggest that the table or its :guard are
modified, what is actually meant is that the current [state] is
redefined so that in it, the affected table name has the
appropriate properties. in such cases, the table form is an event
(see [events]). In the :put case, if the key is already in the
table and associated with the proposed value, then the table event
is redundant (see [redundant-events]).
Table forms are commonly typed by the user while interacting with the
system. :Put and :get forms are especially common. Therefore, we
have adopted a positional syntax that is intended to be convenient
for most applications. Essentially, some operations admit a ``short
form'' of invocation.
(table name key-term value-term :put) ; long form
(table name key-term value-term) ; short form
evaluates the key- and value-terms, obtaining two objects that we
call key and value, checks that the key and value satisfy the
:guard on the named table and then ``modifies'' the named table so
that the value associated with key is value. When used like this,
table is actually an event in the sense that it changes the ACL2
[world]. In general, the forms evaluated to obtain the key and
value may involve the variable [world], which is bound to the
then-current [world] during the evaluation of the forms. However,
in the special case that the table in question is named
[ACL2-defaults-table], the key and value terms may not contain any
variables. Essentially, the keys and values used in [events]
setting the [ACL2-defaults-table] must be explicitly given
constants. See [ACL2-defaults-table].
(table name key-term nil :get) ; long form
(table name key-term) ; short form
evaluates the key-term (see note below), obtaining an object, key,
and returns the value associated with key in the named table (or,
nil if there is no value associated with key). When used like this,
table is not an event; the value is simply returned.
(table name nil nil :alist) ; long form
(table name) ; short form
returns an alist representing the named table; for every key in the
table with a non-nil associated value, the alist pairs the key and
its value. The order in which the keys are presented is
unspecified. When used like this, table is not an event; the alist
is simply returned.
(table name nil val :clear)
sets the named table to the alist val, making the checks that :put
makes for each key and value of val. When used like this, table is
an event because it changes the ACL2 [world].
(table name nil nil :guard)
returns the translated form of the guard of the named table.
(table name nil nil :guard term)
Provided the named table is empty and has not yet been assigned a
:guard and term (which is not evaluated) is a term that mentions at
most the variables key, val and [world], this event sets the :guard
of the named table to term. Whenever a subsequent :put occurs, term
will be evaluated with key bound to the key argument of the :put,
val bound to the val argument of the :put, and [world] bound to the
then current [world]. An error will be caused by the :put if the
result of the evaluation is nil.
Note that it is not allowed to change the :guard on a table once it
has been explicitly set. Before the :guard is explicitly set, it is
effectively just t. After it is set it can be changed only by
undoing the event that set it. The purpose of this restriction is
to prevent the user from changing the :guards on tables provided by
other people or the system.
The intuition behind the :guard mechanism on tables is to enforce
invariants on the keys and values in a table, so that the values,
say, can be used without run-time checking. But if the :guard of a
table is sensitive to the ACL2 [world], it may be possible to cause
some value in the table to cease satisfying the :guard without
doing any operations on the table. Consider for example the :guard
``no value in this table is the name of an event.'' As described,
that is enforced each time a value is stored. Thus, 'bang can be
:put in the table provided there is no event named bang. But once
it is in the table, there is nothing to prevent the user from
defining bang as a function, causing the table to contain a value
that could not be :put there anymore. Observe that not all
state-sensitive :guards suffer this problem. The :guard ``every
value is an event name'' remains invariant, courtesy of the fact
that undoing back through an event name in the table would
necessarily undo the :put of the name into the table.
Table was designed primarily for convenient top-level use. Tables are
not especially efficient. Each table is represented by an alist
stored on the property list of the table name. :Get is just a
getprop and [assoc-equal]. :Put does a getprop to the get the table
alist, a put-assoc-equal to record the new association, and a
putprop to store the new table alist --- plus the overhead
associated with :guards and undoable [events], and checking (for
redundancy) if the key is already bound to its proposed value. Note
that there are never duplicate keys in the resulting alist; in
particular, when the operation :clear is used to install new alist,
duplicate keys are removed from that alist.
A table name may be any symbol whatsoever. Symbols already in use as
function or theorem names, for example, may be used as table names.
Symbols in use only as table names may be defined with [defun],
etc. Because there are no restrictions on the user's choice of
table names, table names are not included among the logical names.
Thus, :pe name will never display a table event (for a logical name
other than :here). Either :pe name will display a ``normal'' event
such as (defun name ...) or (defthm name ...) or else :pe name will
cause an error indicating that name is not a logical name. This
happens even if name is in use as a table name.
Subtopics
[ACL2-defaults-table]
A [table] specifying certain defaults, e.g., the default
[defun-mode]
[Using-tables-efficiently]
Notes on how to use tables efficiently")
(TAKE
(LISTS ACL2-BUILT-INS)
"Initial segment (first n elements) of a list
For any natural number n not exceeding the length of l, (take n l)
collects the first n elements of the list l.
The following is a theorem (though it takes some effort, including
lemmas, to get ACL2 to prove it):
(equal (length (take n l)) (nfix n))
If n is an integer greater than the length of l, then take pads the
list with the appropriate number of nil elements. Thus, the
following is also a theorem.
(implies (and (integerp n)
(true-listp l)
(<= (length l) n))
(equal (take n l)
(append l (make-list (- n (length l))))))
For related functions, see [nthcdr] and see [butlast].
The [guard] for (take n l) is that n is a nonnegative integer and l
is a true list.
Function: <take>
(defun take (n l)
(declare (xargs :guard (and (integerp n)
(not (< n 0))
(true-listp l))))
(first-n-ac n l nil))")
(TAU-DATA
(TAU-SYSTEM)
"To see what tau knows about a function symbol
Examples:
(tau-data binary-+)
General Form:
(tau-data fn)
This macro returns a list structure that indicates what facts about
the symbol fn are known to the tau system. Fn should either be a
function symbol or else a macro associated with fn; see
[macro-aliases-table]. See [introduction-to-the-tau-system] for
background details.
The list structure should be self-explanatory given the following
brief comments. The ``index'' of a function, when non-nil, means
the function is a monadic Boolean function treated by the tau
system as a tau predicate.
The ``positive'' and ``negative implicants'' are conjunctions that
indicate the tau implied by the given one or its negation.
The ``signatures'' entry is a formula indicating all the known
signatures. If the signatures formula is T it means there are no
known signatures. (Signatures is the conjunction of all signature
rules and the empty conjunction is T.)
If you wish to see a long list of all the runes from which some tau
information has been gleaned, evaluate (global-val 'tau-runes (w
state)).")
(TAU-DATABASE
(TAU-SYSTEM HISTORY)
"To see the tau database as a (very large) object
Example:
(tau-database (w state))
This function returns a large list object that shows in a
human-readable way what the tau system knows about every function
symbol. It is supposed to be self-explanatory. See
[introduction-to-the-tau-system] for background details.
If the output is not self-explanatory, please contact the
implementors and we will improve the output or the documentation.")
(TAU-INTERVAL-DOM
(TAU-SYSTEM)
"Access the domain of a tau interval
It is the case that
(tau-interval-dom (make-tau-interval dom lo-rel lo hi-rel hi)) = dom
For a well-formed interval, dom is one of the symbols INTEGERP,
RATIONALP, ACL2-NUMBERP, or NIL. When the domain is NIL there is no
domain restriction.
When the domain is INTEGERP, there are additional constraints on the
other components. See [make-tau-interval].")
(TAU-INTERVAL-HI
(TAU-SYSTEM)
"Access the upper bound of a tau interval
It is the case that
(tau-interval-hi (make-tau-interval dom lo-rel lo hi-rel hi)) = hi
For a well-formed interval, hi is either nil, denoting positive
infinity, or a rational number giving the upper bound of the
interval. It must be the case that the upper bound is weakly above
the lower bound of a well-formed interval.
When the domain of an interval is INTEGERP, there are additional
constraints on the other components. See [make-tau-interval].")
(TAU-INTERVAL-HI-REL
(TAU-SYSTEM)
"Access the upper bound relation of a tau interval
It is the case that
(tau-interval-hi-rel (make-tau-interval dom lo-rel lo hi-rel hi)) = hi-rel
For a well-formed interval, hi-rel is a Boolean, where t denotes the
[<] (strong inequality or ``less-than'') relation and nil denotes
[<=] (weak inequality or ``less-than-or-equal'') relation between
the elements of the interval and the upper bound.
When the domain of an interval is INTEGERP, there are additional
constraints on the other components. See [make-tau-interval].")
(TAU-INTERVAL-LO
(TAU-SYSTEM)
"Access the lower bound of a tau interval
It is the case that
(tau-interval-lo (make-tau-interval dom lo-rel lo hi-rel hi)) = lo
For a well-formed interval, lo is either nil, denoting negative
infinity, or a rational number giving the lower bound of the
interval. It must be the case that the lower bound is weakly below
the upper bound of a well-formed interval.
When the domain of an interval is INTEGERP, there are additional
constraints on the other components. See [make-tau-interval].")
(TAU-INTERVAL-LO-REL
(TAU-SYSTEM)
"Access the lower bound relation of a tau interval
It is the case that
(tau-interval-lo-rel (make-tau-interval dom lo-rel lo hi-rel hi)) = lo-rel
For a well-formed interval, lo-rel is a Boolean, where t denotes the
[<] (strong inequality or ``less-than'') relation and nil denotes
[<=] (weak inequality or ``less-than-or-equal'') relation between
the lower bound and the elements of the interval.
When the domain of an interval is INTEGERP, there are additional
constraints on the other components. See [make-tau-interval].")
(TAU-INTERVALP
(TAU-SYSTEM)
"Boolean recognizer for tau intervals
General Form:
(tau-intervalp x)
An interval is a structure of the form: (dom (lo-rel . lo) . (hi-rel
. hi)). Every tau contains an interval used to represent the domain
and the upper and lower bounds of the objects recognized by the
tau.
Restrictions on the components of an interval are as follows. For an
interpretation of the meaning of the components, see
[in-tau-intervalp] or [make-tau-interval].
dom (``domain'') -- must be one of four symbols: INTEGERP, RATIONALP,
ACL2-NUMBERP, or NIL.
The two ``relations,'' lo-rel and hi-rel, must be Booleans.
Lo and hi must be either nil or explicit rational numbers. Lo must be
no greater than hi (where nils represent negative or positive
infinity for lo and hi respectively.
Finally, if the dom is INTEGERP, then both relations must nil and lo
and hi must be integers when they are non-nil.
Recall that [make-tau-interval] constructs intervals. The intervals
it constructs are well-formed only if the arguments to
make-tau-interval satisfy the rules above; make-tau-interval does
not coerce or adjust its arguments in any way. Thus, it can be
(mis-)used to create non-intervals. Here are examples of
tau-intervalp using make-tau-interval.
; integers: 0 <= x <= 10:
(tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil 10)) = t
; integers: 0 <= x (i.e., the natural numbers):
(tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil nil)) = t
; violations of domain rules:
(tau-intervalp (make-tau-interval 'INTEGERP t 0 t 10)) = nil
(tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil 10/11)) = nil
; violation of rule that bounds must be rational if non-nil:
(tau-intervalp (make-tau-interval 'ACL2-NUMBERP t 0 t #c(3 5))) = nil
; violation of rule that lo <= hi:
(tau-intervalp (make-tau-interval 'ACL2-NUMBERP t 0 t -10)) = nil
; rationals: 0 < x <= 22/7:
(tau-intervalp (make-tau-interval 'RATIONALP t 0 nil 22/7)) = t
; numbers: -10 < x < 10:
(tau-intervalp (make-tau-interval 'ACL2-NUMBERP t -10 t 10)) = t
; any: -10 < x < 10:
(tau-intervalp (make-tau-interval nil t -10 t 10)) = t
: any:
(tau-intervalp (make-tau-interval nil nil nil nil nil)) = t
Note that the second-to-last interval, with domain nil contains all
non-numbers as well as numbers strictly between -10 and 10. The
reason is that the interval contains 0 and all non-numbers are
coerced to 0 by the inequality functions.
Note that the last interval contains all ACL2 objects. It is called
the ``universal interval.''")
(TAU-STATUS
(TAU-SYSTEM)
"Query or set tau system status
Examples:
(tau-status)
(tau-status :system t)
(tau-status :auto-mode nil)
(tau-status :system t :auto-mode nil)
General Form:
(tau-status :system a :auto-mode b)
where a and b are Booleans. Both keyword arguments are optional and
they may be presented in either order. Value a controls whether the
[tau-system] is used during subsequent proofs. Value b controls
whether tau system rules are added automatically (``greedily'')
when rules of other [rule-classes] are added. If no arguments are
supplied, this is not an event and just returns an [error-triple]
indicating the current settings. See
[introduction-to-the-tau-system] for background details.
The two flags are independent. For example, the tau system may be
disabled in proof attempts even though it is automatically (and
silently) extending its database as rules of other classes are
added.
Flag (a) is actually toggled by enabling or disabling the
:[executable-counterpart] of [tau-system]. Flag (b) is toggled with
the function [set-tau-auto-mode], which manipulates the
[ACL2-defaults-table].
This macro expands into zero, one, or two [events], as required by
the supplied values of flags a and b.
If no arguments are supplied the form is not an event and simply
returns (as an [error-triple], (mv nil ans state)) the current
settings of the two flags. For example:
ACL2 !>(tau-system)
((:SYSTEM NIL) (:AUTO-MODE T))
intended to be self-explanatory.")
(TAU-SYSTEM
(RULE-CLASSES)
"Make a rule for the ACL2 ``type checker''
This documentation topic describes the syntactic form of
``tau-system'' rules; these rules extend ACL2's ``type checker.''
For an introduction to the tau system, see
[introduction-to-the-tau-system].
There happens to be a function named tau-system, defined as the
identity function. Its only role is to provide the rune
(:EXECUTABLE-COUNTERPART TAU-SYSTEM), which is used to enable and
disable the tau system. Otherwise the function tau-system has no
purpose and we recommend that you avoid using it so you are free to
enable and disable the tau system.
When in the default (``greedy'') mode (see [set-tau-auto-mode]),
every [defun] and every :corollary (see :[rule-classes]) of every
[defthm] stored as a rule of any :rule-class is inspected to
determine if it is of one of the forms below. Rules of these forms
are added to the tau database, even if they are not labeled as
:tau-system rules, e.g., a :[rewrite] rule might contribute to the
tau database! To add a rule to the tau database without adding any
other kind of rule, tag it with :[rule-classes] :tau-system. If a
theorem has :[rule-classes] nil, it is not considered for the tau
database.
General Forms:
Boolean:
(booleanp (p v))
Eval:
(p 'const) or
(p *const*)
Simple:
(implies (p v) (q v))
Conjunctive:
(implies (and (p1 v) ... (pk v)) (q v)), ; Here k must exceed 1.
Signature Form 1:
(implies (and (p1 x1) (p2 x2) ...)
(q (fn x1 x2 ...)))
Signature Form 2:
(implies (and (p1 x1) (p2 x2) ...)
(q (mv-nth 'n (fn x1 x2 ...))))
Bounder Form 1 (or Form 2):
(implies (and (tau-intervalp i1)
...
(or (equal (tau-interval-dom i1) 'dom1-1)
...)
...
(in-tau-intervalp x1 i1)
...)
(and (tau-intervalp (bounder-fn i1 ...))
(in-tau-intervalp target
(bounder-fn i1 ...))))
where target is
(fn x1 ... y1 ...) in Form 1, and
(mv-nth 'n (fn x1 ... y1 ...)) in Form 2
Big Switch:
(equal (fn . formals) body)
MV-NTH Synonym:
(equal (nth-alt x y) (mv-nth x y)) or
(equal (mv-nth x y) (nth-alt x y))
The symbols p, q, p1, etc., denote monadic (one-argument)
Boolean-valued function symbols, or equalities in which one
argument is constant, arithmetic comparisons in which one argument
is a rational or integer constant, or the logical negations of such
terms. By ``equalities'' we allow [equal], [eq], [eql], and [=]. By
``arithmetic comparison'' we mean [<], [<=], [>=], or [>]. Any of
these tau predicates may appear negated.
The notation (p v) above might stand for any one of:
(INTEGERP X)
(EQUAL V 'MONDAY)
(<= I 16)
(NOT (EQUAL X 'SUNDAY))
The different rule forms above affect different aspects of the tau
system. We discuss each form in more detail below.
The documentation below is written as though the tau system is in
auto mode! To insure that the only rules added to the tau system
are those explicitly assigned to :rule-class :tau-system, you
should use [set-tau-auto-mode] to select manual mode.
General Form: Boolean:
(booleanp (p v))
Here p must be a function symbol and v must be a variable. Such a
:tau-system rule adds p to the list of tau predicates. If p was
recognized as Boolean when it was defined, there is no need to
state this rule. This form is needed if you define a monadic
Boolean function in such a way that the system does not recognize
that it is Boolean.
General Form: Eval:
(p 'const) or
(p *const*)
Here p must be a function symbol. In addition, recall that these
general tau predicate forms may appear negated. So the form above
includes such theorems as (NOT (GOOD-STATEP *INITIAL-STATE*)). A
theorem of this form thus records whether a named predicate is true
or false on the given constant.
Generally, when the tau system must determine whether an enabled tau
predicate is true or false on a constant, it simply evaluates the
predicate on the constant. This can be impossible or very
inefficient if p is not defined but constrained, or if p is defined
in a hard-to-compute way (e.g., (defun p (x) (evenp (ack x x)))
where ack is the Ackermann function), or perhaps if the constant is
very large. By proving a :tau-system rule of Eval form, you cause
the tau system to note the value of the predicate on the constant
and henceforth to look it up instead of evaluating the definition.
A difficulty, however, is determining that a slow down is due to the
evaluation of tau predicates and not some other reason. The first
step is determining that tau is slowing the proof down. See
[time-tracker-tau] for an explanation of TIME-TRACKER-NOTEs output
during some proofs involving tau reasoning. These notes can alert
you to the fact that significant amounts of time are being spent in
the tau system. [Time-tracker-tau] gives some ways of determining
whether tau predicate evaluation is involved. (If worse comes to
worst, consider the following hack: In the ACL2 source file
tau.lisp, immediately after the definition of the system function
ev-fncall-w-tau-recog, there is a comment which contains some raw
Lisp code that can be used to investigate whether tau's use of
evaluation on constants is causing a problem.) However, once a
recognizer and the constants on which it is being evaluated are
identified, the tau system can be sped up by proving Eval rules to
pre-compute and store the values of the recognizer on those
constants. Alternatively, at the possible loss of some completeness
in the tau system, the executable counterpart of the recognizer can
be disabled.
General Form: Simple:
(implies (p v) (q v))
Here v must be a variable symbol. This rule builds-in the information
that anything satisfying p must also satisfy q, i.e., the ``type''
q includes the ``type'' p. Recall that the forms may be negated.
Most of the time, p and q will be predicate symbols but it is
possible they will be equalities- or inequalities-with-constants.
Examples of Simple rules include the following, which are in fact
built-in:
(implies (natp x) (integerp x))
(implies (integerp x) (rationalp x))
(implies (integerp x) (not (true-listp x)))
(implies (natp x) (not (< x 0)))
(implies (symbol-alistp x) (alistp x))
Because the tau system records the transitive closure of the Simple
rules, any time a term is known to satisfy natp it is also known to
satisfy integerp and rationalp, and known not to satisfy
true-listp, and known to be non-negative.
General Form: Conjunctive:
(implies (and (p1 v) ... (pk v)) (q v)), ; Here k must exceed 1.
The pi and q may be any tau predicates or their negations, v must be
a variable symbol, and i must exceed 1 or else this is a Simple
rule. An obvious operational interpretation of this rule is that if
an object is known to satisfy all of the pi, then it is known to
satisfy q. However, the actual interpretation is more general. For
example, if an object is known to satisfy all but one of the pi and
is known not to satisfy q, then the object is known not to satisfy
the ``missing'' pi.
For example, the following Conjunctive rule allows tau to conclude
that if weekday D is not MON, TUE, THU or FRI, then it is WED:
(implies (and (weekdayp d)
(not (eq d 'MON))
(not (eq d 'TUE))
(not (eq d 'WED))
(not (eq d 'THU)))
(eq d 'FRI))
The tau database is not closed under conjunctive rules; they are
applied dynamically.
General Form: Signature Form 1:
(implies (and (p1 x1) (p2 x2) ... (pn xn) dep-hyp)
(q (fn x1 x2 ... xn)))
The pi and q may be any tau predicates or their negations, fn must be
a function symbol of arity n, the xi must be distinct variable
symbols and dep-hyp may be any term, provided it is not of the (pi
xi) shape and the only the variables in it are the xi.
The Signature form actually allows multiple tau predicates to be
applied to each variable, e.g., x1 might be required to be both an
INTEGERP and EVENP. The Signature form allows there to be multiple
hypotheses classified as dep-hyps, i.e., not fitting any of the
previous shapes, and they are implicitly just conjoined. The name
``dep-hyp'' is an abbreviation of ``dependent hypothesis'' and
stems from the fact they often express relations between several of
the function's inputs rather than type-like constraints on
individual inputs.
A Signature rule informs tau that the function fn returns an object
satisfying q provided that the arguments satisfy the respective pi
and provided that dep-hyp occurs in the current context. Note: to
be precise, dependent hypotheses are relieved only by applying
ACL2's most primitive form of reasoning, [type-set]. In particular,
tau reasoning is not used to establish dependent hypotheses. The
presence of a dep-hyp in a signature rule may severely restrict its
applicability. We discuss this after showing a few mundane
examples.
An example Signature rule is
(implies (and (integer-listp x)
(integer-listp y))
(integer-listp (append x y)))
Of course, a function may have multiple signatures:
(implies (and (symbol-listp x)
(symbol-listp y))
(symbol-listp (append x y)))
Here is a Signature rule for the function pairlis$:
(implies (and (symbol-listp x)
(integer-listp y))
(symbol-alistp (pairlis$ x y)))
The tau system can consequently check this theorem by composing the
last two rules shown and exploiting Simple rule stating that
symbol-alists are also alists:
(thm (implies (and (symbol-listp a)
(symbol-listp b)
(integer-listp y))
(alistp (pairlis$ (append a b) y))))
Since a and b are known to be lists of symbols and a signature for
append is that it preserves that predicate, the first argument to
the pairlis$ expression is known to be a list of symbols. This
means the Signature rule for pairlis$ tells us the result is a
symbol-alistp, but the previously mentioned Simple rule, (implies
(symbol-alistp x) (alistp x)), tells us the result is also an
alistp.
When a Signature rule has an dep-hyp, that hypothesis is not an
expression in the tau system. Tau is not used to check that
hypothesis. Instead, tau uses the more primitive [type-set]
mechanism of ACL2. Here is an example of a Signature rule with a
dep-hyp:
(implies (and (natp n)
(integer-listp a)
(< n (len a)))
(integerp (nth n a)))
Note that the last hypothesis is a dependent hypothesis: it is not a
tau predicate but a relationship between n and a. It is relieved by
[type-set]. If one is trying to compute the signature of an (nth n
a) expression in a context in which (< n (len a)) is explicitly
assumed, then this mechanism would establish the dependent
hypothesis. But one can easily imagine an almost identical context
where, say (< n (len (rev a))) is explicitly assumed. In that
context, the Signature rule would not be fired because [type-set]
cannot establish (< n (len a)) from (< n (len (rev a))), even
though it would be easily proved by rewriting using the theorem
(equal (len (rev a)) (len a)).
Note also that if this signature could be phrased in a way that
eliminates the dependency between n and a it would be more
effective. For example, here is a related Signature rule without a
dependent hypothesis:
(implies (and (natp n)
(register-filep a)
(< n 16))
(integerp (nth n a)))
In this theorem we require only that n be less than 16, which is a
tau predicate and hence just an additional tau constraint on n.
General Form: Signature Form 2:
(implies (and (p1 x1) (p2 x2) ... (pn xn) dep-hyp)
(q (mv-nth 'n (fn x1 x2 ... xn))))
This form of signature rule is just like form 1 except that it is
useful for functions that return multiple-values and allows us to
``type-check'' their individual outputs.
General Form: Bounder Forms 1 and 2:
(implies (and (tau-intervalp i1)
...
(or (equal (tau-interval-dom i1) 'dom1-1)
...)
...
(in-tau-intervalp x1 i1)
...)
(and (tau-intervalp (bounder-fn i1 ...))
(in-tau-intervalp target
(bounder-fn i1 ...))))
where target is either (fn x1 ... y1 ...) in Form 1 or (mv-nth 'n (fn
x1 ... y1 ...)) in Form 2.
This form is for advanced users only and the schema given above is
just a reminder of the general shape. A ``bounder'' for a given
function symbol, fn, is a function symbol bounder-fn that computes
an interval containing (fn x1 ... y1 ...) (or its nth component in
the case of Form 2 rules) from the intervals containing certain of
the arguments of fn. The correctness theorem for a bounder function
informs the tau system that bounds for fn are computed by
bounder-fn and sets up the correspondence between the relevant
arguments, xi, of fn and the intervals containing those arguments,
ii to which bounder-fn is applied. When the tau system computes the
tau for a call of fn, it computes the tau of the relevant arguments
and applies the bounder to the intervals of those tau. This
provides a domain and upper and/or lower bounds for the value of
the term. The tau system then further augments that with signature
rules. See [bounders] for details on intervals, bounders, and
bounder correctness theorems.
General Form: Big Switch:
(equal (fn . formals) body)
In the Big Switch form, fn must be a function symbol, formals must be
a list of distinct variable symbols, and body must be a ``big
switch'' term, i.e., one that case splits on tau predicates about a
single variable and produces a term not involving that variable. An
example of a Big Switch rule is
(equal (conditional-type x y)
(if (consp x)
(consp y)
(integerp y)))
The idea is that the tau system can treat calls of conditional-type
as a tau-predicate after determining the tau of an argument.
Since equality-to-constants are tau predicates, a more common example
of a Big Switch rule is
(equal (dtypep x expr)
(case x
(STMT (stmt-typep expr))
(EXPR (expr-typep expr))
(MODULE (module-typep expr))
(otherwise nil)))
This is because (case x (STMT ...) ...) macroexpands in ACL2 to (if
(eql x 'STMT) ... ...) and (eql x 'STMT) is a tau predicate about
x.
Big Switch rules are recognized when a function is defined (if tau is
in automatic mode). They generally do not have to be proved
explicitly, though they might be when mutual recursion is involved.
Only the first detected Big Switch rule about a function fn is
recognized.
General Form: MV-NTH Synonym:
(equal (nth-alt x y) (mv-nth x y)) or
(equal (mv-nth x y) (nth-alt x y))
Rules of this form just tell the tau system that the user-defined
function nth-alt is synonymous with the ACL2 primitive function
mv-nth. Because ACL2's rewriter gives special handling to mv-nth,
users sometimes define their own versions of that function so they
can disable them and control rewriting better. By revealing to the
tau system that such a synonym has been introduced you allow
Signature rules of Form 2 to be used.
Subtopics
[Bounders]
Intervals, bounder functions, and bounder correctness
[In-tau-intervalp]
Boolean membership in a tau interval
[Introduction-to-the-tau-system]
A decision procedure for runtime types
[Make-tau-interval]
Make a tau interval
[Set-tau-auto-mode]
Turn on or off automatic (``greedy'') generation of :tau-system
rules
[Tau-data]
To see what tau knows about a function symbol
[Tau-database]
To see the tau database as a (very large) object
[Tau-interval-dom]
Access the domain of a tau interval
[Tau-interval-hi]
Access the upper bound of a tau interval
[Tau-interval-hi-rel]
Access the upper bound relation of a tau interval
[Tau-interval-lo]
Access the lower bound of a tau interval
[Tau-interval-lo-rel]
Access the lower bound relation of a tau interval
[Tau-intervalp]
Boolean recognizer for tau intervals
[Tau-status]
Query or set tau system status
[Time-tracker-tau]
Messages about expensive use of the [tau-system]")
(TENTH
(NTH ACL2-BUILT-INS)
"Tenth member of the list
See any Common Lisp documentation for details.")
(TERM
(MISCELLANEOUS)
"The three senses of well-formed ACL2 expressions or formulas
Examples of Terms:
(cond ((caar x) (cons t x)) (t 0)) ; an untranslated term
(if (car (car x)) (cons 't x) '0) ; a translated term
(car (cons x y) 'nil v) ; a pseudo-term
In traditional first-order predicate calculus a ``term'' is a
syntactic entity denoting some object in the universe of
individuals. Often, for example, the syntactic characterization of
a term is that it is either a variable symbol or the application of
a function symbol to the appropriate number of argument terms.
Traditionally, ``atomic formulas'' are built from terms with
predicate symbols such as ``equal'' and ``member;'' ``formulas''
are then built from atomic formulas with propositional
``operators'' like ``not,'' ``and,'' and ``implies.'' Theorems are
formulas. Theorems are ``valid'' in the sense that the value of a
theorem is true, in any model of the axioms and under all possible
assignments of individuals to variables.
However, in ACL2, terms are used in place of both atomic formulas and
formulas. ACL2 does not have predicate symbols or propositional
operators as distinguished syntactic entities. The ACL2 universe of
individuals includes a ``true'' object (denoted by t) and a
``false'' object (denoted by nil), predicates and propositional
operators are functions that return these objects. Theorems in ACL2
are terms and the ``validity'' of a term means that, under no
assignment to the variables does the term evaluate to nil.
We use the word ``term'' in ACL2 in three distinct senses. We will
speak of ``translated'' terms, ``untranslated'' terms, and
``pseudo-'' terms.
Translated Terms: The Strict Sense and Internal Form
In its most strict sense, a ``term'' is either a legal variable
symbol, a quoted constant, or the application of an n-ary function
symbol or closed lambda expression to a true list of n terms.
The legal variable symbols are symbols other than t or nil which are
not in the keyword package, do not start with ampersand, do not
start and end with asterisks, and if in the main Lisp package, do
not violate an appropriate restriction (see [name]).
Quoted constants are expressions of the form (quote x), where x is
any ACL2 object. Such expressions may also be written 'x.
Closed lambda expressions are expressions of the form (lambda (v1 ...
vn) body) where the vi are distinct legal variable symbols, body is
a term, and the only free variables in body are among the vi.
The function termp, which takes two arguments, an alleged term x and
a logical world w (see [world]), recognizes terms of a given
extension of the logic. Termp is defined in :[program] mode. Its
definition may be inspected with :[pe] termp for a complete
specification of what we mean by ``term'' in the most strict sense.
Most ACL2 term-processing functions deal with terms in this strict
sense and use termp as a [guard]. That is, the ``internal form'' of
a term satisfies termp, the strict sense of the word ``term.''
Untranslated Terms: What the User Types
While terms in the strict sense are easy to explore (because their
structure is so regular and simple) they can be cumbersome to type.
Thus, ACL2 supports a more sugary syntax that includes uses of
macros and constant symbols. Very roughly speaking, macros are
functions that produce terms as their results. Constants are
symbols that are associated with quoted objects. Terms in this
sugary syntax are ``translated'' to terms in the strict sense; the
sugary syntax is more often called ``untranslated.'' Roughly
speaking, translation just implements macroexpansion, the
replacement of constant symbols by their quoted values, and the
checking of all the rules governing the strict sense of ``term.''
More precisely, macro symbols are as described in the documentation
for [defmacro]. A macro, mac, can be thought of as a function,
mac-fn, from ACL2 objects to an ACL2 object to be treated as an
untranslated term. For example, [caar] is defined as a macro
symbol; the associated macro function maps the object x into the
object (car (car x)). A macro form is a ``call'' of a macro symbol,
i.e., a list whose [car] is the macro symbol and whose [cdr] is an
arbitrary true list of objects, used as a term. Macroexpansion is
the process of replacing in an untranslated term every occurrence
of a macro form by the result of applying the macro function to the
appropriate arguments. The ``appropriate'' arguments are determined
by the exact form of the definition of the macro; macros support
positional, keyword, optional and other kinds of arguments. See
[defmacro].
In addition to macroexpansion and constant symbol dereferencing,
translation implements the mapping of [let] and [let*] forms into
applications of lambda expressions and closes lambda expressions
containing free variables. Thus, the translation of
(let ((x (1+ i))) (cons x k))
can be seen as a two-step process that first produces
((lambda (x) (cons x k)) (1+ i))
and then
((lambda (x k) (cons x k)) (1+ i) k) .
Observe that the body of the [let] and of the first lambda expression
contains a free k which is finally bound and passed into the second
lambda expression.
Translation also maps [flet] forms into applications of lambda
expressions. See [flet].
When we say, of an event-level function such as [defun] or [defthm],
that some argument ``must be a term'' we mean an untranslated term.
The event functions translate their term-like arguments.
To better understand the mapping between untranslated terms and
translated terms it is convenient to use the keyword command
:[trans] to see examples of translations. See [trans] and also see
[trans1].
Finally, we note that the theorem prover prints terms in untranslated
form. But there can be more than one correct untranslated term
corresponding to a given translated term. For example, the
translated term (if x y 'nil) can be untranslated as (if x y nil)
and can also be untranslated as (and x y). The theorem prover
attempts to print an untranslated term that is as helpful to the
user as possible. In particular, consider a term of the form (nth k
st) where st is a single-threaded object (see [stobj]) and the kth
accessor of st is, say, kn. The theorem prover typically would
expand (kn st) to (nth k st). If k is large then it could be
difficult for the user to make sense out of a proof transcript that
mentions the expanded term. Fortunately, the untranslation of (nth
k st) would be (nth *kn* st); here *kn* would be a constant (see
[defconst]) added by the [defstobj] event introducing st, defined
to have value k. The user can extend this user-friendly style of
printing applications of [nth] to stobjs; see [add-nth-alias].
These remarks about printing applications of function [nth] extend
naturally to function [update-nth]. Moreover, the prover will
attempt to treat terms as [stobj]s for the above purpose when
appropriate. For example, if function foo has [signature] ((foo *
st) => (mv * * * st)), where st is introduced with (defstobj st f0
f1), then the [term] (nth '1 (mv-nth '3 (foo x st0))) will be
printed as (nth *f1* (mv-nth 3 (foo x st0))).
Pseudo-Terms: A Common Guard for Metafunctions
Because termp is defined in :[program] mode, it cannot be used
effectively in conjectures to be proved. Furthermore, from the
perspective of merely guarding a term processing function, termp
often checks more than is required. Finally, because termp requires
the logical [world] as one of its arguments it is impossible to use
termp as a [guard] in places where the logical [world] is not
itself one of the arguments.
For these reasons we support the idea of ``pseudo-terms.'' A
pseudo-term is either a symbol (but not necessarily one having the
syntax of a legal variable symbol), a true list of length 2
beginning with quote, or the ``application of'' a symbol or pseudo
lambda expression to a true list of pseudo-terms. A pseudo lambda
expression is an expression of the form (lambda (v1 ... vn) body)
where the vi are all symbols and body is a pseudo-term.
Pseudo-terms are recognized by the unary function [pseudo-termp]. If
(termp x w) is true, then (pseudo-termp x) is true. However, if x
fails to be a (strict) term it may nevertheless still be a
pseudo-term. For example, (car a b) is not a term, because [car] is
applied to the wrong number of arguments, but it is a pseudo-term.
The structures recognized by [pseudo-termp] can be recursively
explored with the same simplicity that terms can be. In particular,
if x is not a variablep or an fquotep, then (ffn-symb x) is the
function (symbol or lambda expression) and (fargs x) is the list of
argument pseudo-terms. A metafunction (see [meta]) or
clause-processor (see [clause-processor]) may use [pseudo-termp] as
the [guard].
Subtopics
[Guard-holders]
Remove trivial calls from a [term]
[Kwote]
Quote an arbitrary object
[Kwote-lst]
Quote an arbitrary true list of objects
[Pseudo-termp]
A predicate for recognizing term-like s-expressions
[Term-order]
The ordering relation on terms used by ACL2")
(TERM-LIST-LISTP
(ACL2-BUILT-INS)
"recognizer for a list of clauses
Example:
(term-list-listp
'(((NOT (ENDP X)) (NATP (LEN X)))
((ENDP X) (NOT (NATP (LEN (CDR X)))) (NATP (LEN X))))
(w state))
General Form:
(term-list-listp x w)
where x is any ACL2 object and w is an ACL2 logical [world]. The
result is t or nil according to whether x is a true list of true
lists of quotations of well-formed terms in w.
This function is the standard ACL2 idiom for recognizing a ``set of
clauses.'' See [clause-processor]. Each clause processor is
supposed to take a clause (i.e., term-listp) as input and yield a
list of clauses (i.e., term-list-listp) as output. When a clause
processor is run by the theorem prover its input is guaranteed to
be a well-formed clause by invariants maintained by ACL2. But its
output is checked by an explicit call to this function unless the
user has proved that the clause processor always returns a list of
clauses (see [well-formedness-guarantee]) or has taken the risk of
disabling the runtime test with [set-skip-meta-termp-checks].
Function: <term-list-listp>
(defun term-list-listp (l w)
(declare (xargs :guard (plist-worldp-with-formals w)))
(if (atom l)
(equal l nil)
(and (term-listp (car l) w)
(term-list-listp (cdr l) w))))")
(TERM-LISTP
(ACL2-BUILT-INS)
"recognizer for a list of quotations of terms and of clauses
Example:
(term-listp '((ZP X) 'NIL (CONS X Y)) (w state))
General Form:
(term-listp x w)
where x is any ACL2 object and w is an ACL2 logical [world]. The
result is t or nil according to whether x is a true list of
quotations of well-formed terms in w.
This function is used in the definition of [termp]. In addition,
term-listp is the standard ACL2 idiom for recognizing a clause
(``set of literals''). See [clause-processor]. Each clause
processor is supposed to take a clause (i.e., term-listp) as input
and yield a list of clauses (i.e., [term-list-listp]) as output.
When a clause processor is run by the theorem prover its input is
guaranteed to be a well-formed clause by invariants maintained by
ACL2. But its output is checked by an explicit call of
[term-list-listp] unless the user has proved that the clause
processor always returns a list of clauses (see
[well-formedness-guarantee]) or has taken the risk of disabling the
runtime test with [set-skip-meta-termp-checks].
[Term-listp] is mutually recursive with [termp].
Function: <term-listp>
(defun term-listp (x w)
(declare (xargs :guard (plist-worldp-with-formals w)))
(cond ((atom x) (equal x nil))
((termp (car x) w)
(term-listp (cdr x) w))
(t nil)))")
(TERM-ORDER
(TERM ACL2-BUILT-INS)
"The ordering relation on terms used by ACL2
ACL2 must occasionally choose which of two terms is syntactically
smaller. The need for such a choice arises, for example, when using
equality hypotheses in conjectures (the smaller term is substituted
for the larger elsewhere in the formula), in stopping loops in
permutative rewrite rules (see [loop-stopper]), and in choosing the
order in which to try to cancel the addends in linear arithmetic
inequalities. When this notion of syntactic size is needed, ACL2
uses ``term order.'' Popularly speaking, term order is just a
lexicographic ordering on terms. But the situation is actually more
complicated.
We define term order only with respect to terms in translated form.
See [trans]. Constants are viewed as built up by pseudo-function
applications, as described at the end of this documentation.
Term1 comes before term2 in the term order iff
(a) the number of variable occurrences in term1 is less than that in
term2, or
(b) the numbers of variable occurrences in the two terms are equal
but the number of function applications in term1 is less than
that in term2, or
(c) the numbers of variable occurrences in the two terms are equal,
the numbers of functions applications in the two terms are
equal, but pseudo-function application count for term1 is less
than that for term2, or
(d) the numbers of variable occurrences in the two terms are equal,
the numbers of functions applications in the two terms are
equal, the pseudo-function application counts for the two terms
are equal, and term1 comes before term2 in a lexicographic
ordering, [lexorder], based their structure as Lisp objects:
see [lexorder].
The function term-order, when applied to the translations of two ACL2
terms, returns t iff the first is ``less than or equal'' to the
second in the term order.
By ``number of variable occurrences'' we do not mean ``number of
distinct variables'' but ``number of times a variable symbol is
mentioned.'' (Cons x x) has two variable occurrences, not one.
Thus, perhaps counterintuitively, a large term that contains only
one variable occurrence, e.g., (standard-char-p (car (reverse x)))
comes before (cons x x) in the term order.
Since constants contain no variable occurrences and non-constant
expressions must contain at least one variable occurrence,
constants come before non-constants in the term order, no matter
how large the constants. For example, the list constant
'(monday tuesday wednesday thursday friday)
comes before x in the term order. Because term order is involved in
the control of permutative rewrite rules and used to shift smaller
terms to the left, a set of permutative rules designed to allow the
permutation of any two tips in a tree representing the nested
application of some function will always move the constants into
the left-most tips. Thus,
(+ x 3 (car (reverse klst)) (dx i j)) ,
which in translated form is
(binary-+ x
(binary-+ '3
(binary-+ (dx i j)
(car (reverse klst))))),
will be permuted under the built-in commutativity rules to
(binary-+ '3
(binary-+ x
(binary-+ (car (reverse klst))
(dx i j))))
or
(+ 3 x (car (reverse klst)) (dx i j)).
Two terms with the same numbers of variable occurrences and function
applications and the same pseudo-function application count are
ordered by lexicographic means, based on their structures. See
[lexorder]. Thus, if two terms (member ...) and (reverse ...)
contain the same numbers of variable occurrences and function
applications, and no quoted constants, then the [member] term is
first in the term order because [member] comes before [reverse] in
the term order (which is here reduced to alphabetic ordering).
It remains to discuss the notion of pseudo-function application
count.
Clearly, two constants are ordered using cases (c) and (d) of term
order, since they each contain 0 variable occurrences and no
function calls. This raises the question ``How many function
applications are in a constant?'' Because we regard the number of
function applications as a more fundamental measure of the size of
a constant than lexicographic considerations, we decided that for
the purposes of term order, constants would be seen as being built
by primitive constructor functions. These constructor functions are
not actually defined in ACL2 but merely imagined for the purposes
of term order. We here use suggestive names for these imagined
functions, ignoring entirely the prior use of these names within
ACL2. The imagined applications of these functions are what we
refer to as pseudo-function applications.
The constant function z constructs 0. Positive integers are
constructed from (z) by the successor function, s. Thus 2 is (s (s
(z))) and contains three function applications. 100 contains one
hundred and one applications. Negative integers are constructed
from their positive counterparts by [-]. Thus, -2 is (- (s (s
(z)))) and has four applications. Ratios are constructed by the
dyadic function [/]. Thus, -1/2 is
(/ (- (s (z))) (s (s (z))))
and contains seven applications. Complex rationals are similarly
constructed from rationals. All character objects are considered
primitive and are constructed by constant functions of the same
name. Thus #\\a and #\\b both contain one application. Strings are
built from the empty string, (o) by the ``string-cons'' function
written cs. Thus \"AB\" is (cs (#\\a) (cs (#\\b) (o))) and contains
five applications. Symbols are obtained from strings by ``packing''
the [symbol-name] with the unary function p. Thus 'ab is
(p (cs (#\\a) (cs (#\\b) (o))))
and has six applications. Note that packages are here ignored and
thus 'acl2::ab and 'my-package::ab each contain just six
applications. Finally, [cons]es are built with [cons], as usual. So
'(1 . 2) is (cons '1 '2) and contains six applications, since '1
contains two and '2 contains three. This, for better or worse,
answers the question ``How many function applications are in a
constant?''
Finally, when we refer to the ``pseudo-function application count'',
we mean the number of pseudo-function applications as described
above, except that we bound this number by the constant
(fn-count-evg-max-val). (This bound is important for efficiency, so
that constants that are very large cons structures do not cause
significant slowdown as ACL2 attempts to walk through them while
computing their pseudo-function application count.)")
(TERM-TABLE
(META)
"A table used to validate meta rules
Example:
(table term-table t '((binary-+ x y) '3 'nil (car x)))
See [table] for a general discussion of tables and the table event
used to manipulate tables.
The ``term-table'' is used at the time a meta rule is checked for
syntactic correctness. Each proposed metafunction is run on each
term in this table, and the result in each case is checked to make
sure that it is a termp in the current world. In each case where
this test fails, a warning is printed.
By default, when a metafunction is run in support of the application
of a meta rule, the result must be a term (see [termp]) in the
current world. When the result is not a term, a hard error arises.
(However, see the last paragraph below.) The term-table is simply a
means for providing feedback to the user at the time a meta rule is
submitted, warning of the definite possibility that such a hard
error will occur at some point in the future.
The key used in term-table is arbitrary. The top-most value is always
the one that is used; it is the entire list of terms to be
considered. Each must be a termp in the current ACL2 world.
The runtime check on the output of metafunctions can be avoided by
proving that it will always succeed (see
[well-formedness-guarantee]) or by telling ACL2 to skip the test at
the risk of soundness (see [set-skip-meta-termp-checks]).")
(TERMINATION-THEOREM
(LEMMA-INSTANCE MEASURE HINTS)
"Use a previously-proved measure theorem
See [lemma-instance] for a discussion of :termination-theorem and
:termination-theorem! lemma instances, and see [tthm] for a related
user-level query utility. Also see [termination-theorem-example]
for a simple example of the use of a measure theorem in [hints].")
(TERMINATION-THEOREM-EXAMPLE
(LEMMA-INSTANCE MEASURE HINTS)
"How to use a previously-proved measure theorem
See [lemma-instance] for a discussion of :termination-theorem and
:termination-theorem! lemma instances, and see [tthm] for a related
user-level query utility. In this topic, we illustrate the use of
such lemma instances to take advantage of a measure theorem already
proved for an existing definition, when attempting to admit a new
definition.
The following very simple example is contrived but should get the
idea across. Suppose that the following event was previously
executed, for example when including a book, in order to define the
log base 10 of x.
(encapsulate
()
(local (include-book \"arithmetic-5/top\" :dir :system))
(defun log10 (x) ; log base 10 of x
(if (or (zp x)
(< x 10))
0
(1+ (log10 (floor x 10))))))
Now suppose we want to admit the following definition, whose
recursion pattern is similar to that above. The simplest way might
be to include the same book as above, but perhaps that is
impossible because the [formula] for some name in that book
conflicts with the formula for that name in the current session.
Without that book, it could be challenging to develop lemmas that
allow the termination proof to succeed for this proposed
definition. So we provide a hint, specifying the use of the
termination theorem already proved for log10, as follows.
(defun base10-digits (x)
(declare (xargs :hints
((\"Goal\" :use ((:termination-theorem log10))))))
(if (or (zp x)
(< x 10))
(list x)
(append (base10-digits (floor x 10))
(list (mod x 10)))))
With this hint, the termination proof succeeds, printing the
following line in the event summary.
Hint-events: ((:USE LOG10))
This line says that the only :use hint was based on the event log10.
This may surprise you; perhaps you would expect to see something
instead such as (:USE (:TERMINATION-THEOREM LOG10)). However, the
Hint-events field of the summary is intended only to show the names
of [events] that support the hints. For example, if you replace the
:use hint in the example above with
:use ((:rewrite car-cons) (:termination-theorem log10))
then the Hint-events summary line will be as follows.
Hint-events: ((:USE CAR-CONS) (:USE LOG10))
Similarly, proof output for a :use hint (provided when not in
[gag-mode]) is also given at the level of events. For the
definition above, we get the following output.
We augment the goal with the hypothesis provided by the :USE hint.
The hypothesis can be obtained from LOG10. We are left with the following
subgoal.
Again, perhaps one would expect to see ``obtained from the
termination theorem for LOG10''. But for the modified hint shown
above, using (:rewrite car-cons), we similarly see only event
names, not a [rune].
These hypotheses can be obtained from CAR-CONS and LOG10.
We conclude with a remark about what happens when the termination
theorem does not exist, even though (as required) the indicated
function symbol is in [logic] mode. (For example, imagine that you
are generating such hints programmatically, without analyzing
whether the indicated function symbol was defined using recursion.)
In that case, using :termination-theorem will fail. Here, for
example, is what happens if f was defined non-recursively.
ACL2 !>(defun g (x)
(declare (xargs :hints
((\"Goal\" :use ((:termination-theorem f))))))
(if (consp x)
(g (cddr x))
x))
ACL2 Error in ( DEFUN G ...): The object (:TERMINATION-THEOREM F)
is an ill-formed lemma instance because there is no termination theorem
for F. The function F is not recursive. See :DOC lemma-instance.
Summary
Form: ( DEFUN G ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
ACL2 Error in ( DEFUN G ...): See :DOC failure.
******** FAILED ********
ACL2 !>
The alternative, :termination-theorem!, is provided in order to avoid
this sort of error. Here is the corresponding (edited) log, with
[gag-mode] off. Notice that since there is no termination theorem
stored for f, the :use hint specifies the use of T for the
termination theorem.
ACL2 !>(defun g (x)
(declare (xargs :hints
((\"Goal\" :use ((:termination-theorem! f))))))
(if (consp x)
(g (cddr x))
x))
For the admission of G we will use the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT X). The non-trivial part of the measure conjecture is
Goal
(IMPLIES (CONSP X)
(O< (ACL2-COUNT (CDDR X))
(ACL2-COUNT X))).
[Note: A hint was supplied for our processing of the goal above.
Thanks!]
We augment the goal with the hypothesis provided by the :USE hint.
The hypothesis can be obtained from F. We are left with the following
subgoal.
Goal'
(IMPLIES T
(OR (NOT (CONSP X))
(O< (ACL2-COUNT (CDDR X))
(ACL2-COUNT X)))).
By case analysis we reduce the conjecture to
[[.. output elided ..]]
Hint-events: ((:USE F))
Time: 0.02 seconds (prove: 0.01, print: 0.01, other: 0.00)
Prover steps counted: 1121
G
ACL2 !>")
(TERMP
(ACL2-BUILT-INS)
"recognizer for the quotation of a term
Example:
(termp '(CAR (CONS X Y)) (w state))
General Form:
(termp x w)
where x is any ACL2 object and w is an ACL2 logical [world]. The
result is t or nil according to whether x is the quotation of a
well-formed term in w.
Each metafunction (see [meta]) is supposed to take (the quotation of)
a well-formed term as input and yield (the quotation of) a
well-formed term as output. When a metafunction is run by the
simplifier its input is guaranteed to be well-formed by invariants
maintained by ACL2. But its output is checked by an explicit call
of termp unless the user has proved that the metafunction always
returns a term (see [well-formedness-guarantee]) or has taken the
risk of disabling the runtime test with
[set-skip-meta-termp-checks].
[Termp] is mutually recursive with [term-listp].
Function: <termp>
(defun
termp (x w)
(declare (xargs :guard (plist-worldp-with-formals w)))
(cond ((atom x) (legal-variablep x))
((eq (car x) 'quote)
(and (consp (cdr x)) (null (cddr x))))
((symbolp (car x))
(let ((arity (arity (car x) w)))
(and arity (true-listp (cdr x))
(eql (length (cdr x)) arity)
(term-listp (cdr x) w))))
((and (consp (car x))
(true-listp (car x))
(eq (car (car x)) 'lambda)
(equal 3 (length (car x)))
(arglistp (cadr (car x)))
(termp (caddr (car x)) w)
(null (set-difference-eq (all-vars (caddr (car x)))
(cadr (car x))))
(term-listp (cdr x) w)
(equal (length (cadr (car x)))
(length (cdr x))))
t)
(t nil)))")
(THE
(GUARD COMPILATION ACL2-BUILT-INS)
"The is a special form that can be used to optimize the execution
efficiency of [guard]-verified ACL2 definitions, or (less
frequently) to carry out a low-level run-time type checks.
(Advanced)
The is a special Common Lisp form. It is usually used as a way to
boost the performance of ACL2 definitions by telling the Common
Lisp compiler that a certain expression will always produce a
result of a certain type. This information may allow the Common
Lisp compiler to avoid certain run-time checks. See [declare] and
[type-spec] for general, related background.
General form:
(the <typ> <val>) ;; returns <val>, or causes a run-time error
* <typ> is a [type-spec]
* <val> is some expression that should produce a value of that type.
Typical example:
(defun merge-bytes (b1 b2)
;; Combine two 8-bit bytes into a 16-bit result.
(declare (type (unsigned-byte-p 8) b1 b2))
(the (unsigned-byte 16)
(logior (the (unsigned-byte 16) (ash b1 8))
b2)))
On most Lisp implementations 16-bit numbers are fixnums. The the
forms above are promises to the Lisp compiler that these ash and
logior operations will always produce 16-bit numbers. Ideally, the
compiler could use this information to generate more efficient
code, i.e., by omitting whatever code is normally required to
handle bignum results. (Of course, a sufficiently smart compiler
could have figured this out on its own; in practice Lisp compilers
vary in their reasoning abilities.)
Relation to Guards
To justify that type declarations are correct, the is integrated into
ACL2's [guard] mechanism. When a call of (the TYPE EXPR) in the
body of a function definition generates a guard proof obligation
that the type, TYPE, holds for the value of the expression, EXPR.
Consider the following example.
(defun f (x)
(declare (xargs :guard (p1 x)))
(if (p2 x)
(the integer (h x))
17))
The [guard] proof obligation generated for the THE expression above
is as follows.
(implies (and (p1 x) (p2 x))
(let ((var (h x))) (integerp var)))
For the to provide any execution speed benefit, [guard]s must be
[verified].
In contexts where guards have not been verified, the acts as a
low-level, run-time type check that val satisfies the type
specification typ (see [type-spec]). An error is caused if the
check fails; otherwise, val is returned. Here are some examples:
(the integer 3) ; returns 3
(the (integer 0 6) 3) ; returns 3
(the (integer 0 6) 7) ; causes an error (see below for exception)
There is an exception to the rule that failure of the type-check
causes an error: there is no error when [guard]-checking has been
turned off, that is, in any of the following ways; also
[set-guard-checking] and see [with-guard-checking].
* :set-guard-checking nil
* (with-guard-checking nil ...)
* :set-guard-checking :none
* (with-guard-checking :none ...)
Further resources
The [b*] macro provides a special syntax that may make using the
forms more pleasant; see [patbind-the] for more information.
When optimizing functions with type declarations, you may wish to
manually inspect the compiler's output with [disassemble$] or
conduct experiments to measure the impact of your optimizations.
THE is defined in Common Lisp. See any Common Lisp documentation for
more information.
Subtopics
[Type-spec]
Type specifiers can be used in Common Lisp type declarations and
[the] forms, and may result in improved efficiency of
execution.")
(THE-METHOD
(ACL2-TUTORIAL)
"How to find proofs
Also see [introduction-to-the-theorem-prover] for a more detailed
tutorial on how to prove theorems with ACL2.
Many users develop proof scripts in an Emacs buffer and submit one
event at a time to the theorem prover running in a *shell* buffer.
The script buffer is logically divided into two regions: the events
that have been accepted by the theorem prover and those that have
not yet been accepted. An imaginary ``barrier'' divides these two
regions. The region above the barrier describes the state of the
*shell* buffer (and ACL2's logical world). The region below the
barrier is the ``to do'' list.
We usually start a proof project by typing the key lemmas, and main
goal into the to do list. Definitions are here just regarded as
theorems to prove (i.e., the measure conjectures). Then we follow
``The Method.''
(1) Think about the proof of the first theorem in the to do list.
Structure the proof either as an induction followed by
simplification or just simplification. Have the necessary lemmas
been proved? That is, are the necessary lemmas in the done list
already? If so, proceed to Step 2. Otherwise, add the necessary
lemmas at the front of the to do list and repeat Step 1.
(2) Call the theorem prover on the first theorem in the to do list
and let the output stream into the *shell* buffer. Abort the proof
if it runs more than a few seconds.
(3) If the theorem prover succeeded, advance the barrier past the
successful command and go to Step 1.
(4) Otherwise, inspect the failed proof attempt, starting from the
beginning, not the end. Basically you should look for the first
place the proof attempt deviates from your imagined proof. If your
imagined proof was inductive, inspect the induction scheme used by
ACL2. If that is ok, then find the first subsequent subgoal that is
stable under simplification and think about why it was not proved
by the simplifier. If your imagined proof was not inductive, then
think about the first subgoal stable under simplification, as
above. Modify the script appropriately. It usually means adding
lemmas to the to do list, just in front of the theorem just tried.
It could mean adding hints to the current theorem. In any case,
after the modifications go to Step 1.
We do not seriously suggest that this or any rotely applied algorithm
will let you drive ACL2 to difficult proofs. Indeed, to remind you
of this we call this ``The Method'' rather than ``the method.''
That is, we are aware of the somewhat pretentious nature of any
such advice. But these remarks have helped many users approach ACL2
in a constructive and disciplined way.
We say much more about The Method in the ACL2 book. See the home
page. Also see [set-gag-mode] for a discussion of a way for ACL2 to
help you to use The Method. And again, see
[introduction-to-the-theorem-prover] for a more detailed tutorial.
Learning to read failed proofs is a useful skill. There are several
kinds of ``checkpoints'' in a proof: (1) a formula to which
induction is being (or would be) applied, (2) the first formula
stable under simplification, (3) a formula that is possibly
generalized, either by cross-fertilizing with and throwing away an
equivalence hypothesis or by explicit generalization of a term with
a new variable.
At the induction checkpoint, confirm that you believe the formula
being proved is a theorem and that it is appropriately strong for
an inductive proof. Read the selected induction scheme and make
sure it agrees with your idea of how the proof should go.
At the post-simplification checkpoint, which is probably the most
commonly seen, consider whether there are additional rewrite rules
you could prove to make the formula simplify still further. Look
for compositions of function symbols you could rewrite. Look for
contradictions among hypotheses and prove the appropriate
implications: for example, the checkpoint might contain the two
hypotheses (P (F A)) and (NOT (Q (G (F A)))) and you might realize
that (implies (p x) (q (g x))) is a theorem. Look for signs that
your existing rules did not apply, e.g., for terms that should have
been rewritten, and figure out why they were not. Possible causes
include that they do not exactly match your old rules, that your
old rules have hypotheses that cannot be relieved here -- perhaps
because some other rules are missing, or perhaps your old rules are
disabled. If you cannot find any further simplifications to make in
the formula, ask yourself whether it is valid. If so, sketch a
proof. Perhaps the proof is by appeal to a combination of lemmas
you should now prove?
At the two generalization checkpoints --- where hypotheses are
discarded or terms are replaced by variables --- ask yourself
whether the result is a theorem. It often is not. Think about
rewrite rules that would prove the formula. These are often
restricted versions of the overly-general formulas created by the
system's heuristics.
See [proof-tree] for a discussion of a tool to help you navigate
through ACL2 proofs.")
(THEORIES
(ACL2)
"Sets of [rune]s to [enable]/[disable] in concert
Example: '((:definition app) ; or (:d app)
(:executable-counterpart app)
(:i app)
rv
(rv)
(:r assoc-of-app))
See:
A theory is a list of ``runic designators'' as described below. Each
runic designator denotes a set of ``runes'' (see [rune]) and by
unioning together the runes denoted by each member of a theory we
define the set of runes corresponding to a theory. Theories are
used to control which rules are ``[enable]d,'' i.e., available for
automatic application by the theorem prover. There is always a
``current'' theory. A rule is [enable]d precisely if its [rune] is
an element of the set of [rune]s corresponding to the current
theory. At the top-level, the current theory is the theory selected
by the most recent [in-theory] event, extended with the rule names
introduced since then. Inside the theorem prover, the :[in-theory]
hint (see [hints]) can be used to select a particular theory as
current during the proof attempt for a particular goal.
Theories are generally constructed by ``theory expressions.''
Formally, a theory expression is any term, containing at most the
single free variable [world], that when evaluated with [world]
bound to the current ACL2 world (see [world]) produces a theory.
ACL2 provides various functions for the convenient construction and
manipulation of theories. These are called ``theory functions''(see
[theory-functions]). For example, the theory function
[union-theories] takes two theories and produces their union. The
theory function [universal-theory] returns the theory containing
all known rule names as of the introduction of a given logical
name. But a theory expression can contain constants, e.g.,
'(len (len) (:rewrite car-cons) car-cdr-elim)
and user-defined functions. The only important criterion is that a
theory expression mention no variable freely except [world] and
evaluate to a theory.
More often than not, theory expressions typed by the user do not
mention the variable [world]. This is because user-typed theory
expressions are generally composed of applications of ACL2's theory
functions. These ``functions'' are actually macros that expand into
terms in which [world] is used freely and appropriately. Thus, the
technical definition of ``theory expression'' should not mislead
you into thinking that interestng theory expressions must mention
[world]; they probably do and you just didn't know it!
One aspect of this arrangement is that theory expressions cannot
generally be evaluated at the top-level of ACL2, because [world] is
not bound. To see the value of a theory expression, expr, at the
top-level, type
ACL2 !>(LET ((WORLD (W STATE))) expr).
However, because the built-in theories are quite long, you may be
sorry you printed the value of a theory expression!
A theory is a true list of runic designators and to each theory there
corresponds a set of [rune]s, obtained by unioning together the
sets of [rune]s denoted by each runic designator. For example, the
theory constant
'(len (len) (:e nth) (:rewrite car-cons) car-cdr-elim)
corresponds to the set of [rune]s
{(:definition len)
(:induction len)
(:executable-counterpart len)
(:executable-counterpart nth)
(:elim car-cdr-elim)
(:rewrite car-cons)} .
Observe that the theory contains five elements but its runic
correspondent contains six. That is because runic designators can
denote sets of several [rune]s, as is the case for the first
designator, len. If the above theory were selected as current then
the six rules named in its runic counterpart would be [enable]d and
all other rules would be [disable]d.
We now precisely define the runic designators and the set of [rune]s
denoted by each. When we refer below to the ``macro-aliases
dereference of'' a symbol, symb, we mean the (function) symbol
corresponding symb in the macro-aliases-table if there is such a
symbol, else symb itself; see [macro-aliases-table]. For example,
the macro-aliases dereference of [append] is [binary-append], and
the macro-aliases dereference of [nth] is nth.
* A [rune] is a runic designator and denotes the singleton set
containing that rune.
* Suppose that symb is a symbol and symb' is the macro-aliases
dereference of symb, where symb' is a function symbol
introduced with a [defun] (or [defuns]) event. Then symb is a
runic designator and denotes the set containing the runes
(:definition symb') and (:induction symb'), omitting the latter
if no such [induction] rune exists (presumably because the
definition of symb' is not singly recursive).
* Suppose that symb is a symbol and symb' is the macro-aliases
dereference of symb, where symb' is a function symbol
introduced with a [defun] (or [defuns]) event. Then (symb) is a
runic designator and denotes the singleton set containing the
rune (:executable-counterpart symb').
* If symb is the name of a [defthm] (or [defaxiom]) event that
introduced at least one rule, then symb is a runic designator
and denotes the set of the names of all rules introduced by the
named event.
* If str is the string naming some [defpkg] event and symb is the
symbol returned by (intern str \"ACL2\"), then symb is a runic
designator and denotes the singleton set containing (:rewrite
symb), which is the name of the rule stating the conditions
under which the [symbol-package-name] of (intern x str) is str.
* If symb is the name of a [deftheory] event, then symb is a runic
designator and denotes the runic theory corresponding to symb.
* Finally, suppose that symb is a symbol and symb' is the macro-aliases
dereference of symb. Then (:KWD symb . rest) is a runic
designator, known as a ``runic abbreviation'', if (:KWD' symb'
. rest) is a [rune], where: :KWD is one of :d, :e, :i, :r, or
:t; and :KWD' is :definition, :executable-counterpart,
:induction, :rewrite, or :type-prescription, respectively. In
this case, (:KWD symb . rest) denotes the runic theory
corresponding to the rune (:KWD' symb' . rest).
Note that including a function name, e.g., [len], in the current
theory [enable]s that function but does not [enable] the executable
counterpart. Similarly, including (len) or (:e len) [enable]s the
executable counterpart but not the symbolic definition. And
including the name of a proved lemma [enable]s all of the rules
added by the event. Of course, one can include explicitly the
[rune]s naming the rules in question and so can avoid entirely the
use of non-runic elements in theories.
Because a [rune] is a runic designator denoting the set containing
that [rune], a list of [rune]s is a theory and denotes itself. We
call such theories ``runic theories.'' To every theory there
corresponds a runic theory obtained by unioning together the sets
denoted by each designator in the theory. When a theory is selected
as ``current'' it is actually its runic correspondent that is
effectively used. That is, a [rune] is [enable]d iff it is a member
of the runic correspondent of the current theory. The value of a
theory defined with [deftheory] is the runic correspondent of the
theory computed by the defining theory expression. The theory
manipulation functions, e.g., [union-theories], actually convert
their theory arguments to their runic correspondents before
performing the required set operation. The manipulation functions
always return runic theories. Thus, it is sometimes convenient to
think of (non-runic) theories as merely abbreviations for their
runic correspondents, abbreviations which are ``expanded'' at the
first opportunity by theory manipulation functions and the ``theory
consumer'' functions such as [in-theory] and [deftheory].
Subtopics
[Active-runep]
Check that a [rune] exists and is [enable]d
[Current-theory]
Currently [enable]d rules as of logical name
[Deftheory]
Define a theory (to [enable] or [disable] a set of rules)
[Deftheory-static]
Define a `static' theory (to [enable] or [disable] a set of rules)
[Disable]
Deletes names from current theory
[Disabledp]
Determine whether a given name or rune is disabled
[E/d]
Enable/disable rules
[Enable]
Adds names to current theory
[Executable-counterpart-theory]
Executable counterpart rules as of logical name
[Function-theory]
Function symbol rules as of logical name
[Ground-zero]
[enable]d rules in the [startup] theory
[In-theory]
Designate ``current'' theory (enabling its rules)
[Incompatible]
Declaring that two rules should not both be [enable]d
[Intersection-theories]
Intersect two [theories]
[Minimal-theory]
A minimal theory to enable
[Rule-names]
How rules are named.
[Rune]
A rule name
[Set-difference-theories]
Difference of two [theories]
[Theories-and-primitives]
Warnings from disabling certain built-in functions
[Theory]
Retrieve named theory
[Theory-functions]
Functions for obtaining or producing [theories]
[Union-theories]
Union two [theories]
[Universal-theory]
All rules as of logical name
[Using-enabled-rules]
Avoiding :use [hints] for [enable]d :[rewrite] rules")
(THEORIES-AND-PRIMITIVES
(THEORIES)
"Warnings from disabling certain built-in functions
When you [disable] the [definition] or [executable-counterpart] of a
built-in function, you may see a warning, for example as follows.
ACL2 !>(in-theory (disable mv-nth))
ACL2 Warning [Theory] in ( IN-THEORY (DISABLE ...)): The :DEFINITION
rule for MV-NTH is disabled by the theory expression (DISABLE MV-NTH),
but because this built-in function is given certain special handling,
some expansions of its calls may still occur. See :DOC theories-and-
primitives.
This warning can be eliminated by turning off all theory warnings
(see [set-inhibit-warnings]) or simply by evaluating the following
form.
(assign verbose-theory-warning nil)
But before you eliminate such warnings, you may wish to read the
following to understand their significance.
First consider the following example, evaluated after the [in-theory]
event displayed above.
ACL2 !>(thm (equal (mv-nth 2 (list a b c d e)) c))
Q.E.D.
Summary
Form: ( THM ...)
Rules: ((:DEFINITION MV-NTH)
(:FAKE-RUNE-FOR-TYPE-SET NIL))
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Prover steps counted: 19
Proof succeeded.
ACL2 !>
Note that even though the [definition] of [mv-nth] had been
[disable]d, nevertheless its definition rule was used in proving
this theorem. It is as though [mv-nth] had not been been disabled
after all! The warning is intended to indicate that expansion of
mv-nth calls may be made by the theorem prover even when mv-nth is
disabled. Indeed, the prover has special-purpose code for
simplifying certain mv-nth calls.
A similar issue can arise for executable-counterpart rules, as the
following log illustrates.
ACL2 !>(in-theory (disable (:e symbolp)))
ACL2 Warning [Theory] in ( IN-THEORY (DISABLE ...)): The :EXECUTABLE-
COUNTERPART rule for SYMBOLP is disabled by the theory expression
(DISABLE (:E SYMBOLP)), but because this built-in function is given
certain special handling, some evaluations of its calls may still occur.
See :DOC theories-and-primitives.
Summary
Form: ( IN-THEORY (DISABLE ...))
Rules: NIL
Warnings: Theory
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
(:NUMBER-OF-ENABLED-RUNES 3233)
ACL2 !>(thm (symbolp 'a))
Q.E.D.
Summary
Form: ( THM ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Proof succeeded.
ACL2 !>
In general, ACL2 warns when [in-theory] [events] or [hints] leave you
in a theory where a rule for a built-in function has just been
disabled, but may be applied in some cases nonetheless, because of
special-purpose prover code for handling calls of that function.
The built-in function symbols with such [definition] rules or
[executable-counterpart] rules are those in the following two
lists, respectively.
Definition: <*definition-minimal-theory*>
(defconst *definition-minimal-theory*
(list* 'mv-nth
'iff
*expandable-boot-strap-non-rec-fns*))
Definition: <*built-in-executable-counterparts*>
(defconst *built-in-executable-counterparts*
'(acl2-numberp binary-* binary-+ unary-- unary-/
< car cdr char-code characterp code-char
complex complex-rationalp coerce
cons consp denominator equal if imagpart
integerp intern-in-package-of-symbol
numerator pkg-witness pkg-imports
rationalp realpart stringp symbol-name
symbol-package-name symbolp not))")
(THEORY
(THEORIES THEORY-FUNCTIONS)
"Retrieve named theory
Examples:
For use in [in-theory] [events] or :in-theory [hints]:
(theory 'ground-zero)
For direct evaluation at the top-level loop:
(let ((world (w state))) (theory 'ground-zero))
In the examples above, the theory returned is the one in force when
ACL2 is started up (see [ground-zero]).
General Form:
(theory name)
where name is the name of a previously executed [deftheory] event
(otherwise a hard error occurs). Returns the named theory. See
[theories].
This ``function'' is actually a macro that expands to a term
mentioning the single free variable [world]. When theory
expressions are evaluated by [in-theory] or the :[in-theory] hint,
[world] is bound to the current ACL2 [world].")
(THEORY-FUNCTIONS
(THEORIES)
"Functions for obtaining or producing [theories]
Example Calls of Theory Functions:
(universal-theory :here)
(union-theories th1 th2)
(set-difference-theories th1 th2)
The theory functions are documented individually:
The functions (actually, macros) mentioned above are convenient ways
to produce [theories]. (See [theories].) Some, like
[universal-theory], take a logical name (see [logical-name]) as an
argument and return the relevant theory as of the time that name
was introduced. Others, like [union-theories], take two [theories]
and produce a new one. See [redundant-events] for a caution about
the use of logical names in theory expressions.
Theory expressions are generally composed of applications of theory
functions. Formally, theory expressions are expressions that
involve, at most, the free variable [world] and that when evaluated
with [world] bound to the current ACL2 world (see [world]) return
[theories]. The ``theory functions'' are actually macros that
expand into forms that involve the free variable [world]. Thus, for
example (universal-theory :here) actually expands to
(universal-theory-fn :here world) and when that form is evaluated
with [world] bound to the current ACL2 [world], universal-theory-fn
scans the ACL2 property lists and computes the current universal
theory. Because the theory functions all implicitly use [world],
the variable does not generally appear in anything the user types.
Subtopics
[Current-theory]
Currently [enable]d rules as of logical name
[Disable]
Deletes names from current theory
[E/d]
Enable/disable rules
[Enable]
Adds names to current theory
[Executable-counterpart-theory]
Executable counterpart rules as of logical name
[Function-theory]
Function symbol rules as of logical name
[Ground-zero]
[enable]d rules in the [startup] theory
[Intersection-theories]
Intersect two [theories]
[Minimal-theory]
A minimal theory to enable
[Set-difference-theories]
Difference of two [theories]
[Theory]
Retrieve named theory
[Union-theories]
Union two [theories]
[Universal-theory]
All rules as of logical name")
(THEORY-INVARIANT
(EVENTS)
"User-specified invariants on [theories]
Examples:
(theory-invariant (not (and (active-runep '(:rewrite left-to-right))
(active-runep '(:rewrite right-to-left))))
:key my-invariant
:error nil)
; Equivalent to the above:
(theory-invariant (incompatible (:rewrite left-to-right)
(:rewrite right-to-left))
:key my-invariant
:error nil)
General Form:
(theory-invariant term &key key error)
where:
* term is a term that uses no variables other than ens and [state];
* key is an arbitrary ``name'' for this invariant (if omitted, an
integer is generated and used); and
* :error specifies the action to be taken when an invariant is violated
--- either nil if a warning is to be printed, else t (the
default) if an error is to be caused.
Theory-invariant is an event that adds to or modifies the [table] of
user-supplied theory invariants that are checked each time a theory
expression is evaluated.
The theory invariant mechanism is provided via a table (see [table])
named theory-invariant-table. In fact, the theory-invariant
``event'' is just a macro that expands into a use of the [table]
event. More general access to the theory-invariant [table] is
provided by [table] itself. For example, the [table] can be
inspected or cleared with [table]; you can clear an individual
theory invariant by setting the invariant to t, or eliminate all
theory invariants with the command (table theory-invariant-table
nil nil :clear).
Theory-invariant-table maps arbitrary keys to records containing
terms that mention, at most, the variables ens and [state]. Every
time an alleged theory expression is evaluated, e.g., in the
[in-theory] event or :[in-theory] hint, each of the terms in
theory-invariant-table is evaluated with ens bound to a so-called
``enabled structure'' obtained from the theory expression and
[state] bound to the current ACL2 state (see [state]). Users
generally need not know about the enabled structure, other than
that it can be accessed using the macros active-runep and
incompatible; see [active-runep] and see [incompatible]. If the
result is nil, a message is printed and an error occurs (except,
only a warning occurs if :error nil is specified). Thus, the
[table] can be thought of as a list of conjuncts. Each term in the
[table] has a ``name,'' which is just the key under which the term
is stored. When a theory violates the restrictions specified by
some term, both the name and the term are printed. By calling
theory-invariant with a new term but the same name, you can
overwrite that conjunct of the theory invariant; but see the Local
Redefinition Caveat at the end of this note. You may want to avoid
using explicit names, since otherwise the subsequent inclusion of
another book that defines a theory invariant with the same name
will override your theory invariant.
Theory invariants are particularly useful in the context of large
rule sets intended for re-use. Such sets often contain conflicting
rules, e.g., rules that are to be [enable]d when certain function
symbols are [disable]d, rules that rewrite in opposite directions
and thus loop if simultaneously [enable]d, groups of rules which
should be [enable]d in concert, etc. The developer of such rule
sets understands these restrictions and probably documents them.
The theory invariant mechanism allows the developer to codify his
restrictions so that the user is alerted when they are violated.
Since theory invariants are arbitrary terms, macros may be used to
express commonly used restrictions. For example, executing the
event
(theory-invariant (incompatible (:rewrite left-to-right)
(:rewrite right-to-left)))
would subsequently cause an error any time the current theory
contained both of the two [rune]s shown. Of course, [incompatible]
is just defined as a macro. Its definition may be inspected with
:pe incompatible.
In order for a theory-invariant event to be accepted, the proposed
theory invariant must be satisfied by the current theory (see
[current-theory]). The value returned upon successful execution of
the event is the key (whether user-supplied or generated).
Local Redefinition Caveat. Care needs to be taken when redefining a
theory invariant in a [local] context. Consider the following
example.
(theory-invariant
(active-runep '(:definition binary-append))
:key app-inv)
(encapsulate
()
(local (theory-invariant t :key app-inv))
(in-theory (disable binary-append))
(defthm ...))
The second pass of the [encapsulate] will fail, because the
[in-theory] event violates the original theory-invariant and the
[local] theory-invariant is skipped in the second pass of the
[encapsulate]. Of course, [local] [theory-invariant]s in [books]
can cause the analogous problem in the second ([include-book]) pass
of a [certify-book]. In both cases, though, the theory invariants
are only checked at the conclusion of the (include-book or
encapsulate) event. Indeed, theory invariants are checked at the
end of every event related to [theories], including [defun],
[defthm], [in-theory], [encapsulate], and [include-book], except
for events executed on behalf of an [include-book] or the second
pass of an [encapsulate].")
(THE_ADMISSION_OF_APP
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Admission of App
[{IMAGE}]
Here is what it looks like to submit the definition of app to ACL2:
{IMAGE}
ACL2 !>(defun app (x y)
(cond ((endp x) y)
(t (cons (car x)
(app (cdr x) y)))))
The admission of APP is trivial, using the relation O< (which
is known to be well-founded on the domain recognized by O-P)
and the measure (ACL2-COUNT X). We observe that the type of APP is
described by the theorem (OR (CONSP (APP X Y)) (EQUAL (APP X Y) Y)).
We used primitive type reasoning.
Summary
Form: ( DEFUN APP ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: None
Time: 0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
APP
{IMAGE}
The text between the lines above is one interaction with the ACL2
command loop. Interacting with the latest version of ACL2 may not
produce the very same output, but we trust you'll recognize the
basics.
Above you see the user's input and how the system responds. This
little example shows you what the syntax looks like and is a very
typical successful interaction with the definitional principle.
Let's look at it a little more closely.
[{IMAGE}]")
(THE_ASSOCIATIVITY_OF_APP
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Associativity of App
[{IMAGE}]
{IMAGE}
ACL2!>(let ((a '(1 2))
(b '(3 4))
(c '(5 6)))
(equal (app (app a b) c)
(app a (app b c))))
T
{IMAGE}
Observe that, for the particular a, b, and c above, (app (app a b) c)
returns the same thing as (app a (app b c)). Perhaps app is
associative. Of course, to be associative means that the above
property must hold for all values of a, b, and c, not just the ones
tested above.
Wouldn't it be cool if you could type
ACL2!>(equal (app (app a b) c)
(app a (app b c)))
and have ACL2 compute the value T? Well, you can't! If you try it,
you'll get an error message! The message says we can't evaluate
that form because it contains free variables, i.e., variables not
given values. Click [here] to see the message.
We cannot evaluate a form on an infinite number of cases. But we can
prove that a form is a theorem and hence know that it will always
evaluate to true.
[{IMAGE}]")
(THE_BASE_CASE_IN_THE_APP_EXAMPLE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Base Case in the App Example
This formula is the Base Case. It consists of two parts, a test
identifying the non-inductive case and the conjecture to prove.
(IMPLIES (ENDP A) ; Test
(:P A B C)) ; Conjecture
When we prove this we can assume
* A is empty
and we have to prove the conjecture for A.")
(THE_END_OF_THE_FLYING_TOUR
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The End of the Flying Tour
{IMAGE}
This completes the Flying Tour.
We recommend that you now take [A Walking Tour of ACL2].
Thanks.
Matt Kaufmann and J Moore
[{IMAGE}]")
(THE_END_OF_THE_PROOF_OF_THE_ASSOCIATIVITY_OF_APP
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The End of the Proof of the Associativity of App
[{IMAGE}]
That [completes] the proof of *1.
[Q.E.D.]
Summary
Form: ( DEFTHM ASSOCIATIVITY-OF-APP ...)
[Rules]: ((:REWRITE CDR-CONS)
(:REWRITE CAR-CONS)
(:DEFINITION NOT)
(:DEFINITION ENDP)
(:FAKE-RUNE-FOR-TYPE-SET NIL)
(:DEFINITION APP))
Warnings: None
Time: 0.27 seconds (prove: [0.10], print: 0.05, other: 0.12)
ASSOCIATIVITY-OF-APP
{IMAGE}
[{IMAGE}]")
(THE_END_OF_THE_WALKING_TOUR
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The End of the Walking Tour
{IMAGE}
This completes the Walking Tour.
We intend to document many other parts of the system this way, but we
just haven't gotten around to it.
To start the two tours over again from the beginning, click on the
icons below. If you are really interested in learning how to use
ACL2, we recommend that you repeat each tour at least once more to
explore branches of the tour that you might have missed.
If you want to learn how to use the theorem prover, we now recommend
that you devote the time necessary to work your way through the
extended introduction to how to use the prover.
See [introduction-to-the-theorem-prover].
This will explain how to interact with ACL2 and has some sample
problems for you to solve including some challenge proofs to make
ACL2 find.
We hope you enjoy ACL2. We do.
Matt Kaufmann and J Strother Moore
[{IMAGE}] [{IMAGE}]")
(THE_EVENT_SUMMARY
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Event Summary
At the conclusion of most events (click [here] for a brief discussion
of events or see [events] [{ICON}]), ACL2 prints a summary. The
summary for app is:
Summary
Form: ( DEFUN APP ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: None
Time: 0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
APP
The ``rules'' listed are those used in function admission or proof
summarized. What is actually listed are ``runes'' (see [rune])
[{ICON}]) which are list-structured names for rules in the ACL2
database or ``[world]'' [{ICON}]. Using [theories] [{ICON}] you can
``enable'' and ``disable'' rules so as to make them available (or
not) to the ACL2 theorem prover.
The ``warnings'' mentioned (none are listed for app) remind the
reader whether the event provoked any warnings. The warnings
themselves would have been printed earlier in the processing and
this part of the summary just names the earlier warnings printed.
The ``time'' indicates how much processing time was used and is
divided into three parts: the time devoted to proof, to printing,
and to syntactic checks, pre-processing and database updates.
Despite the fact that ACL2 is an applicative language it is
possible to measure time with ACL2 programs. The [state] [{ICON}]
contains a clock. The times are printed in decimal notation but are
actually counted in integral units. Note that by default, each time
is a runtime, also known as a cpu time, as opposed to being a real
time, also known as a wall clock time.
The final APP is the value of the defun command and was printed by
the read-eval-print loop. The fact that it is indented one space is
a subtle reminder that the command actually returned an ``error
triple'', consisting of a flag indicating (in this case) that no
error occurred, a value (in this case the symbol APP), and the
final [state] [{ICON}]). See [ld-post-eval-print] [{ICON}] for some
details. If you really want to follow that link, however, you might
see [ld] [{ICON}] first.
You should now return to [the Walking Tour].")
(THE_EXPANSION_OF_ENDP_IN_THE_INDUCTION_STEP_{STEP_0}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Expansion of ENDP in the Induction Step (Step 0)
Subgoal *1/2
(IMPLIES (AND (NOT [(]ENDP A))
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (APP (APP A B) C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above (the open parenthesis before ENDP) to replace
(ENDP A) by its definition.")
(THE_EXPANSION_OF_ENDP_IN_THE_INDUCTION_STEP_{STEP_1}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Expansion of ENDP in the Induction Step (Step 1)
Subgoal *1/2
(IMPLIES (AND [(]NOT (NOT (CONSP A)))
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (APP (APP A B) C)
(APP A (APP B C)))).
{IMAGE}
The bold text is the instantiated definition of ENDP.
Now click on the link above to simplify (NOT (NOT (CONSP A)))")
(THE_EXPANSION_OF_ENDP_IN_THE_INDUCTION_STEP_{STEP_2}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Expansion of ENDP in the Induction Step (Step 2)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (APP (APP A B) C)
(APP A (APP B C)))).
{IMAGE}
Note that this is Subgoal *1/2'.
You may click [here] to return to the main proof.")
(THE_FALLING_BODY_MODEL
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Falling Body Model
{IMAGE}
One particularly famous and very simple model is the equation of a
falling body: the distance d an object falls is proportional to the
square of the time t. If the time is measured in seconds and the
distance in feet, the equation relating these two is
2
d = 16t
This equation is a model of falling objects. It can be used to
predict how long it takes a cannonball to fall from the top of a
200 foot tower (3.5 seconds). This might be important if your
product is designed to drop cannonballs on moving targets.")
(THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE_{STEP_0}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Final Simplification in the Base Case (Step 0)
Subgoal *1/1'
(IMPLIES (NOT (CONSP A))
(EQUAL (APP [(]APP A B) C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above to replace (APP A B) by its definition. Note
that the hypothesis (NOT (CONSP A)) allows us to simplify the IF in
APP to its false branch this time.")
(THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE_{STEP_1}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Final Simplification in the Base Case (Step 1)
Subgoal *1/1'
(IMPLIES (NOT (CONSP A))
(EQUAL (APP B C)
[(]APP A (APP B C)))).
{IMAGE}
Click on the link above to expand the definition of APP. Again, we
come out through the false branch because of the hypothesis.")
(THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE_{STEP_2}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Final Simplification in the Base Case (Step 2)
Subgoal *1/1'
(IMPLIES (NOT (CONSP A))
[(]EQUAL (APP B C)
(APP B C))).
{IMAGE}
Click on the link above to use the Axiom (EQUAL x x) = t")
(THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE_{STEP_3}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Final Simplification in the Base Case (Step 3)
Subgoal *1/1'
(IMPLIES (NOT (CONSP A))
T)
{IMAGE}
Now that its conclusion is identically T the IMPLIES will simplify to
T (not shown) and we are done with Subgoal *1/1'.
You may click [here] to return to the main proof.")
(THE_FIRST_APPLICATION_OF_THE_ASSOCIATIVITY_RULE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The First Application of the Associativity Rule
So here we see our associativity rule being used!
The rewriter sweeps the conjecture in a leftmost innermost fashion,
applying rewrite rules as it goes.
The associativity rule is used many times in this sweep. The first
``target'' is highlighted below. Click on it to see what happens:
Current Conjecture:
(equal (app (app [(app (app x1 x2) (app x3 x4))] (app x5 x6)) x7)
(app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7)))))")
(THE_INDUCTION_SCHEME_SELECTED_FOR_THE_APP_EXAMPLE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Induction Scheme Selected for the App Example
(AND
(IMPLIES (AND (NOT (ENDP A)) ; Induction Step: test
(:P (CDR A) B C)) ; and induction hypothesis
(:P A B C)) ; implies induction conclusion.
(IMPLIES (ENDP A) (:P A B C))) ; Base Case
The formula beginning with this parenthesis is the induction scheme
suggested by (APP A B) applied to (P A B C).
It is a conjunction ([and] [{ICON}]) of two formulas.
The first is the induction step and the second is the base case.")
(THE_INDUCTION_STEP_IN_THE_APP_EXAMPLE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Induction Step in the App Example
This formula is the Induction Step. It basically consists of three
parts, a test identifying the inductive case, an induction
hypothesis and an induction conclusion.
(IMPLIES (AND (NOT (ENDP A)) ; Test
(:P (CDR A) B C)) ; Induction Hypothesis
(:P A B C)) ; Induction Conclusion
When we prove this we can assume
* A is not empty, and that
* the associativity conjecture holds for a ``smaller'' version of A,
namely, (CDR A).
Under those hypotheses we have to prove the associativity conjecture
for A itself.")
(THE_INSTANTIATION_OF_THE_INDUCTION_SCHEME
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Instantiation of the Induction Scheme
The induction scheme just shown is just an abbreviation for our real
goal.
To obtain our actual goals we have to replace the schema :P by the
associativity conjecture (instantiated as shown in the scheme).
This produces two actual goals, the induction step and the base case.")
(THE_JUSTIFICATION_OF_THE_INDUCTION_SCHEME
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Justification of the Induction Scheme
This paragraph explains why the induction selected is legal. The
explanation is basically the same as the explanation for why the
recursion in (APP A B) terminates.")
(THE_PROOF_OF_THE_ASSOCIATIVITY_OF_APP
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Proof of the Associativity of App
[{IMAGE}]
Here is the theorem prover's output when it processes the defthm
command for the associativity of app. We have highlighted text for
which we offer some explanation, and broken the presentation into
several pages. (The most recent version of ACL2 may print slightly
different output but the basics are the same.) Just follow the
Walking Tour after exploring the explanations.
However, before exploring this output you should understand that ACL2
users rarely read successful proofs! Instead, they look at certain
subgoals printed in failed proofs, figure whether and how those
subgoals can be proved, and give ACL2 directions for proving them,
usually by simply proving other lemmas. Furthermore, to be a good
user of ACL2 you do not have to understand how the theorem prover
works. You just have to understand how to interact with it. We
explain this in great detail later. But basically all new users are
curious to know how ACL2 works and this little tour attempts to
give some answers, just to satisfy your curiosity.
{IMAGE}
ACL2!>(defthm associativity-of-app
(equal (app (app a b) c)
(app a (app b c))))
Name the formula above [*1].
[Perhaps] we can prove *1 by induction. Three induction schemes are
[suggested] by this conjecture. [Subsumption] reduces that number to two.
However, one of these is [flawed] and so we are left with one viable
candidate.
We will induct according to a scheme suggested by (APP A B). If we
let (:P A B C) denote *1 above then the induction scheme we'll use
is
[(]AND
[(]IMPLIES (AND (NOT (ENDP A))
(:P (CDR A) B C))
(:P A B C))
[(]IMPLIES (ENDP A) (:P A B C))).
This induction is [justified] by the same argument used to admit APP,
namely, the measure (ACL2-COUNT A) is decreasing according to the relation
O< (which is known to be well-founded on the domain recognized
by O-P). When [applied] to the goal at hand the above induction
scheme produces the following two [nontautological subgoals].
[{IMAGE}]")
(THE_Q.E.D._MESSAGE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Q.E.D. Message
Q.E.D. stands for ``quod erat demonstrandum'' which is Latin for
``which was to be demonstrated'' and is the signal that a proof is
completely done.")
(THE_RULES_USED_IN_THE_ASSOCIATIVITY_OF_APP_PROOF
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Rules used in the Associativity of App Proof
Note that under Rules we list the [runes] [{ICON}] of all the rules
used in the proof. This list says that we used the rewrite rules
CAR-CONS and CDR-CONS, the definitions of the functions NOT, ENDP
and APP, and primitive type reasoning (which is how we simplified
the IF and EQUAL terms).
For what it is worth, IMPLIES and AND are actually [macros] [{ICON}]
that are expanded into IF expressions before the proof ever begins.
The use of macros is not reported among the rules.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_0}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 0)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (APP [(]APP A B) C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above to replace (APP A B) by its definition.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_10}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 10)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
[(]EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C)))).
{IMAGE}
Click on the link above to use the Induction Hypothesis (which is the
second of the two hypotheses above and which is identical to the
rewritten conclusion).")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_11}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 11)
Subgoal *1/2'
[(]IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
T)
{IMAGE}
Click on the link above to use the definition of IMPLIES. Since the
conclusion of the implication is now identically T, the implication
simplifies to T.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_12}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 12)
Subgoal *1/2'
T
{IMAGE}
So, indeed, Subgoal *1/2' does simplify to T!
You can see that even in an example as simple as this one, quite a
lot happens in simplification.
You may click [here] to return to the main proof.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_1}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 1)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (APP (IF [(]CONSP A)
(CONS (CAR A) (APP (CDR A) B))
B)
C)
(APP A (APP B C)))).
{IMAGE}
Note that the IF expression above is the simplified body of APP. But
we know the test (CONSP A) is true, by the first hypothesis. Click
on the link above to replace the test by T. Actually this step and
several subsequent ones are done during the simplification of the
body of APP but we want to illustrate the basic principles of
simplification without bothering with every detail.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_2}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 2)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (APP [(]IF T
(CONS (CAR A) (APP (CDR A) B))
B)
C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above to apply the Axiom (IF T x y) = x.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_3}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 3)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL [(]APP (CONS (CAR A) (APP (CDR A) B))
C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above to expand the definition of APP here.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_4}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 4)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (IF [(]CONSP (CONS (CAR A) (APP (CDR A) B)))
(CONS (CAR (CONS (CAR A) (APP (CDR A) B)))
(APP (CDR (CONS (CAR A) (APP (CDR A) B)))
C))
C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above to apply the Axiom (CONSP (CONS x y)) = T.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_5}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 5)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (IF T
(CONS [(]CAR (CONS (CAR A) (APP (CDR A) B)))
(APP (CDR (CONS (CAR A) (APP (CDR A) B)))
C))
C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above to apply the Axiom (CAR (CONS x y)) = x.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_6}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 6)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (IF T
(CONS (CAR A)
(APP [(]CDR (CONS (CAR A) (APP (CDR A) B)))
C))
C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above to apply the Axiom (CDR (CONS x y)) = y.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_7}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 7)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL [(]IF T
(CONS (CAR A)
(APP (APP (CDR A) B)
C))
C)
(APP A (APP B C)))).
{IMAGE}
Click on the link above to apply the Axiom (IF T x y) = x.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_8}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 8)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
(EQUAL (CONS (CAR A)
(APP (APP (CDR A) B)
C))
[(]APP A (APP B C)))).
{IMAGE}
Click on the link above to expand the definition of APP here. This
time, we'll do the whole expansion at once, including the
simplification of the resulting IF. This is how ACL2 actually does
it.")
(THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_9}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Simplification of the Induction Conclusion (Step 9)
Subgoal *1/2'
(IMPLIES (AND (CONSP A)
(EQUAL (APP (APP (CDR A) B) C)
(APP (CDR A) (APP B C))))
[(]EQUAL (CONS (CAR A)
(APP (APP (CDR A) B)
C))
(CONS (CAR A)
(APP (CDR A) (APP B C))))).
{IMAGE}
Click on the link above to apply the Axiom that (EQUAL (CONS x y)
(CONS u v)) is equal to the conjunction of (EQUAL x u) and (EQUAL y
v). In this case, (EQUAL x u) is trivial, (EQUAL (CAR A) (CAR A)).")
(THE_SUMMARY_OF_THE_PROOF_OF_THE_TRIVIAL_CONSEQUENCE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Summary of the Proof of the Trivial Consequence
Note that at the conclusion of the proof, the system reminds you of
the earlier Warning.
It is a good idea, when the Q.E.D. flys by, to see if there were any
Warnings.")
(THE_THEOREM_THAT_APP_IS_ASSOCIATIVE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Theorem that App is Associative
[{IMAGE}]
ACL2!>(defthm associativity-of-app
(equal (app (app a b) c)
(app a (app b c))))
The formula above says app is associative. The [defthm] [{ICON}]
command instructs ACL2 to prove the formula and to name it
associativity-of-app. Actually, the defthm command also builds the
formula into the database as a [rewrite] [{ICON}] rule, but we
won't go into that just yet.
What we will consider is how the ACL2 theorem prover proves this
formula.
If you proceed you will find the actual output of ACL2 in response to
the command above. Some of the text is highlighted for the purposes
of the tour. ACL2 does not highlight its output.
You will note that we sometimes highlight a single open parenthesis.
This is our way of drawing your attention to the subformula that
begins with that parenthesis. By clicking on the parenthesis you
will get an explanation of the subformula or its processing.
[{IMAGE}]")
(THE_TIME_TAKEN_TO_DO_THE_ASSOCIATIVITY_OF_APP_PROOF
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Time Taken to do the Associativity of App Proof
The time it took us to explain this proof may leave the impression
that the proof is complicated. In a way, it is. But it happens
quickly.
The time taken to do this proof is about 1/10 second. The rest of the
time (about 2/10 seconds) is spent in pre- and post-processing.
Basically, this proof flashes across your screen before you can read
it; you see the Q.E.D. and don't bother to scroll back to read it.
You have more important things to do than read successful proofs.")
(THE_TOURS
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The Tours
ACL2 is a very large, multipurpose system. You can use it as a
programming language, a specification language, a modeling
language, a formal mathematical logic, or a semi-automatic theorem
prover, just to name its most common uses. It has been used on a
number of [industrial applications]. If you're uncertain as to
whether your project is appropriate for ACL2 we urge you to look
over this list or contact the ACL2 developers.
This home page includes all of ACL2's online documentation, which is
quite extensive (over 4 megabytes). To help ease your introduction
to ACL2, we have built two tours through this documentation.
If you are familiar with at least some of the [industrial
applications] of ACL2, then you will understand the distance
between the simple examples we talk about in these tours and the
kinds of things ACL2 users do with the system.
Newcomers to ACL2 should first take the ``Flying Tour.'' Then, if you
want to know more, take the ``Walking Tour.'' On your first
reading, follow the two Tours linearly, clicking only on the icon
of the Tour you're on. Beware of other links, which might jump you
from one tour to the other or into the ACL2 User's Manual! Once
you've had a coherent overview of the system, you might quickly
repeat both Tours to see if there are unvisited links you're
interested in, using your brower's Back Button to return to your
starting points.
If after all this you want to learn how to use the theorem prover
(!), see [introduction-to-the-theorem-prover].
To start a tour, click on the appropriate icon below.
[{IMAGE}] [{IMAGE}]
If you take the tours in a text-based format (such as using the :DOC
command in Emacs), they will probably be unsatisfying because we
use gif files and assume you can navigate ``back.''")
(THE_WARNING_ABOUT_THE_TRIVIAL_CONSEQUENCE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"The WARNING about the Trivial Consequence
This Warning alerts us to the fact that when treated as a rewrite
rule, the new rule TRIVIAL-CONSEQUENCE, rewrites terms of the same
form as a rule we have already proved, namely ASSOCIATIVITY-OF-APP.
When you see this warning you should think about your rules!
In the current case, it would be a good idea not to make
TRIVIAL-CONSEQUENCE a rule at all. We could do this with
:[rule-classes] [{ICON}] nil.
ACL2 proceeds to try to prove the theorem, even though it printed
some warnings. The basic assumption in ACL2 is that the user
understands what he or she is doing but may need a little reminding
just to manage a complicated set of facts.")
(THIRD
(NTH ACL2-BUILT-INS)
"Third member of the list
See any Common Lisp documentation for details.")
(THM
(MISCELLANEOUS)
"Prove a theorem
Example:
(thm (equal (app (app a b) c)
(app a (app b c))))
Also see [defthm]. Unlike [defthm], thm does not create an event; it
merely causes the theorem prover to attempt a proof.
General Form:
(thm term
:hints hints
:otf-flg otf-flg)
where term is a term alleged to be a theorem, and [hints] and
[otf-flg] are as described in the corresponding [documentation]
topics. The keyword arguments above are both optional.
Subtopics
[Otf-flg]
Allow more than one initial subgoal to be pushed for induction")
(TIDBITS
(ACL2-TUTORIAL)
"Some basic hints for using ACL2
See [books] for a discussion of books. Briefly, a book is a file
whose name ends in ``.lisp'' that contains ACL2 [events]; see
[events].
See [history] for a list of useful commands. Some examples:
:pbt :here ; print the current event
:pbt (:here -3) ; print the last four events
:u ; undo the last event
:pe append ; print the definition of append
See [documentation] to learn how to print documentation to the
terminal. There are also versions of the [documentation] for web
browsers and for Emacs (see [ACL2-Doc]).
There are quite a few kinds of rules allowed in ACL2 besides
:[rewrite] rules, though we hope that beginners won't usually need
to be aware of them. See [rule-classes] for details. In particular,
there is support for [congruence] rewriting. See [rune] (``RUle
NamE'') for a description of the various kinds of rules in the
system. Also see [theories] for a description of how to build
[theories] of [rune]s, which are often used in hints; see [hints].
A ``[programming] mode'' is supported; see [program], see
[defun-mode], and see [default-defun-mode]. It can be useful to
prototype functions after executing the command :[program], which
will cause definitions to be syntaxed-checked only.
ACL2 supports mutual recursion, though this feature is not tied into
the automatic discovery of [induction] schemas and is often not the
best way to proceed when you expect to be reasoning about the
functions. See [defuns]; also see [mutual-recursion].
See [ld] for discussion of how to load files of [events]. There are
many options to [ld], including ones to suppress proofs and to
control output.
The :[otf-flg] (Onward Thru the Fog FLaG) is a useful feature that
Nqthm users have often wished for. It prevents the prover from
aborting a proof attempt and inducting on the original conjecture.
See [otf-flg].
ACL2 supports redefinition and redundancy in [events]; see
[ld-redefinition-action] and see [redundant-events].
A [proof-tree] display feature is available for use with Emacs. This
feature provides a view of ACL2 proofs that can be much more useful
than reading the stream of [characters] output by the theorem
prover as its ``proof.'' See [proof-tree].
An interactive feature similar to Pc-Nqthm is supported in ACL2. See
[verify] and see [proof-checker].
ACL2 allows you to [monitor] the use of [rewrite] rules. See
[break-rewrite].
See [arrays] to read about applicative, fast [arrays] in ACL2.
To quit the ACL2 [command] loop, or (in akcl) to return to the ACL2
[command] loop after an interrupt, type :[q]. To continue (resume)
after an interrupt (in akcl), type :r. To cause an interrupt (in
akcl under Unix (trademark of AT&T)), hit control-C (twice, if
inside Emacs). To exit ACL2 altogether, type :[quit].
See [state] to read about the von Neumannesque ACL2 [state] object
that records the ``current state'' of the ACL2 session. Also see
[@], and see [assign], to learn about reading and setting global
[state] variables.
If you want your own von Neumannesque object, e.g., a structure that
can be ``destructively modified'' but which must be used with some
syntactic restrictions, see [stobj].")
(TIME$
(PROGRAMMING ACL2-BUILT-INS)
"Time an evaluation
Semantically, (time$ x ...) equals x. However, its evaluation may
write timing output to the trace output (which is usually the
terminal), as explained further below.
Examples:
; Basic examples:
(time$ (foo 3 4))
(time$ (mini-proveall))
(defun bar (x) (time$ (f x)))
; Custom examples, which use a custom timing message rather than a built-in
; message from Lisp:
; Report only if real time is at least 1/2 second (two equivalent forms).
(time$ (foo) :mintime 1/2)
(time$ (foo) :real-mintime 1/2)
; Report only if allocation is at least 1000 bytes (and if the Lisp supports
; :minalloc).
(time$ (foo) :minalloc 1000)
; Report only if real time is at least 1/2 second and (if the Lisp supports
; :minalloc) allocation is at least 931 bytes.
(time$ (foo) :real-mintime 1/2 :minalloc 931)
; Print \"Hello Moon, Goodbye World\" instead of any timing data.
(time$ (foo)
:msg \"Hello ~s0, ~s1 World.\"
:args (list \"Moon\" \"Goodbye\"))
; Print default custom timing message (same as omitting :mintime 0):
(time$ (foo)
:mintime 0)
; Print supplied custom timing message.
(let ((bar ...))
(time$ (foo)
:msg \"The execution of ~xf took ~st seconds of real ~
time and ~sc seconds of run time (cpu time), and ~
allocated ~sa bytes. In an unrelated note, bar ~
currently has the value ~x0.~%\"
:args (list bar)))
General Forms:
(time$ form)
(time$ form ; arguments below are optional
:real-mintime <rational number of seconds>
:run-mintime <rational number of seconds>
:minalloc <number of bytes>
:msg <fmt string>
:args <list of arguments for msg>
)
; Note: :real-mintime can be replaced by :mintime
where form is processed as usual except that the host Common Lisp
times its evaluation.
The simplest form is (time$ x), which will call the time utility in
the underlying Lisp, and will print a small default message. If you
want to see a message printed by the host Lisp, use (time$ x
:mintime nil) instead, which may provide detailed,
implementation-specific data such as the amounts of time spent in
user and system mode, the gc time, the number of page faults
encountered, and so on. Of you can create a custom message,
configured using the :msg and :args parameters. Time$ can also be
made to report timing information only conditionally: the
:real-mintime (or equivalently, :mintime), :run-mintime, and
:minalloc arguments can be used to avoid reporting timing
information for computations that take a small amount of time
(perhaps as might be expected in ordinary cases), but to draw the
user's attention to computations that take longer or allocate more
memory than expected.
We next document the keyword arguments in some detail.
Keyword arguments :real-mintime (or :mintime) and :run-mintime can be
used to specify a minimum time threshold for time reporting.
That is, no timing information will be printed if the execution
of form takes less than the specified number of seconds of real
(total) time or run (cpu) time, respectively. Note that
rational numbers like 1/2 may be used to specify a fractional
amount of seconds. It is an error to specify both :real-mintime
and its synonym, :mintime.
Keyword argument :minalloc is not supported on all Lisps. When it is
not supported, it is ignored. But on supported Lisps, :minalloc
can be used to specify a minimum memory allocation threshold.
If form results in fewer than this many bytes being allocated,
then no timing information will be reported.
Keyword argument :msg, when provided, should be a string accepted by
the fmt family of functions (see [fmt]), and it may refer to
the elements of :args by their positions, just as for cw (see
[cw]).
The following directives allow you to report timing information using
the :msg string. The examples at the top of this documentation
topic illustrate the use of these directives.
~xf --- the form that was executed
~sa --- the amount of memory allocated, in bytes (in supported Lisps)
~st --- the real time taken, in seconds
~sc --- the run time (cpu time) taken, in seconds
The following apply only when the host Lisp is GCL. The two system
times will likely be nil unless the GCL version is 2.6.10 or
later. Note the upper-case characters for child times.
~sC --- the child run time (cpu time) taken, in seconds
~ss --- the system time taken, in seconds
~sS --- the child system time taken, in seconds
We turn now to an example that illustrates how time$ can be called in
function bodies. Consider the following definition of the Fibonacci
function, followed by the definition of a function that times k
calls of this function.
(defun fib (n)
(if (zp n)
1
(if (= n 1)
1
(+ (fib (- n 1))
(fib (- n 2))))))
(defun time-fib (k)
(if (zp k)
nil
(prog2$
(time$ (fib k)
:mintime 1/2
:msg \"(fib ~x0) took ~st seconds, ~sa bytes allocated.~%\"
:args (list k))
(time-fib (1- k)))))
The following log shows a sample execution of the function defined
just above.
ACL2 !>(time-fib 36)
(fib 36) took 3.19 seconds, 1280 bytes allocated.
(fib 35) took 1.97 seconds, 1280 bytes allocated.
(fib 34) took 1.21 seconds, 1280 bytes allocated.
(fib 33) took 0.75 seconds, 1280 bytes allocated.
NIL
ACL2 !>
Notes:
(1) Common Lisp specifies that the time utility prints to ``trace
output'', and time$ follows this convention. Thus, if you have
opened a [trace] file (see [open-trace-file]), then you can expect
to find the time$ output there.
(2) Unless the :msg argument is supplied, an explicit call of time$
in the top-level loop will show that the form being timed is a call
of the ACL2 evaluator function ev-rec. This is normal; the curious
are invited, at their own risk, to see [return-last] for an
explanation.
Subtopics
[Time-tracker]
Display time spent during specified evaluation")
(TIME-TRACKER
(DEBUGGING TIME$ ACL2-BUILT-INS)
"Display time spent during specified evaluation
The time-tracker macro is a utility for displaying time spent during
specified evaluation. In general, the user provides this
specification. However, ACL2 itself uses this utility for tracking
uses of its [tau-system] reasoning utility (see
[time-tracker-tau]). We discuss that use as an example before
discussing the general form for calls of time-tracker.
Note that by default, the time being tracked is runtime (cpu time);
to switch to realtime (elapsed time), see [get-internal-time].
Remark for ACL2(p) users (see [parallelism]): time-tracker is merely
a no-op in ACL2(p).
During the development of the [tau-system], we were concerned about
the possibility that it would slow down proofs without any
indication of how one might avoid the problem. We wanted a utility
that would alert the user in such situations. However, the
tau-system code does not return [state], so we could not track time
spent in the state. We developed the time-tracker utility to track
time and print messages, and we did it in a general way so that
others can use it in their own code. Here is an example of such a
message that could be printed during a proof.
TIME-TRACKER-NOTE [:TAU]: Elapsed runtime in tau is 2.58 secs; see
:DOC time-tracker-tau.
And here is an example of such a message that could be printed at the
end of the proof.
TIME-TRACKER-NOTE [:TAU]: For the proof above, the total time spent
in the tau system was 20.29 seconds. See :DOC time-tracker-tau.
The time-tracker utility tracks computation time spent on behalf of a
user-specified ``tag''. In the case of the tau-system, we chose the
tag, :tau. The first argument of time-tracker is the tag, which in
our running example is always :tau. Note that although all
arguments of time-tracker are evaluated, the first argument is
typically a keyword and the second is always a keyword, and such
arguments evaluate to themselves.
An ACL2 function invoked at the start of a proof includes
approximately the following code.
(progn$
(time-tracker :tau :end)
(time-tracker :tau :init
:times '(1 2 3 4 5)
:interval 5
:msg \"Elapsed runtime in tau is ~st secs; see :DOC ~
time-tracker-tau.~|~%\")
...)
The first time-tracker call (above) ends any existing time-tracking
for tag :tau. One might have expected it to be put into code
managing the proof summary, but we decided not to rely on that code
being executed, say, in case of an interrupt. When a given tag is
not already being time-tracked, then :end is a no-op (rather than
an error).
The second time-tracker call (above) initiates time-tracking for the
tag, :tau. Moreover, it specifies the effect of the :print?
keyword. Consider the following abbreviated definition from the
ACL2 source code.
(defun tau-clausep-lst-rec (clauses ens wrld ans ttree state calist)
(cond
((endp clauses)
(mv (revappend ans nil) ttree calist))
(t (mv-let
(flg1 ttree1 calist)
(tau-clausep (car clauses) ens wrld state calist)
(prog2$ (time-tracker :tau :print?)
(tau-clausep-lst-rec (cdr clauses) ...))))))
Notice that (time-tracker :tau :print?) is executed immediately after
tau-clausep is called. The idea is to check whether the total time
elapsed inside the tau-system justifies printing a message to the
user. The specification of :times '(1 2 3 4 5) in the :init form
above says that a message should be printed after 1 second, after 2
seconds, ..., and after 5 seconds. Thereafter, the specification of
:interval 5 in the :init form above says that each time we print,
at least 5 additional seconds should have been tracked before
(time-tracker :tau :print?) prints again. Finally, the :msg keyword
above specifies just what should be printed. If it is omitted, then
a reasonable default message is printed (as discussed below), but
in this case we wanted to print a custom message. The :msg string
above is what is printed using formatted printing (see [fmt]),
where the character #\\t is bound to a string giving a decimal
representation with two decimal points of the time tracked so far
for tag :tau. (As our general description below points out, :msg
can also be a ``message'' list rather than a string.)
But when is time actually tracked for :tau? Consider the following
definition from the ACL2 source code.
(defun tau-clausep-lst (clauses ens wrld ans ttree state calist)
(prog2$ (time-tracker :tau :start!)
(mv-let
(clauses ttree calist)
(tau-clausep-lst-rec clauses ens wrld ans ttree state calist)
(prog2$ (time-tracker :tau :stop)
(mv clauses ttree calist)))))
The two calls of time-tracker above first start, and then stop,
time-tracking for the tag, :tau. Thus, time is tracked during
evaluation of the call of tau-clausep-lst-rec, which is the
function (discussed above) that does the [tau-system]'s work.
Finally, as noted earlier above, ACL2 may print a time-tracking
message for tag :tau at the end of a proof. The ACL2 function
print-summary contains essentially the following code.
(time-tracker :tau :print?
:min-time 1
:msg \"For the proof above, the total runtime ~
spent in the tau system was ~st seconds. ~
See :DOC time-tracker-tau.~|~%\")
The use of :min-time says that we are to ignore the :times and
:interval established by the :init call described above, and
instead, print a message if and only if at least 1 second (since 1
is the value of keyword :min-time) has been tracked for tag :tau.
Formatted printing (see [fmt]) is used for the value of :msg, where
the character #\\t is bound to a decimal string representation of
the time in seconds, as described above.
The example above covers all legal values for the second argument of
time-tracker and discusses all the additional legal keyword
arguments. We conclude with a precise discussion of all arguments.
Note that all arguments are evaluated; thus when we refer to an
argument, we are discussing the value of that argument. All times
discussed are runtimes, i.e., cpu times, unless that default is
changed; see [get-internal-time].
General forms:
(time-tracker t) ; enable time-tracking (default)
(time-tracker nil) ; disable time-tracking
(time-tracker tag ; a symbol other than t or nil
option ; :init, :end, :start, :start!, :stop, or :print?
;; keyword arguments:
:times ; non-nil if and only if option is :init
:interval ; may only be non-nil with :init option
:min-time ; may only be non-nil with :print? option
:msg ; may only be non-nil with :init and :print? options
Time-tracking is enabled by default. If the first argument is t or
nil, then no other arguments are permitted and time-tracking is
enabled or disabled, respectively. When time-tracking is disabled,
nothing below takes place. Thus we assume time-tracking is enabled
for the remainder of this discussion. We also assume below that the
first argument is neither t nor nil.
We introduce some basic notions about time-tracking. A given tag,
such as :tau in the example above, might or might not currently be
``tracked'': :init causes the specified tag to be tracked, while
:end causes the specified tag not to be tracked. If the tag is
being tracked, the tag might or might not be ``active'': :start and
:start! cause the tag to be in an active state, whie :stop causes
the tag not to be active. Note that only tracked tags can be in an
active or inactive state. For a tag that is being tracked, the
``accumulated time'' is the total time spent in an active state
since the time that the tag most recently started being tracked,
and the ``checkpoint list'' is a non-empty list of rational numbers
specifying when printing may take place, as described below.
We now consider each legal value for the second argument, or
``option'', for a call of time-tracker on a given tag.
:Init specifies that the tag is to be tracked. It also establishes
defaults for the operation of :print?, as described below, using
the :times, :interval, and :msg keywords. Of these three, only
:times is required, and its value must be a non-empty list of
rational numbers specifying the initial checkpoint list for the
tag. It is an error to specify :init if the tag is already being
tracked. (So if you don't care whether or not the tag is already
being tracked and you want to initiate tracking for that tag, use
:end first.)
:End specifies that if the tag is being tracked, then it should nstop
being tracked. If the tag is not being tracked, then :end has no
effect.
:Start specifies that the tag is to be active. It is an error to
specify :start if the tag is not being tracked or is already
active.
:Start! has the same effect as :start, except that it does not cause
an error when the tag is already active. In effect, :start! first
invokes :stop if the tag is already active, and then invokes start.
:Stop specifies that the tag is to stop being active. It is an error
to specify :stop if the tag is not being tracked or is not active.
:Print? specifies that if the tag is being tracked (not necessarily
active), then a message should be printed if a suitable condition
is met. The nature of that message and that condition depend on the
keyword options supplied with :print? as well as those supplied
with the :init option that most recently initiated tracking.
:Print? has no effect if the tag is not being tracked, except that
if certain keyword values are checked if supplied with :print?:
:min-time must be a rational number or nil, and :msg must be either
a string, a true-list whose car is a string, or nil. The remainder
of this documentation describes the :print? option in detail under
the assumption that the tag is being tracked: first, giving the
conditions under which it causes a message to be printed, and
second, explaining what is printed.
When :print? is supplied a non-nil value of :min-time, that value
must be a rational number, in which case a message is printed if
the accumulated time for the tag is at least that value. Otherwise
a message is printed if the accumulated time is greater than or
equal to the car of the checkpoint list for the tag. In that case,
the tracking state for the tag is updated in the following two
ways. First, the checkpoint list is scanned from the front and as
long as the accumulated time is greater than or equal to the car of
the remaining checkpoint list, that car is popped off the
checkpoint list. Second, if the checkpoint list has been completely
emptied and a non-nil :interval was supplied when tracking was most
recently initiated with the :init option, then the checkpoint list
is set to contain a single element, namely the sum of the
accumulated time with that value of :interval.
Finally, suppose the above criteria are met, so that :print? results
in printing of a message. We describe below the message, msg, that
is printed. Here is how it is printed (see [fmt]), where
seconds-as-decimal-string is a string denoting the number of
seconds of accumulated time for the tag, with two digits after the
decimal point.
(fms \"TIME-TRACKER-NOTE [~x0]: ~@1~|\"
(list (cons #0 tag)
(cons #1 msg)
(cons #t seconds-as-decimal-string))
(proofs-co state) state nil)
The value of msg is the value of the :msg keyword supplied with
:print?, if non-nil; else, the value of :msg supplied when most
recently initialization with the :init option, if non-nil; and
otherwise, the string \"~st s\" (the final ``s'' abbreviating the
word ``seconds''). It is convenient to supply :msg as a call (msg
str arg-0 arg-1 ... arg-k), where str is a string and each arg-i is
the value to be associated with #\\i upon formatted printing (as
with [fmt]) of the string str.")
(TIME-TRACKER-TAU
(TAU-SYSTEM)
"Messages about expensive use of the [tau-system]
This [documentation] topic explains messages printing by the theorem
prover about the [tau-system], as follows.
During a proof you may see a message such as the following.
TIME-TRACKER-NOTE [:TAU]: Elapsed runtime in tau is 4.95 secs; see
:DOC time-tracker-tau.
Just below a proof summary you may see a message such as the
following.
TIME-TRACKER-NOTE [:TAU]: For the proof above, the total runtime spent
in the tau system was 30.01 seconds. See :DOC time-tracker-tau.
Both of these messages are intended to let you know that certain
prover heuristics (see [tau-system]) may be slowing proofs down
more than they are helping. If you are satisfied with the prover's
performance, you may ignore these messages or even turn them off by
disabling time-tracking entirely (see [time-tracker]). Otherwise,
here are some actions that you can take to solve such a performance
problem.
The simplest solution is to disable the tau-system, in either of the
following equivalent ways.
(in-theory (disable (:executable-counterpart tau-system)))
(in-theory (disable (tau-system)))
But if you want to leave the tau-system enabled, you could
investigate the possibility is that the tau-system is causing an
expensive :[logic]-mode function to be executed. You can diagnose
that problem by observing the rewriter --- see [dmr] --- or by
interrupting the system and getting a backtrace (see
[set-debugger-enable]). A solution in that case is to disable the
executable-counterpart of that function, for example in either of
these equivalent ways.
(in-theory (disable (:executable-counterpart foo)))
(in-theory (disable (foo)))
As a result, the tau-system will be weakened, but perhaps only
negligibly.
In either case above, you may prefer to provide :[in-theory] hints
rather than :in-theory [events]; see [hints].
A more sophisticated solution is to record values of the
:[logic]-mode function in question, so that the tau-system will
look up the necessary values rather than calling the function,
whether or not the executable-counterpart of that function is
enabled. Here is an example of a lemma that can provide such a
solution. See [tau-system].
(defthm lemma
(and (foo 0)
(foo 17)
(foo t)
(not (foo '(a b c))))
:rule-classes :tau-system)")
(TIPS
(ACL2-TUTORIAL)
"Some hints for using the ACL2 prover
We present here some tips for using ACL2 effectively. Though this
collection is somewhat ad hoc, we try to provide some organization,
albeit somewhat artificial: for example, the sections overlap, and
no particular order is intended. This material has been adapted by
Bill Young from a very similar list for Nqthm that appeared in the
conclusion of: ``Interaction with the Boyer-Moore Theorem Prover: A
Tutorial Study Using the Arithmetic-Geometric Mean Theorem,'' by
Matt Kaufmann and Paolo Pecchiari, CLI Technical Report 100, June,
1995. We also draw from a similar list in Chapter 13 of ``A
Computational Logic Handbook'' by R.S. Boyer and J S. Moore
(Academic Press, 1988). We'll refer to this as ``ACLH'' below.
These tips are organized roughly as follows.
A. ACL2 Basics
B. Strategies for creating events
C. Dealing with failed proofs
D. Performance tips
E. Miscellaneous tips and knowledge
F. Some things you DON'T need to know
ACL2 BASICS
A1. The ACL2 logic.
This is a logic of total functions. For example, if A and B are less
than or equal to each other, then we need to know something more in
order to conclude that they are equal (e.g., that they are
numbers). This kind of twist is important in writing definitions;
for example, if you expect a function to return a number, you may
want to apply the function [fix] or some variant (e.g., [nfix] or
[ifix]) in case one of the formals is to be returned as the value.
ACL2's notion of ordinals is important on occasion in supplying
``measure [hints]'' for the acceptance of recursive definitions. Be
sure that your measure is really an ordinal. Consider the following
example, which ACL2 fails to admit (as explained below).
(defun cnt (name a i x)
(declare (xargs :measure (+ 1 i)))
(cond ((zp (+ 1 i))
0)
((equal x (aref1 name a i))
(1+ (cnt name a (1- i) x)))
(t (cnt name a (1- i) x))))
One might think that (+ 1 i) is a reasonable measure, since we know
that (+ 1 i) is a positive integer in any recursive call of cnt,
and positive integers are ACL2 ordinals (see [o-p]). However, the
ACL2 logic requires that the measure be an ordinal unconditionally,
not just under the governing assumptions that lead to recursive
calls. An appropriate fix is to apply [nfix] to (+ 1 i), i.e., to
use
(declare (xargs :measure (nfix (+ 1 i))))
in order to guarantee that the measure will always be an ordinal (in
fact, a positive integer).
For more about admissibility of recursive definitions, see [defun],
in particular the discussion of termination.
A2. Simplification.
The ACL2 simplifier is basically a rewriter, with some ``[linear]
arithmetic'' thrown in. One needs to understand the notion of
conditional rewriting. See [rewrite].
A3. Parsing of rewrite rules.
ACL2 parses [rewrite] rules roughly as explained in ACLH, except that
it never creates ``unusual'' rule classes. In ACL2, if you want a
:[linear] rule, for example, you must specify :[linear] in the
:[rule-classes]. See [rule-classes], and also see [rewrite] and see
[linear].
A4. Linear arithmetic.
On this subject, it should suffice to know that the prover can
handle truths about [+] and [-], and that [linear] rules (see
above) are somehow ``thrown in the pot'' when the prover is doing
such reasoning. Perhaps it's also useful to know that [linear]
rules can have hypotheses, and that conditional rewriting is used
to relieve those hypotheses.
A5. Events.
Over time, the expert ACL2 user will know some subtleties of its
[events]. For example, [in-theory] [events] and [hints] are
important, and they distinguish between a function and its
executable counterpart.
B. STRATEGIES FOR CREATING EVENTS
In this section, we concentrate on the use of definitions and
[rewrite] rules. There are quite a few kinds of rules allowed in
ACL2 besides [rewrite] rules, though most beginning users probably
won't usually need to be aware of them. See [rule-classes] for
details. In particular, there is support for [congruence]
rewriting. Also see [rune] (``RUle NamE'') for a description of the
various kinds of rules in the system.
B1. Use high-level strategy.
Decompose theorems into ``manageable'' lemmas (admittedly,
experience helps here) that yield the main result ``easily.'' It's
important to be able to outline non-trivial proofs by hand (or in
your head). In particular, avoid submitting goals to the prover
when there's no reason to believe that the goal will be proved and
there's no ``sense'' of how an induction argument would apply. It
is often a good idea to avoid induction in complicated theorems
unless you have a reason to believe that it is appropriate.
B2. Write elegant definitions.
Try to write definitions in a reasonably modular style, especially
recursive ones. Think of ACL2 as a [programming] language whose
procedures are definitions and lemmas, hence we are really
suggesting that one follow good [programming] style (in order to
avoid duplication of ``code,'' for example).
When possible, complex functions are best written as compositions of
simpler functions. The theorem prover generally performs better on
primitive recursive functions than on more complicated recursions
(such as those using accumulating parameters).
Avoid large non-recursive definitions which tend to lead to large
case explosions. If such definitions are necessary, try to prove
all relevant facts about the definitions and then [disable] them.
Whenever possible, avoid mutual recursion if you care to prove
anything about your functions. The induction heuristics provide
essentially no help with reasoning about mutually defined
functions. Mutually recursive functions can usually be combined
into a single function with a ``flag'' argument. (However, see
[mutual-recursion-proof-example] for a small example of proof
involving mutually recursive functions.)
B3. Look for analogies.
Sometimes you can easily edit sequences of lemmas into sequences of
lemmas about analogous functions.
B4. Write useful rewrite rules.
As explained in A3 above, every [rewrite] rule is a directive to the
theorem prover, usually to replace one [term] by another. The
directive generated is determined by the syntax of the [defthm]
submitted. Never submit a [rewrite] rule unless you have considered
its interpretation as a proof directive.
B4a. Rewrite rules should simplify.
Try to write [rewrite] rules whose right-hand sides are in some
sense ``simpler than'' (or at worst, are variants of) the left-hand
sides. This will help to avoid infinite loops in the rewriter.
B4b. Avoid needlessly expensive rules.
Consider a rule whose conclusion's left-hand side (or, the entire
conclusion) is a [term] such as (consp x) that matches many [term]s
encountered by the prover. If in addition the rule has complicated
hypotheses, this rule could slow down the prover greatly. Consider
switching the conclusion and a complicated hypothesis (negating
each) in that case.
B4c. The ``Knuth-Bendix problem''.
Be aware that left sides of [rewrite] rules should match the
``normalized forms'', where ``normalization'' (rewriting) is inside
out. Be sure to avoid the use of nonrecursive function symbols on
left sides of [rewrite] rules, except when those function symbols
are [disable]d, because they tend to be expanded away before the
rewriter would encounter an instance of the left side of the rule.
Also assure that subexpressions on the left hand side of a rewrite
rule are in simplified form; see [community-books] example
books/demos/knuth-bendix-problem-1.lisp.
B4d. Avoid proving useless rules.
Sometimes it's tempting to prove a [rewrite] rule even before you
see how it might find application. If the rule seems clean and
important, and not unduly expensive, that's probably fine,
especially if it's not too hard to prove. But unless it's either
part of the high-level strategy or, on the other hand, intended to
get the prover past a particular unproved goal, it may simply waste
your time to prove the rule, and then clutter the database of rules
if you are successful.
B4e. State rules as strongly as possible, usually.
It's usually a good idea to state a rule in the strongest way
possible, both by eliminating unnecessary hypotheses and by
generalizing subexpressions to variables.
Advanced users may choose to violate this policy on occasion, for
example in order to avoid slowing down the prover by excessive
attempted application of the rule. However, it's a good rule of
thumb to make the strongest rule possible, not only because it will
then apply more often, but also because the rule will often be
easier to prove (see also B6 below). New users are sometimes
tempted to put in extra hypotheses that have a ``type restriction''
appearance, without realizing that the way ACL2 handles (total)
functions generally lets it handle trivial cases easily.
B4f. Avoid circularity.
A stack overflow in a proof attempt almost always results from
circular rewriting. Use [brr] to investigate the stack; see
[break-lemma]. Because of the complex heuristics, it is not always
easy to define just when a [rewrite] will cause circularity. See
the very good discussion of this topic in ACLH.
See [break-lemma] for a trick involving use of the forms brr t and
(cw-gstack) for inspecting loops in the rewriter.
B4g. Remember restrictions on permutative rules.
Any rule that permutes the variables in its left hand side could
cause circularity. For example, the following axiom is
automatically supplied by the system:
(defaxiom commutativity-of-+
(equal (+ x y) (+ y x))).
This would obviously lead to dangerous circular rewriting if such
``permutative'' rules were not governed by a further restriction.
The restriction is that such rules will not produce a [term] that
is ``lexicographically larger than'' the original [term] (see
[loop-stopper]). However, this sometimes prevents intended
rewrites. See Chapter 13 of ACLH for a discussion of this problem.
B5. Conditional vs. unconditional rewrite rules.
It's generally preferable to form unconditional [rewrite] rules
unless there is a danger of case explosion. That is, rather than
pairs of rules such as
(implies p
(equal term1 term2))
and
(implies (not p)
(equal term1 term3))
consider:
(equal term1
(if p term2 term3))
However, sometimes this strategy can lead to case explosions: [if]
[term]s introduce cases in ACL2. Use your judgment. (On the subject
of [if]: [cond], [case], [and], and [or] are macros that abbreviate
[if] forms, and propositional functions such as [implies] quickly
expand into [if] [term]s.)
B6. Create elegant theorems.
Try to formulate lemmas that are as simple and general as possible.
For example, sometimes properties about several functions can be
``factored'' into lemmas about one function at a time. Sometimes
the elimination of unnecessary hypotheses makes the theorem easier
to prove, as does generalizing first by hand.
B7. Use [defaxiom]s temporarily to explore possibilities.
When there is a difficult goal that seems to follow immediately (by
a :use hint or by rewriting) from some other lemmas, you can create
those lemmas as [defaxiom] [events] (or, the application of
[skip-proofs] to [defthm] [events]) and then double-check that the
difficult goal really does follow from them. Then you can go back
and try to turn each [defaxiom] into a [defthm]. When you do that,
it's often useful to [disable] any additional [rewrite] rules that
you prove in the process, so that the ``difficult goal'' will still
be proved from its lemmas when the process is complete.
Better yet, rather than disabling [rewrite] rules, use the [local]
mechanism offered by [encapsulate] to make temporary rules
completely [local] to the problem at hand. See [encapsulate] and
see [local].
B9. Use books.
Consider using previously certified [books], especially for
[arithmetic] reasoning. This cuts down the duplication of effort
and starts your specification and proof effort from a richer
foundation. See [community-books].
C. DEALING WITH FAILED PROOFS
C1. Look in proof output for goals that can't be further simplified.
Use the ``[proof-tree]'' utility to explore the proof space.
However, you don't need to use that tool to use the ``checkpoint''
strategy. The idea is to think of ACL2 as a ``simplifier'' that
either proves the theorem or generates some goal to consider. That
goal is the first ``checkpoint,'' i.e., the first goal that does
not further simplify. Exception: it's also important to look at the
induction scheme in a proof by induction, and if induction seems
appropriate, then look at the first checkpoint after the induction
has begun.
Consider whether the goal on which you focus is even a theorem.
Sometimes you can execute it for particular values to find a
counterexample.
When looking at checkpoints, remember that you are looking for any
reason at all to believe the goal is a theorem. So for example,
sometimes there may be a contradiction in the hypotheses.
Don't be afraid to skip the first checkpoint if it doesn't seem very
helpful. Also, be willing to look a few lines up or down from the
checkpoint if you are stuck, bearing in mind however that this
practice can be more distracting than helpful.
C2. Use the ``break rewrite'' facility.
[Brr] and related utilities let you inspect the ``rewrite stack.''
These can be valuable tools in large proof efforts. See
[break-lemma] for an introduction to these tools, and see
[break-rewrite] for more complete information.
The break facility is especially helpful in showing you why a
particular rewrite rule is not being applied.
C3. Use induction hints when necessary. Of course, if you can define
your functions so that they suggest the correct inductions to ACL2,
so much the better! But for complicated inductions, induction
[hints] are crucial. See [hints] for a description of :induct
[hints].
C4. Use the ``Proof Checker'' to explore.
The [verify] command supplied by ACL2 allows one to explore problem
areas ``by hand.'' However, even if you succeed in proving a
conjecture with [verify], it is useful to prove it without using
it, an activity that will often require the discovery of [rewrite]
rules that will be useful in later proofs as well.
C5. Don't have too much patience.
Interrupt the prover fairly quickly when simplification isn't
succeeding.
C6. Simplify rewrite rules.
When it looks difficult to relieve the hypotheses of an existing
[rewrite] rule that ``should'' apply in a given setting, ask
yourself if you can eliminate a hypothesis from the existing
[rewrite] rule. If so, it may be easier to prove the new version
from the old version (and some additional lemmas), rather than to
start from scratch.
C7. Deal with base cases first.
Try getting past the base case(s) first in a difficult proof by
induction. Usually they're easier than the inductive step(s), and
rules developed in proving them can be useful in the inductive
step(s) too. Moreover, it's pretty common that mistakes in the
statement of a theorem show up in the base case(s) of its proof by
induction.
C8. Use :expand hints. Consider giving :expand [hints]. These are
especially useful when a proof by induction is failing. It's almost
always helpful to open up a recursively defined function that is
supplying the induction scheme, but sometimes ACL2 is too timid to
do so; or perhaps the function in question is [disable]d.
D. PERFORMANCE TIPS
D1. Disable rules.
There are a number of instances when it is crucial to [disable]
rules, including (often) those named explicitly in :use [hints].
Also, [disable] recursively defined functions for which you can
prove what seem to be all the relevant properties. The prover can
spend significant time ``behind the scenes'' trying to open up
recursively defined functions, where the only visible effect is
slowness.
D2. Turn off the ``break rewrite'' facility. Remember to execute :brr
nil after you've finished with the ``break rewrite'' utility (see
[break-rewrite]), in order to bring the prover back up to full
speed.
E. MISCELLANEOUS TIPS AND KNOWLEDGE
E1. Order of application of rewrite rules.
Keep in mind that the most recent [rewrite] rules in the [history]
are tried first.
E2. Relieving hypotheses is not full-blown theorem proving.
Relieving hypotheses on [rewrite] rules is done by rewriting and
[linear] arithmetic alone, not by case splitting or by other prover
processes ``below'' simplification.
E3. ``Free variables'' in rewrite rules.
The set of ``free variables'' of a [rewrite] rule is defined to
contain those variables occurring in the rule that do not occur in
the left-hand side of the rule. It's often a good idea to avoid
rules containing free variables because they are ``weak,'' in the
sense that hypotheses containing such variables can generally only
be proved when they are ``obviously'' present in the current
context. This weakness suggests that it's important to put the most
``interesting'' (specific) hypotheses about free variables first,
so that the right instances are considered. For example, suppose
you put a very general hypothesis such as (consp x) first. If the
context has several [term]s around that are known to be [consp]s,
then x may be bound to the wrong one of them. For much more
information on free variables, see [free-variables].
E4. Obtaining information
Use :[pl] foo to inspect [rewrite] rules whose left hand sides are
applications of the function foo. Another approach to seeing which
[rewrite] rules apply is to enter the [proof-checker] with
[verify], and use the show-rewrites or sr command.
E5. Consider esoteric rules with care.
If you care to see [rule-classes] and peruse the list of subtopics
(which will be listed right there in most versions of this
[documentation]), you'll see that ACL2 supports a wide variety of
rules in addition to :[rewrite] rules. Should you use them? This is
a complex question that we are not ready to answer with any
generality. Our general advice is to avoid relying on such rules as
long as you doubt their utility. More specifically: be careful not
to use conditional type prescription rules, as these have been
known to bring ACL2 to its knees, unless you are conscious that you
are doing so and have reason to believe that they are working well.
F. SOME THINGS YOU DON'T NEED TO KNOW
Most generally: you shouldn't usually need to be able to predict too
much about ACL2's behavior. You should mainly just need to be able
to react to it.
F1. Induction heuristics.
Although it is often important to read the part of the prover's
output that gives the induction scheme chosen by the prover, it is
not necessary to understand how the prover made that choice.
(Granted, advanced users may occasionally gain minor insight from
such knowledge. But it's truly minor in many cases.) What is
important is to be able to tell it an appropriate induction when it
doesn't pick the right one (after noticing that it doesn't). See C3
above.
F2. Heuristics for expanding calls of recursively defined functions.
As with the previous topic, the important thing isn't to understand
these heuristics but, rather, to deal with cases where they don't
seem to be working. That amounts to supplying :expand [hints] for
those calls that you want opened up, which aren't. See also C8
above.
F3. The ``waterfall''.
As discussed many times already, a good strategy for using ACL2 is
to look for checkpoints (goals stable under simplification) when a
proof fails, perhaps using the [proof-tree] facility. Thus, it is
reasonable to ignore almost all the prover output, and to avoid
pondering the meaning of the other ``processes'' that ACL2 uses
besides simplification (such as elimination, cross-fertilization,
generalization, and elimination of irrelevance). For example, you
don't need to worry about prover output that mentions ``type
reasoning'' or ``abbreviations,'' for example.")
(TOGGLE-PC-MACRO
(PROOF-CHECKER)
"Change an ordinary macro command to an atomic macro, or vice-versa
Example:
(toggle-pc-macro pro)
Change pro from an atomic macro command to an ordinary one (or
vice-versa, if pro happens to be an ordinary macro command)
General Form:
(toggle-pc-macro name &optional new-tp)
If name is an atomic macro command then this turns it into an
ordinary one, and vice-versa. However, if new-tp is supplied and
not nil, then it should be the new type (the symbol macro or
atomic-macro, in any package), or else there is no change.")
(TOP-LEVEL
(MISCELLANEOUS)
"Evaluate a top-level form as a function body
Some forms, such as calls of [with-local-stobj], are illegal when
supplied directly to the ACL2 top-level loop. The macro top-level
provides a workaround in such cases, by defining a temporary
:[program]-mode function named top-level-fn whose only argument is
state and whose body is the form to be evaluated. When the call of
top-level returns there is no change to the existing ACL2 logical
[world]. The following edited log illustrates all of the above
points.
ACL2 !>:pbt 0
0 (EXIT-BOOT-STRAP-MODE)
ACL2 !>(defstobj st fld)
Summary
Form: ( DEFSTOBJ ST ...)
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
ST
ACL2 !>(top-level
(with-local-stobj
st
(mv-let (result st)
(let ((st (update-fld 17 st)))
(mv (fld st) st))
result)))
17
ACL2 !>(top-level
(with-local-stobj
st
(mv-let (result st)
(let ((st (update-fld 17 st)))
(mv (fld st) st))
(mv nil result state))))
17
ACL2 !>(top-level
(with-local-stobj
st
(mv-let (result st)
(let ((st (update-fld 17 st)))
(mv (fld st) st))
(mv result state))))
(17 <state>)
ACL2 !>:pbt 0
0 (EXIT-BOOT-STRAP-MODE)
d 1:x(DEFSTOBJ ST FLD)
ACL2 !>
Each argument of top-level after the first should be a [declare] form
or [documentation] string, as the list of these extra arguments
will be placed before the first argument when forming the
definition of top-level-fn.
[Top-level] generates a call of [ld], so that the value returned is
printed in the normal way. The call of [top-level] itself actually
evaluates to (mv erp :invisible state), where erp is t if and only
evaluation of the call of top-level-fn caused an error, which
normally results in no additional output. (For details about
``caused an error'', see the definition of top-level in the ACL2
source code, and see [ld-error-action].)")
(TRACE
(DEBUGGING)
"Tracing functions in ACL2
ACL2 provides a trace utility, [trace$], with corresponding reverse
operation [untrace$]. These can be used without any dependence on
the underlying Lisp utility, and are the tracing utilities of
choice in ACL2; see [trace$] and see [untrace$].
However, for advanced users we note that the underlying host Lisp may
also provide a trace utility, trace, and corresponding untrace.
Moreover, these have been modified in the case that the host Lisp
is GCL, Allegro CL, or CCL (OpenMCL), to provide limited support
for :entry, :exit, and perhaps :cond keywords, to hide certain
large data structures (world, enabled structure, rewrite constant),
and to trace executable counterparts. See source files
*-trace.lisp. For the above Lisps, you can invoke the original
trace and untrace by invoking old-trace and old-untrace,
respectively, in raw Lisp rather than in the normal ACL2 loop.
Subtopics
[Break-on-error]
Break when encountering a hard or soft error caused by ACL2
[Close-trace-file]
Stop redirecting trace output to a file
[Open-trace-file]
Redirect trace output to a file
[Set-trace-evisc-tuple]
Set the trace evisc tuple
[Trace!]
Trace the indicated functions after creating an active trust tag
[Trace$]
Trace function evaluations
[Untrace$]
Untrace functions
[Wet]
Evaluate a form and print subsequent error trace")
(TRACE!
(TRACE)
"Trace the indicated functions after creating an active trust tag
Example:
(trace! (fact :native t :entry *foo*))
General Form:
(trace! spec1 ... specn)
where the speci are suitable arguments to [trace$].
See [trace$] for a way to trace function calls. Some calls of trace$
are potentially dangerous and thus require a trust tag (see
[defttag]). But it can be a nuisance to call defttag explicitly, so
the trace! macro is provided in order to avoid the need to do that:
trace! automatically defines a (temporary) trust tag.
See [untrace$] for how to undo the effect of [trace!].
The evaluation of a trace! form causes temporary creation of an
active trust tag, :trace!, followed by the corresponding trace$
form. The trust tag will disappear when the call to trace!
completes. Even though trace! will remove its temporary ttag, it
will still print a ``TTAG NOTE'', which indicates that the session
is suspect. See [defttag] and see [ttags-seen] for further remarks
on this issue.
Because of the active trust tag, it is possible to do things with
trace! that are useful but without logical justification. Below is
an example of how to use trace! to cause a function call to change
[state], even though the function does not take [state] as a
parameter.
ACL2 !>(defun fact (n)
(declare (xargs :guard (natp n) :verify-guards nil))
(if (zp n)
1
(* n (fact (1- n)))))
The admission of FACT is trivial, using the relation O< (which is known
to be well-founded on the domain recognized by O-P) and the measure
(ACL2-COUNT N). We observe that the type of FACT is described by the
theorem (AND (INTEGERP (FACT N)) (< 0 (FACT N))). We used the :compound-
recognizer rule ZP-COMPOUND-RECOGNIZER and primitive type reasoning.
Summary
Form: ( DEFUN FACT ...)
Rules: ((:COMPOUND-RECOGNIZER ZP-COMPOUND-RECOGNIZER)
(:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FACT
ACL2 !>(defun update-foo (n value state)
(declare (xargs :stobjs state :verify-guards nil))
(assign foo (cons (cons n value) (@ foo))))
Since UPDATE-FOO is non-recursive, its admission is trivial. We observe
that the type of UPDATE-FOO is described by the theorem
(AND (CONSP (UPDATE-FOO N VALUE STATE))
(TRUE-LISTP (UPDATE-FOO N VALUE STATE))).
We used primitive type reasoning.
(UPDATE-FOO * * STATE) => (MV * * STATE).
Summary
Form: ( DEFUN UPDATE-FOO ...)
Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
UPDATE-FOO
ACL2 !>(trace! (fact :exit (update-foo n value state)))
TTAG NOTE: Adding ttag :TRACE! from the top level loop.
((FACT :EXIT (UPDATE-FOO N VALUE STATE)))
ACL2 !>(assign foo nil)
NIL
ACL2 !>(fact 7)
1> (ACL2_*1*_ACL2::FACT 7)
2> (ACL2_*1*_ACL2::FACT 6)
3> (ACL2_*1*_ACL2::FACT 5)
4> (ACL2_*1*_ACL2::FACT 4)
5> (ACL2_*1*_ACL2::FACT 3)
6> (ACL2_*1*_ACL2::FACT 2)
7> (ACL2_*1*_ACL2::FACT 1)
8> (ACL2_*1*_ACL2::FACT 0)
<8 NIL
<7 NIL
<6 NIL
<5 NIL
<4 NIL
<3 NIL
<2 NIL
<1 NIL
5040
ACL2 !>(@ foo)
((7 . 5040)
(6 . 720)
(5 . 120)
(4 . 24)
(3 . 6)
(2 . 2)
(1 . 1)
(0 . 1))
ACL2 !>(verify-guards fact)
Computing the guard conjecture for FACT....
The guard conjecture for FACT is trivial to prove, given the :compound-
recognizer rules NATP-COMPOUND-RECOGNIZER and ZP-COMPOUND-RECOGNIZER,
primitive type reasoning and the :type-prescription rule FACT. FACT
is compliant with Common Lisp.
Summary
Form: ( VERIFY-GUARDS FACT)
Rules: ((:COMPOUND-RECOGNIZER NATP-COMPOUND-RECOGNIZER)
(:COMPOUND-RECOGNIZER ZP-COMPOUND-RECOGNIZER)
(:FAKE-RUNE-FOR-TYPE-SET NIL)
(:TYPE-PRESCRIPTION FACT))
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
FACT
ACL2 !>(assign foo nil)
NIL
ACL2 !>(fact 7)
1> (ACL2_*1*_ACL2::FACT 7)
2> (FACT 7)
3> (FACT 6)
4> (FACT 5)
5> (FACT 4)
6> (FACT 3)
7> (FACT 2)
8> (FACT 1)
9> (FACT 0)
<9 NIL
<8 NIL
<7 NIL
<6 NIL
<5 NIL
<4 NIL
<3 NIL
<2 NIL
<1 NIL
5040
ACL2 !>(@ foo)
((7 . 5040)
(7 . 5040)
(6 . 720)
(5 . 120)
(4 . 24)
(3 . 6)
(2 . 2)
(1 . 1)
(0 . 1))
ACL2 !>(trace! (fact :exit (progn (update-foo n value state)
(cons traced-fn values))))
TTAG NOTE: Adding ttag :TRACE! from the top level loop.
((FACT :EXIT (PROGN (UPDATE-FOO N VALUE STATE)
(CONS TRACED-FN VALUES))))
ACL2 !>(assign foo nil)
NIL
ACL2 !>(fact 7)
1> (ACL2_*1*_ACL2::FACT 7)
2> (FACT 7)
3> (FACT 6)
4> (FACT 5)
5> (FACT 4)
6> (FACT 3)
7> (FACT 2)
8> (FACT 1)
9> (FACT 0)
<9 (FACT 1)
<8 (FACT 1)
<7 (FACT 2)
<6 (FACT 6)
<5 (FACT 24)
<4 (FACT 120)
<3 (FACT 720)
<2 (FACT 5040)
<1 (ACL2_*1*_ACL2::FACT 5040)
5040
ACL2 !>(@ foo)
((7 . 5040)
(7 . 5040)
(6 . 720)
(5 . 120)
(4 . 24)
(3 . 6)
(2 . 2)
(1 . 1)
(0 . 1))
ACL2 !>
Finally, we remark that using trace! can cause errors in situations
where tracing is automatically suspended and re-introduced. This is
likely to be a rare occurrence, but consider the following example.
(trace! (lexorder :native t :multiplicity 1))
(certify-book \"foo\" 0 t)
If the certify-book causes compilation, you may see an error such as
the following.
ACL2 Error in (CERTIFY-BOOK \"foo\" ...): The keyword :NATIVE cannot
be used in a trace spec unless there is an active trust tag. The trace
spec (LEXORDER :NATIVE T :MULTIPLICITY 1) is thus illegal. Consider
using trace! instead. The complete list of keywords that require a
trust tag for use in a trace spec is: (:NATIVE :DEF :MULTIPLICITY).
This error is harmless. The function will appear, when calling
(trace$), to remain traced, but in fact there will be no tracing
behavior, so you may want to call [untrace$] on the function symbol
in question.")
(TRACE$
(TRACE)
"Trace function evaluations
Examples:
(trace$ foo bar) ; trace foo and bar
(trace$) ; return current trace info (no new tracing specified)
(trace$ (foo :entry ; trace foo, printing first actual parameter upon entry
(car arglist)))
(trace$ (foo :exit ; trace foo, using fmt to print upon exit
(:fmt (msg \"Exiting FOO with ~x0\"
value))))
(trace$ (foo :native t))
General Forms:
(trace$ spec1 spec2 ... specn) ; n >= 1
(trace$)
where the speci are trace specs, as described below.
Trace$ installs alternate code for the indicated functions that
prints information upon entry to, and exit from, calls of the
functions. For an alternate tracing utility used for educational
purposes in {ACL2s | http://acl2s.ccs.neu.edu/acl2s/doc/}, see
community book books/misc/trace-star.lisp.
From a logical perspective all trace printing is a fiction. (But see
[trace!] for a way to get around this and modify [state].) For a
related fiction, see [cw]. (Trace$) returns the list of
currently-active trace specs, while the application of trace$ to at
least one argument returns the list of its arguments that are
successfully acted on.
Output from [trace$] normally goes to the screen, i.e., to
[standard-co]. But it can be redirected to a file; see
[open-trace-file].
See [untrace$] for how to undo the effect of [trace$]. Also see
[trace] for mention of modifications made to raw Lisp trace, which
is accessible (as described below) using the :native keyword.
Note that when trace$ is applied to a function without option
:native, that function's declarations and documentation are
discarded.
Next, we introduce tracing with some examples. After that, we provide
reference documentation for individual trace options allowed in a
trace spec. Note that although our example focuses on user-defined
functions, trace$ can also be applied to built-in functions, though
perhaps only system hackers should take advantage of this
observation.
We begin by illustrating the simplest sort of trace spec: a function
symbol. For example, the form (trace$ foo bar) directs the tracing
of functions foo and bar by virtue of the two trace specs foo and
bar. We can see tracing in action by first defining:
(defun f (x)
(cons x x))
(defun g (x)
(list (f x) 3))
The following log then illustrates tracing of these two functions.
Notice that before [guard]s have been verified, the so-called
``*1*'' functions (sometimes called ``executable counterpart
functions'' or ``logic functions'') are called but the
corresponding raw Lisp functions are not; but after guard
verification of f, the raw Lisp counterpart of f is indeed called.
(See [guard] and see [guard-evaluation-examples-log].)
ACL2 !>(trace$ f g)
((F) (G))
ACL2 !>(g 7)
1> (ACL2_*1*_ACL2::G 7)
2> (ACL2_*1*_ACL2::F 7)
<2 (ACL2_*1*_ACL2::F (7 . 7))
<1 (ACL2_*1*_ACL2::G ((7 . 7) 3))
((7 . 7) 3)
ACL2 !>(verify-guards f)
Computing the guard conjecture for F....
The guard conjecture for F is trivial to prove. F is compliant with
Common Lisp.
Summary
Form: ( VERIFY-GUARDS F)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
F
ACL2 !>(g 7)
1> (ACL2_*1*_ACL2::G 7)
2> (ACL2_*1*_ACL2::F 7)
3> (F 7)
<3 (F (7 . 7))
<2 (ACL2_*1*_ACL2::F (7 . 7))
<1 (ACL2_*1*_ACL2::G ((7 . 7) 3))
((7 . 7) 3)
ACL2 !>
The following example introduces trace specs other than function
symbols. Consider the following definition.
(defun fact (n)
(declare (xargs :guard (natp n)))
(if (zp n)
1
(* n (fact (1- n)))))
The following log illustrates the use of trace options :cond
(condition for entering trace), :entry (what to print on entry),
and :exit (what to print on exit). The reason for two calls on
argument 4 is that we are seeing such calls for the executable
counterpart of fact and also its raw Lisp function.
ACL2 !>(trace$ (fact :cond (evenp (car arglist))
:entry (cons 'factorial-call arglist)
:exit (car values)))
((FACT :COND (EVENP (CAR ARGLIST))
:ENTRY (CONS 'FACTORIAL-CALL ARGLIST)
:EXIT (CAR VALUES)))
ACL2 !>(fact 4)
1> (FACTORIAL-CALL 4)
2> (FACTORIAL-CALL 4)
3> (FACTORIAL-CALL 2)
4> (FACTORIAL-CALL 0)
<4 1
<3 2
<2 24
<1 24
24
ACL2 !>
Notice that VALUES above is the list of all values returned, which is
a one-element list unless [mv] return is used, as illustrated in
the following example, after defining: (defun two-vals (x) (mv x
7)).
ACL2 !>(trace$ two-vals)
((TWO-VALS))
ACL2 !>(two-vals 3)
1> (ACL2_*1*_ACL2::TWO-VALS 3)
<1 (ACL2_*1*_ACL2::TWO-VALS 3 7)
(3 7)
ACL2 !>(verify-guards two-vals)
Computing the guard conjecture for TWO-VALS....
The guard conjecture for TWO-VALS is trivial to prove, given the :executable-
counterpart of CONS. TWO-VALS is compliant with Common Lisp.
Summary
Form: ( VERIFY-GUARDS TWO-VALS)
Rules: ((:EXECUTABLE-COUNTERPART CONS))
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
TWO-VALS
ACL2 !>(two-vals 3)
1> (ACL2_*1*_ACL2::TWO-VALS 3)
2> (TWO-VALS 3)
<2 (TWO-VALS 3 7)
<1 (ACL2_*1*_ACL2::TWO-VALS 3 7)
(3 7)
ACL2 !>
We now document all of the options that may appear in a trace spec. A
trace spec with options is of the form
(fn :kwd1 val1 :kwd2 val2 ... :kwdn valn)
and here we document each legal keyword :kwdi and corresponding
expected value vali. Note that trace$ is intended primarily for
functions defined in the ACL2 command loop (see [lp]). If you want
to trace a function that is defined in raw Lisp, then you can use
option :native (see below), but then many other trace$ options will
not be available to you: all of them except :multiplicity and
:native itself will be passed directly to the trace utility of the
underlying Common Lisp.
:COND, :ENTRY, and :EXIT
Introduction. For each of these three options, the value is a
(user-level) term, except that for :entry and :exit the value can
be of the form (:fmt u) or (:fmt! u), where u is a user-level term.
We skip these two latter cases for now and return to them later.
Then the indicated term is evaluated as indicated in the next
paragraph, and if the :cond term is omitted or evaluates to
non-nil, then the value of the :entry term is printed on entry and
the value of the :exit term is printed on exit. By default, where
:entry is omitted or is specified as nil, the value printed for
:entry is the list obtained by consing the calling function symbol
onto the list of actual parameters: in the notation described
below, this is (cons TRACED-FN ARGLIST). Similarly, the default for
printing at the exit of the function call, i.e. where :exit is
omitted or is specified as nil, is (cons TRACED-FN VALUES) where
VALUES is the list of values returned as described below.
Available Variables. In the evaluations of the term described below
upon a call of fn, each formal parameter of the definition of fn
will be bound to the corresponding actual of the call, the variable
ARGLIST will be bound to the list of actuals, and the variable
TRACED-FN will be bound to the function being called (either fn or
its executable counterpart function; see above). Additionally in
the case of :exit, the variable VALUES will be bound to the
multiple values returned (thus, a one-element list if [mv] is not
used in the return). Also for :exit, we bind VALUE to the logical
value returned, i.e., to the suitable list of values returned in
the [mv] case and otherwise to the single value returned. So in the
mv case, VALUE is the same as VALUES, and otherwise VALUE is (car
VALUES). Other than these variables and [state], no other variable
may occur in the term, whose value must be a single non-[stobj]
value, unless there is an active trust tag (see [defttag]).
Now suppose fn is called. First: If :cond is supplied and the result
of evaluating the :cond term is nil, then no tracing is done.
Otherwise tracing proceeds as follows. First the :entry form is
evaluated, and the result is printed. Then the call of fn is
evaluated. Finally the :exit term is evaluated and the result is
printed. As indicated above, the default for the :entry term if
omitted or explicitly nil is (cons TRACED-FN ARGLIST), and the
default for the :exit term if omitted or explicitly nil is (cons
TRACED-FN VALUES).
Note that if the function has a formal named ARGLIST, then ARGLIST
will nevertheless refer to the entire list of formals, not the
single formal named ARGLIST; similarly for TRACED-FN, and
additionally for VALUE and VALUES in the case of :exit.
As mentioned above, for each of :entry and :exit, a value of nil
specifies the default behavior. If you really want a value of nil,
use a non-nil form that evaluates to nil, for example (car nil) or
'nil. However, for :cond a value of nil means what it says: do not
evaluate the :entry or :exit forms.
Finally we discuss the case that the :entry or :exit term is of the
form (:fmt u) or (:fmt! u). In these cases, the term u is evaluated
as described above to produce a value, say msg, but instead of
printing msg directly, ACL2 calls fmt1 using the string \"~@0\" and
the alist that binds just character #\\0 to msg. The following
example illustrates this point, where fact is defined as above.
Also see [fmt]. Note that (msg string . vals) produces a value
suitable for a \"~@\" directive to the fmt family of print functions.
ACL2 !>(trace$
(fact
:entry (:fmt (msg \"Tracing ~x0 on ~x1\" traced-fn arglist))
:exit (car values)))
((FACT :ENTRY (:FMT (MSG \"Tracing ~x0 on ~x1\" TRACED-FN ARGLIST))
:EXIT (CAR VALUES)))
ACL2 !>(fact 3)
1> Tracing ACL2_*1*_ACL2::FACT on (3)
2> Tracing FACT on (3)
3> Tracing FACT on (2)
4> Tracing FACT on (1)
5> Tracing FACT on (0)
<5 1
<4 1
<3 2
<2 6
<1 6
6
ACL2 !>
If :fmt! is used instead of :fmt, then indentation as is the prefix
string, \"n> \" or \"<n \". The following example illustrates the use
of :fmt!.
ACL2 !>(trace$
(fact
:entry (:fmt! (msg \"Tracing ~x0 on ~x1\" traced-fn arglist))
:exit (:fmt! (msg \"From input ~x0: ~x1\"
(car arglist) (car values)))))
((FACT :ENTRY (:FMT! (MSG \"Tracing ~x0 on ~x1\" TRACED-FN ARGLIST))
:EXIT (:FMT! (MSG \"From input ~x0: ~x1\" (CAR ARGLIST)
(CAR VALUES)))))
ACL2 !>(fact 3)
Tracing ACL2_*1*_ACL2::FACT on (3)
Tracing FACT on (3)
Tracing FACT on (2)
Tracing FACT on (1)
Tracing FACT on (0)
From input 0: 1
From input 1: 1
From input 2: 2
From input 3: 6
From input 3: 6
6
ACL2 !>
Here is the same example, with user-managed indentation.
ACL2 !>(trace$
(fact
:entry (:fmt! (msg \"~t0Tracing ~x1 on ~x2\"
(+ 3 (* 2 (@ trace-level)))
traced-fn arglist))
:exit (:fmt! (msg \"~t0From input ~x1: ~x2\"
(1+ (* 2 (@ trace-level)))
(car arglist) (car values)))))
((FACT :ENTRY (:FMT! (MSG \"~t0Tracing ~x1 on ~x2\"
(+ 3 (* 2 (@ TRACE-LEVEL)))
TRACED-FN ARGLIST))
:EXIT (:FMT! (MSG \"~t0From input ~x1: ~x2\"
(1+ (* 2 (@ TRACE-LEVEL)))
(CAR ARGLIST)
(CAR VALUES)))))
ACL2 !>(fact 3)
Tracing ACL2_*1*_ACL2::FACT on (3)
Tracing FACT on (3)
Tracing FACT on (2)
Tracing FACT on (1)
Tracing FACT on (0)
From input 0: 1
From input 1: 1
From input 2: 2
From input 3: 6
From input 3: 6
6
ACL2 !>
ADVANCED OPTIONS (alphabetical list)
:COMPILE
The tracing of fn installs a substitute definition of fn that prints
trace information. If the :compile option is omitted or has value
:same, then the new definition will be compiled if and only if the
existing definition is already compiled. Otherwise, the new
definition will be compiled exactly when the value of :compile is
not nil.
:DEF, :MULTIPLICITY
ACL2's trace$ mechanism often needs to know the number of outputs of
a traced function, in the sense of [mv]. If you trace a function
that was not defined inside the ACL2 loop (hence you are using the
:native option), or if you provide an alternative definition using
option :def (see below) and the new definition changes the number
of values returned, then a natural number value for :multiplicity
informs the trace utility of the number of expected outputs of the
function being traced. In the case that :native is supplied, the
effect of a non-nil :multiplicity value depends on the host Lisp.
In the case of Lisps for which ACL2 uses the built-in Lisp
mechanism for returning multiple values (see [mv]), which are CCL
and threaded SBCL as of June, 2010, :multiplicity is not needed and
is ignored with :native t. For GCL and Allegro CL, :multiplicity is
used to generate a suitable :exit form if the :exit keyword was not
already supplied. For the other Lisps, the :multiplicity value is
treated essentially as 1 whether it is supplied or not, because we
do not know how to pass suitable information based on this value to
the host Lisp's built-in tracing mechanism.
Note that even supplying a :multiplicity option does not change the
meaning of the variable values. See the discussion of :native
below.
A useful option can be to supply a definition as the value of :def.
(Again, note that if :native is used, then all options other than
:multiplicity are passed directly to the underlying Lisp; in
particular, :def will have no effect with :native except in the
unlikely case that the raw Lisp provides some sort of support for
:def.) Note that this definition should be like a [defun] form, but
without the leading defun symbol; and it should define the function
symbol being traced, with the same formal parameter list. However,
tracing of the so-called ``executable counterpart'' of a function
(sometimes referred to as the ``*1* function'', for evaluation in
the ACL2 loop; see [guards] for related discussion) is not
sensitive to the :def option; rather, if a function has an
executable counterpart then that executable counterpart is traced.
:EVISC-TUPLE
The printing described above is, by default, done using the current
default trace evisc-tuple, which can be set using
[set-trace-evisc-tuple] (for the shape of this tuple, see
[evisc-tuple]); see [set-trace-evisc-tuple]. This tuple is based by
default on the raw Lisp variables *print-level* and *print-length*,
and will hide the ACL2 [world] and handle [stobj]s appropriately.
You may override this default by supplying an evisc tuple with the
:evisc-tuple argument in your trace spec. Be careful to supply a
valid evisc-tuple, or you may get a raw Lisp error!
A special value, :print, is useful if you are doing system hacking
that can produce objects that are not valid ACL2 objects, such as
raw Lisp arrays or objects in supporting packages not visible in
the ACL2 read-eval-print loop. If you supply :evisc-tuple :print,
then the printing described above will be done with raw Lisp
printing rather than ACL2 printing: specifically, with (format
*trace-output* \"s%\" x), where x is the value to be printed.
A second special value for :evisc-tuple, :no-print, avoids printing
the values of the :entry and :exit forms (or their defaults, if not
specified). This option is of use for side effects; for an example
see community book books/misc/wet.lisp.
Note that if :evisc-tuple X is supplied, then the form X will be
evaluated before the function body is entered. You can thus pull
some tricks to print extra information before the :entry form is
evaluated, for example as follows for a factorial function, fact.
ACL2 !>(trace$ (fact :evisc-tuple
(prog2$ (cw \"~|**** HERE IS CW ****~|\")
nil)))
((FACT :EVISC-TUPLE (PROG2$ (CW \"~|**** HERE IS CW ****~|\")
NIL)))
ACL2 !>(fact 3)
**** HERE IS CW ****
1> (ACL2_*1*_ACL2::FACT 3)
**** HERE IS CW ****
2> (ACL2_*1*_ACL2::FACT 2)
**** HERE IS CW ****
3> (ACL2_*1*_ACL2::FACT 1)
**** HERE IS CW ****
4> (ACL2_*1*_ACL2::FACT 0)
<4 (ACL2_*1*_ACL2::FACT 1)
<3 (ACL2_*1*_ACL2::FACT 1)
<2 (ACL2_*1*_ACL2::FACT 2)
<1 (ACL2_*1*_ACL2::FACT 6)
6
ACL2 !>
:FORMALS
Normally ACL2 can figure out the formals for a given function. This
is always the case for functions defined in the ACL2 command loop
and when option :def is supplied. If neither of these cases applies
then you can still trace a function (even without using the :native
option) by supplying option :notinline :fncall, but you will still
need to supply the list of formal parameters. The value of the
:formals option should be the list of formals in this case.
:HIDE
The default value for this advanced option is t, which causes
[stobj]s and the logical [world] to be printed as single symbols,
along with certain large structures of interest to developers
(rewrite contants, enabled structures, and event and command index
structures). If however the value nil is supplied, then this
default behavior is defeated. In that case, you can still arrange
to print the logical world as a symbol and to print [stobj]s
without breaking the trace printing: see [set-trace-evisc-tuple]
for how to do this globally, or similarly use the :evisc-tuple
option to trace$ to do this with a single trace spec. Note however
that with value nil specified for :hide, such use of an evisc-tuple
will not deal properly with local stobjs (see [with-local-stobj])
or stobjs bound by [stobj-let], or with the aforementioned large
structures other than the logical [world].
:NATIVE
If :native is supplied with a non-nil value, then the trace spec is
passed to the native Lisp trace (after removing the :native
option). A trust tag (see [defttag]) is required in order to use
this option, because no syntactic check is made on the :cond,
:entry, or :exit forms -- arbitrary raw Lisp may occur in them!
Note that by ``native Lisp trace'' we mean the currently installed
trace. As discussed briefly elsewhere (see [trace]), ACL2 has
modified that trace to be more useful if the underlying host Lisp
is GCL, Allegro CL, or CCL (OpenMCL). If you need the original
trace utility supplied for those Lisps, quit the ACL2 loop with :q
and call old-trace and old-untrace in raw Lisp where you would
otherwise call trace and untrace. Note that the original trace
utility supplied with a given Lisp will not hide the ACL2 logical
[world] or give special treatment to [stobj]s.
It is important to understand that if :native t is specified, then
all other options are interpreted by the native Lisp trace. For
example, that trace probably has no understanding of the use of
:fmt described above for :entry or :exit. Indeed, the native trace
may not even accept any of :cond, :entry or :exit, let alone any of
the advanced options! Moreover, if :native t is specified, then
even a :multiplicity option does not provide the meaning of the
variable values that one might desire. In GCL for example, in the
case of an [mv] return of a function defined only in raw Lisp (not
in ACL2), this variable will be bound to a list containing only the
first result.
:NOTINLINE
By default, a new definition installed by trace$ will include a
notinline declaration so that recursive calls will always be
traced. To avoid this declaration, supply value nil.
A special value for :notinline, :fncall, will cause the traced
function to call its original definition. Without this special
value, the new installed definition for the traced function will
include the body of the original definition. This :fncall behavior
is the default only in the following cases:
* for functions whose definitions are built into ACL2;
* for functions that have been added (using a trust tag, an advanced
feature, so most users can probably ignore this case) to either
of the [state] global variables program-fns-with-raw-code or
logic-fns-with-raw-code;
* for [memoize]d functions.
The legal values for :notinline are t (the default for other than the
cases displayed above), nil, and :fncall.
Remarks.
(1) If some of the given trace specs have errors, then trace$ will
generally print error messages for those but will still process
those that do not have errors. The value returned will indicate the
trace specs that were processed successfully.
(2) If you certify or include a book that redundantly defines a
function that is currently traced, then tracing behavior may
disappear if a compiled definition is installed for the function or
its in-the-logic (so-called `*1*') counterpart.
(3) Some predefined functions are called during tracing. In order to
avoid infinite loops, such calls of traced predefined functions
will be made using the original predefined functions, not using
their code installed by trace$.")
(TRANS
(MACROS)
"Print the macroexpansion of a form
Examples:
:trans (list a b c)
:trans (caddr x)
:trans (cond (p q) (r))
This function takes one argument, an alleged term, and translates it,
expanding the macros in it completely. Either an error is caused or
the formal meaning of the term is printed. We also print the
``output signature'' which indicates how many results are returned
and which are single-threaded objects. For example, a term that
returns one ordinary object (e.g., an object other than [state] or
a user-defined single-threaded object (see [defstobj])) has the
output signature
=> *
A term that returns the single-threaded object STATE has the output
signature
=> STATE
and a term that returns four results might have the output signature
=> (MV $MEM * * STATE)
This signature indicates that the first result is the (user defined)
single-threaded object $MEM, that the next two results are
ordinary, and that the last result is STATE.
See [trans!] for a corresponding command that does not enforce
restrictions of single-threaded objects.
It is sometimes more convenient to use [trans1] which is like trans
but which only does top-level macroexpansion.
For more, see [term].")
(TRANS!
(MACROS)
"Print the macroexpansion of a form without single-threadedness
concerns
Examples:
:trans! (list a b c)
:trans! (append x state)
:Trans! is identical to :[trans], except that unlike :trans, :trans!
ignores single-threadedness restrictions. Thus, the second form
above is legal for :trans!. Also see [trans] and see [trans1].")
(TRANS1
(MACROS)
"Print the one-step macroexpansion of a form
Examples:
:trans1 (list a b c)
:trans1 (caddr x)
:trans1 (cond (p q) (r))
This function takes one argument, an alleged term, and expands the
top-level macro in it for one step only. Either an error is caused,
which happens when the form is not a call of a macro, or the result
is printed. Also see [trans], which translates the given form
completely.")
(TRUE-LIST-LISTP
(LISTS TRUE-LISTP ACL2-BUILT-INS)
"Recognizer for true (proper) lists of true lists
True-list-listp is the function that checks whether its argument is a
list that ends in, or equals, nil, and furthermore, all of its
elements have that property. Also see [true-listp].
Function: <true-list-listp>
(defun true-list-listp (x)
(declare (xargs :guard t))
(cond ((atom x) (eq x nil))
(t (and (true-listp (car x))
(true-list-listp (cdr x))))))")
(TRUE-LISTP
(LISTS ACL2-BUILT-INS)
"Recognizer for proper (null-terminated) lists
True-listp is the function that checks whether its argument is a list
that ends in, or equals, nil.
For a discussion of whether requring lists to be nil-terminated is
right for you, see [std::strict-list-recognizers].
Function: <true-listp>
(defun true-listp (x)
(declare (xargs :guard t))
(if (consp x)
(true-listp (cdr x))
(eq x nil)))
Subtopics
[True-list-listp]
Recognizer for true (proper) lists of true lists")
(TRUNCATE
(NUMBERS ACL2-BUILT-INS)
"Division returning an integer by truncating toward 0
Example Forms:
ACL2 !>(truncate 14 3)
4
ACL2 !>(truncate -14 3)
-4
ACL2 !>(truncate 14 -3)
-4
ACL2 !>(truncate -14 -3)
4
ACL2 !>(truncate -15 -3)
5
ACL2 !>(truncate 10/4 3/4)
3
(Truncate i j) is the result of taking the quotient of i and j and
dropping the fraction. For example, the quotient of -14 by 3 is -4
2/3, so dropping the fraction 2/3, we obtain a result for (truncate
-14 3) of -4.
The [guard] for (truncate i j) requires that i and j are rational
([real], in ACL2(r)) numbers and j is non-zero.
Truncate is a Common Lisp function. However, note that unlike Common
Lisp, the ACL2 truncate function returns only a single value, Also
see [nonnegative-integer-quotient], which is appropriate for
integers and may simplify reasoning, unless a suitable arithmetic
library is loaded, but be less efficient for evaluation on concrete
objects.
Function: <truncate>
(defun truncate (i j)
(declare (xargs :guard (and (real/rationalp i)
(real/rationalp j)
(not (eql j 0)))))
(let* ((q (* i (/ j)))
(n (numerator q))
(d (denominator q)))
(cond ((= d 1) n)
((>= n 0)
(nonnegative-integer-quotient n d))
(t (- (nonnegative-integer-quotient (- n)
d))))))")
(TRUST-TAG (POINTERS) "See [defttag].")
(TTAG (POINTERS) "See [defttag].")
(TTAGS-SEEN
(MISCELLANEOUS)
"List some declared trust tags (ttags)
General Forms:
:ttags-seen
(ttags-seen)
Suppose the output is as follows.
(T NIL)
(FOO \"/home/bob/bar.lisp\"
\"/home/cindy/bar.lisp\")
Warning: This output is minimally trustworthy (see :DOC TTAGS-SEEN).
This output indicates that the current logical [world] has seen the
declaration of trust tag T at the top-level (see [defttag]) and the
declaration of trust tag FOO in the two books included from the
listed locations. The warning emphasizes that this command cannot
be used to validate the ``purity'' of an ACL2 session, because
using a ttag renders enough power to hide from this or any other
command the fact that the ttag was ever declared.
As discussed elsewhere (see [defttag]), the only reliable way to
validate the ``purity'' of a session is to watch for ``TTAG NOTE''
output.
Another shortcoming of this command is that it only checks the
current logical [world] for ttag declarations. For example, one
could execute a [defttag] event; then use [progn!] and
[set-raw-mode] to replace system functions with corrupt definitions
or to introduce inconsistent axioms in the [ground-zero] [world];
and finally, execute :[ubt!] 1 to remove all evidence of the ttag
in the [world] while leaving in place the corrupt definitions or
axioms. The base world is now tainted, meaning we could prove nil
or certify a book that proves nil, but the resulting session or
book would contain no trace of the ttag that tainted it!
Despite shortcomings, this command might be useful to system hackers.
It also serves to illustrate the inherent flaw in asking a session
whether or how it is ``tainted'', justifying the ``TTAG NOTE''
approach (see [defttag]).")
(TTHM
(HISTORY MEASURE)
"The [measure] (termination) theorem for a given function symbol
Example Forms:
:tthm FN
(tthm 'FN) ; equivalent to the above
where FN is a function symbol. This shows the [measure] (termination)
theorem for FN. More precisely, evaluation of a call of this macro
--- pronounced ``tee-thumb'' --- either results in an error or
returns an [error-triple] whose value component is the user-level
(untranslated) version of that termination theorem. Also see
[lemma-instance] for discussion of a way to specify this theorem as
a :termination-theorem prover hint.
Technical note: a corresponding evaluation that provides a
(translated) [termp] is: (termination-theorem 'FN state).")
(TTREE
(MISCELLANEOUS)
"Tag-trees
Many low-level ACL2 functions take and return ``tag trees'' or
``ttrees'' (pronounced ``tee-trees'') which contain various useful
bits of information such as the lemmas used, the linearize
assumptions made, etc.
Abstractly a tag-tree represents a list of sets, each member set
having a name given by one of the ``tags'' (which are symbols) of
the ttree. The elements of the set named tag are all of the objects
tagged tag in the tree. You are invited to browse the source code.
Definitions of primitives are labeled with the comment ``; Note:
Tag-tree primitive''.
The rewriter, for example, takes a term and a ttree (among other
things), and returns a new term, term', and new ttree, ttree'.
Term' is equivalent to term (under the current assumptions) and the
ttree' is an extension of ttree. If we focus just on the set
associated with the tag LEMMA in the ttrees, then the set for
ttree' is the extension of that for ttree obtained by unioning into
it all the [rune]s used by the rewrite. The set associated with
LEMMA can be obtained by (tagged-objects 'LEMMA ttree).")
(TUTORIAL1-TOWERS-OF-HANOI
(ANNOTATED-ACL2-SCRIPTS)
"The Towers of Hanoi Example
This example was written almost entirely by Bill Young of
Computational Logic, Inc.
We will formalize and prove a small theorem about the famous ``Towers
of Hanoi'' problem. This problem is illustrated by the following
picture.
| | |
| | |
--- | |
----- | |
------- | |
A B C
We have three pegs --- a, b, and c --- and n disks of different
sizes. The disks are all initially on peg a. The goal is to move
all disks to peg c while observing the following two rules.
1. Only one disk may be moved at a time, and it must start and finish
the move as the topmost disk on some peg;
2. A disk can never be placed on top of a smaller disk.
Let's consider some simple instances of this problem. If n = 1, i.e.,
only one disk is to be moved, simply move it from a to c. If n = 2,
i.e., two disks are to be moved, the following sequence of moves
suffices: move from a to b, move from a to c, move from b to c.
In this doc topic we will show an ACL2 function that generates a
suitable list of moves for a tower of n disks. Then we will use
ACL2 to prove that the number of moves is (- (expt 2 n) 1). For an
ACL2 script that proves the correctness of (a version of) this
function, see the community book \"misc/hanoi.lisp\" in the books
directory of your ACL2 sources.
In general, this problem has a straightforward recursive solution.
Suppose that we desire to move n disks from a to c, using b as the
intermediate peg. For the basis, we saw above that we can always
move a single disk from a to c. Now if we have n disks and assume
that we can solve the problem for n-1 disks, we can move n disks as
follows. First, move n-1 disks from a to b using c as the
intermediate peg; move the single disk from a to c; then move n-1
disks from b to c using a as the intermediate peg.
In ACL2, we can write a function that will return the sequence of
moves. One such function is as follows. Notice that we have two
base cases. If (zp n) then n is not a positive integer; we treat
that case as if n were 0 and return an empty list of moves. If n is
1, then we return a list containing the single appropriate move.
Otherwise, we return the list containing exactly the moves dictated
by our recursive analysis above.
(defun move (a b)
(list 'move a 'to b))
(defun hanoi (a b c n)
(if (zp n)
nil
(if (equal n 1)
(list (move a c))
(append (hanoi a c b (1- n))
(cons (move a c)
(hanoi b a c (1- n)))))))
Notice that we give hanoi four arguments: the three pegs, and the
number of disks to move. It is necessary to supply the pegs
because, in recursive calls, the roles of the pegs differ. In any
execution of the algorithm, a given peg will sometimes be the
source of a move, sometimes the destination, and sometimes the
intermediate peg.
After submitting these functions to ACL2, we can execute the hanoi
function on various specific arguments. For example:
ACL2 !>(hanoi 'a 'b 'c 1)
((MOVE A TO C))
ACL2 !>(hanoi 'a 'b 'c 2)
((MOVE A TO B)
(MOVE A TO C)
(MOVE B TO C))
ACL2 !>(hanoi 'a 'b 'c 3)
((MOVE A TO C)
(MOVE A TO B)
(MOVE C TO B)
(MOVE A TO C)
(MOVE B TO A)
(MOVE B TO C)
(MOVE A TO C))
From the algorithm it is clear that if it takes m moves to transfer n
disks, it will take (m + 1 + m) = 2m + 1 moves for n+1 disks. From
some simple calculations, we see that we need the following number
of moves in specific cases:
Disks 0 1 2 3 4 5 6 7 ...
Moves 0 1 3 7 15 31 63 127 ...
The pattern is fairly clear. To move n disks requires (2^n - 1)
moves. Let's attempt to use ACL2 to prove that fact.
First of all, how do we state our conjecture? Recall that hanoi
returns a list of moves. The length of the list (given by the
function len) is the number of moves required. Thus, we can state
the following conjecture.
(defthm hanoi-moves-required-first-try
(equal (len (hanoi a b c n))
(1- (expt 2 n))))
When we submit this to ACL2, the proof attempt fails. Along the way
we notice subgoals such as:
Subgoal *1/1'
(IMPLIES (NOT (< 0 N))
(EQUAL 0 (+ -1 (EXPT 2 N)))).
This tells us that the prover is considering cases that are
uninteresting to us, namely, cases in which n might be negative.
The only cases that are really of interest are those in which n is
a non-negative natural number. Therefore, we revise our theorem as
follows:
(defthm hanoi-moves-required
(implies (and (integerp n)
(<= 0 n)) ;; n is at least 0
(equal (len (hanoi a b c n))
(1- (expt 2 n)))))
and submit it to ACL2 again.
Again the proof fails. Examining the proof script we encounter the
following text. (How did we decide to focus on this goal? Some
information is provided in ACLH, and the ACL2 documentation on
[tips] may be helpful. But the simplest answer is: this was the
first goal suggested by the ``[proof-tree]'' tool below the start
of the proof by induction. See [proof-tree].)
Subgoal *1/5''
(IMPLIES (AND (INTEGERP N)
(< 0 N)
(NOT (EQUAL N 1))
(EQUAL (LEN (HANOI A C B (+ -1 N)))
(+ -1 (EXPT 2 (+ -1 N))))
(EQUAL (LEN (HANOI B A C (+ -1 N)))
(+ -1 (EXPT 2 (+ -1 N)))))
(EQUAL (LEN (APPEND (HANOI A C B (+ -1 N))
(CONS (LIST 'MOVE A 'TO C)
(HANOI B A C (+ -1 N)))))
(+ -1 (* 2 (EXPT 2 (+ -1 N))))))
It is difficult to make much sense of such a complicated goal.
However, we do notice something interesting. In the conclusion is a
[term] of the following shape.
(LEN (APPEND ... ...))
We conjecture that the length of the [append] of two lists should be
the sum of the lengths of the lists. If the prover knew that, it
could possibly have simplified this [term] earlier and made more
progress in the proof. Therefore, we need a [rewrite] rule that
will suggest such a simplification to the prover. The appropriate
rule is:
(defthm len-append
(equal (len (append x y))
(+ (len x) (len y))))
We submit this to the prover, which proves it by a straightforward
induction. The prover stores this lemma as a [rewrite] rule and
will subsequently (unless we [disable] the rule) replace [term]s
matching the left hand side of the rule with the appropriate
instance of the [term] on the right hand side.
We now resubmit our lemma hanoi-moves-required to ACL2. On this
attempt, the proof succeeds and we are done.
One bit of cleaning up is useful. We needed the hypotheses that:
(and (integerp n) (<= 0 n)).
This is an awkward way of saying that n is a natural number; natural
is not a primitive data type in ACL2. We could define a function
naturalp, but it is somewhat more convenient to define a macro as
follows:
(defmacro naturalp (x)
(list 'and (list 'integerp x)
(list '<= 0 x)))
Subsequently, we can use (naturalp n) wherever we need to note that a
quantity is a natural number. See [defmacro] for more information
about ACL2 macros. With this macro, we can reformulate our theorem
as follows:
(defthm hanoi-moves-required
(implies (naturalp n)
(equal (len (hanoi a b c n))
(1- (expt 2 n))))).
Another interesting (but much harder) theorem asserts that the list
of moves generated by our hanoi function actually accomplishes the
desired goal while following the rules. When you can state and
prove that theorem, you'll be a very competent ACL2 user.
By the way, the name ``Towers of Hanoi'' derives from a legend that a
group of Vietnamese monks works day and night to move a stack of 64
gold disks from one diamond peg to another, following the rules set
out above. We're told that the world will end when they complete
this task. From the theorem above, we know that this requires
18,446,744,073,709,551,615 moves:
ACL2 !>(1- (expt 2 64))
18446744073709551615
ACL2 !>
We're guessing they won't finish any time soon.")
(TUTORIAL2-EIGHTS-PROBLEM
(ANNOTATED-ACL2-SCRIPTS)
"The Eights Problem Example
This example was written almost entirely by Bill Young of
Computational Logic, Inc.
This simple example was brought to our attention as one that Paul
Jackson has solved using the NuPrl system. The challenge is to
prove the theorem:
for all n > 7, there exist naturals i and j such that: n = 3i + 5j.
In ACL2, we could phrase this theorem using quantification. However
we will start with a constructive approach, i.e., we will show that
values of i and j exist by writing a function that will construct
such values for given n. Suppose we had a function (split n) that
returns an appropriate pair (i . j). Our theorem would be as
follows:
(defthm split-splits
(let ((i (car (split n)))
(j (cdr (split n))))
(implies (and (integerp n)
(< 7 n))
(and (integerp i)
(<= 0 i)
(integerp j)
(<= 0 j)
(equal (+ (* 3 i) (* 5 j))
n)))))
That is, assuming that n is a natural number greater than 7, (split
n) returns values i and j that are in the appropriate relation to
n.
Let's look at a few cases:
8 = 3x1 + 5x1; 11 = 3x2 + 5x1; 14 = 3x3 + 5x1; ...
9 = 3x3 + 5x0; 12 = 3x4 + 5x0; 15 = 3x5 + 5x0; ...
10 = 3x0 + 5x2; 13 = 3x1 + 5x2; 16 = 3x2 + 5x2; ...
Maybe you will have observed a pattern here; any natural number
larger than 10 can be obtained by adding some multiple of 3 to 8,
9, or 10. This gives us the clue to constructing a proof. It is
clear that we can write split as follows:
(defun bump-i (x)
;; Bump the i component of the pair
;; (i . j) by 1.
(cons (1+ (car x)) (cdr x)))
(defun split (n)
;; Find a pair (i . j) such that
;; n = 3i + 5j.
(if (or (zp n) (< n 8))
nil ;; any value is really reasonable here
(if (equal n 8)
(cons 1 1)
(if (equal n 9)
(cons 3 0)
(if (equal n 10)
(cons 0 2)
(bump-i (split (- n 3))))))))
Notice that we explicitly compute the values of i and j for the cases
of 8, 9, and 10, and for the degenerate case when n is not a
natural or is less than 8. For all naturals greater than n, we
decrement n by 3 and bump the number of 3's (the value of i) by 1.
We know that the recursion must terminate because any integer value
greater than 10 can eventually be reduced to 8, 9, or 10 by
successively subtracting 3.
Let's try it on some examples:
ACL2 !>(split 28)
(6 . 2)
ACL2 !>(split 45)
(15 . 0)
ACL2 !>(split 335)
(110 . 1)
Finally, we submit our theorem split-splits, and the proof succeeds.
In this case, the prover is ``smart'' enough to induct according to
the pattern indicated by the function split.
For completeness, we'll note that we can state and prove a quantified
version of this theorem. We introduce the notion split-able to mean
that appropriate i and j exist for n.
(defun-sk split-able (n)
(exists (i j)
(equal n (+ (* 3 i) (* 5 j)))))
Then our theorem is given below. Notice that we prove it by observing
that our previous function split delivers just such an i and j (as
we proved above).
(defthm split-splits2
(implies (and (integerp n)
(< 7 n))
(split-able n))
:hints ((\"Goal\" :use (:instance split-able-suff
(i (car (split n)))
(j (cdr (split n)))))))
Unfortunately, understanding the mechanics of the proof requires
knowing something about the way [defun-sk] works. See [defun-sk] or
see [Tutorial4-Defun-Sk-Example] for more on that subject.")
(TUTORIAL3-PHONEBOOK-EXAMPLE
(ANNOTATED-ACL2-SCRIPTS)
"A Phonebook Specification
The other tutorial examples are rather small and entirely self
contained. The present example is rather more elaborate, and makes
use of a feature that really adds great power and versatility to
ACL2, namely: the use of previously defined collections of lemmas,
in the form of ``[books].''
This example was written almost entirely by Bill Young of
Computational Logic, Inc.
This example is based on one developed by Ricky Butler and Sally
Johnson of NASA Langley for the PVS system, and subsequently
revised by Judy Crow, et al, at SRI. It is a simple phone book
specification. We will not bother to follow their versions closely,
but will instead present a style of specification natural for ACL2.
The idea is to model an electronic phone book with the following
properties.
Our phone book will store the phone numbers of a city.
It must be possible to retrieve a phone number, given a name.
It must be possible to add and delete entries.
Of course, there are numerous ways to construct such a model. A
natural approach within the Lisp/ACL2 context is to use
``association lists'' or ``alists.'' Briefly, an alist is a list of
pairs (key . value) associating a value with a key. A phone book
could be an alist of pairs (name . pnum). To find the phone number
associated with a given name, we merely search the alist until we
find the appropriate pair. For a large city, such a linear list
would not be efficient, but at this point we are interested only in
modeling the problem, not in deriving an efficient implementation.
We could address that question later by proving our alist model
equivalent, in some desired sense, to a more efficient data
structure.
We could build a theory of alists from scratch, or we can use a
previously constructed theory (book) of alist definitions and
facts. By using an existing book, we build upon the work of others,
start our specification and proof effort from a much richer
foundation, and hopefully devote more of our time to the problem at
hand. Unfortunately, it is not completely simple for the new user
to know what [books] are available and what they contain. We hope
later to improve the documentation of the growing collection of
[community-books] that are typically downloaded with ACL2; for now,
the reader is encouraged to look in the README.html file in the
books' top-level directory. For present purposes, the beginning
user can simply take our word that a book exists containing useful
alist definitions and facts. These definitions and lemmas can be
introduced into the current theory using the [command]:
(include-book \"data-structures/alist-defthms\" :dir :system)
This book has been ``certified,'' which means that the definitions
and lemmas have been mechanically checked and stored in a safe
manner. (See [books] and see [include-book] for details.)
Including this book makes available a collection of functions
including the following:
(ALISTP A) ; is A an alist (actually a primitive ACL2 function)
(BIND X V A) ; associate the key X with value V in alist A
(BINDING X A) ; return the value associated with key X in alist A
(BOUND? X A) ; is key X associated with any value in alist A
(DOMAIN A) ; return the list of keys bound in alist A
(RANGE A) ; return the list of values bound to keys in alist A
(REMBIND X A) ; remove the binding of key X in alist A
Along with these function definitions, the book also provides a
number of proved lemmas that aid in simplifying expressions
involving these functions. (See [rule-classes] for the way in which
lemmas are used in simplification and rewriting.) For example,
(defthm bound?-bind
(equal (bound? x (bind y v a))
(or (equal x y)
(bound? x a))))
asserts that x will be bound in (bind y v a) if and only if: either x
= y or x was already bound in a. Also,
(defthm binding-bind
(equal (binding x (bind y v a))
(if (equal x y)
v
(binding x a))))
asserts that the resulting binding will be v, if x = y, or the
binding that x had in a already, if not.
Thus, the inclusion of this book essentially extends our
specification and reasoning capabilities by the addition of new
operations and facts about these operations that allow us to build
further specifications on a richer and possibly more intuitive
foundation.
However, it must be admitted that the use of a book such as this has
two potential limitations:
the definitions available in a book may not be ideal for your
particular problem;
it is (extremely) likely that some useful facts (especially,
[rewrite] rules) are not available in the book and will have to
be proved.
For example, what is the value of binding when given a key that is
not bound in the alist? We can find out by examining the function
definition. Look at the definition of the binding function (or any
other defined function), using the :[pe] command:
ACL2 !>:pe binding
d 33 (INCLUDE-BOOK
\"/slocal/src/acl2/v1-9/books/public/alist-defthms\")
>V d (DEFUN BINDING (X A)
\"The value bound to X in alist A.\"
(DECLARE (XARGS :GUARD (ALISTP A)))
(CDR (ASSOC-EQUAL X A)))
This tells us that binding was introduced by the given [include-book]
form, is currently [disable]d in the current theory, and has the
definition given by the displayed [defun] form. We see that binding
is actually defined in terms of the primitive [assoc-equal]
function. If we look at the definition of [assoc-equal]:
ACL2 !>:pe assoc-equal
V -489 (DEFUN ASSOC-EQUAL (X ALIST)
(DECLARE (XARGS :GUARD (ALISTP ALIST)))
(COND ((ENDP ALIST) NIL)
((EQUAL X (CAR (CAR ALIST)))
(CAR ALIST))
(T (ASSOC-EQUAL X (CDR ALIST)))))
we can see that [assoc-equal] returns nil upon reaching the end of an
unsuccessful search down the alist. So binding returns (cdr nil) in
that case, which is nil. Notice that we could also have
investigated this question by trying some simple examples.
ACL2 !>(binding 'a nil)
NIL
ACL2 !>(binding 'a (list (cons 'b 2)))
NIL
These definitions aren't ideal for all purposes. For one thing,
there's nothing that keeps us from having nil as a value bound to
some key in the alist. Thus, if binding returns nil we don't always
know if that is the value associated with the key in the alist, or
if that key is not bound. We'll have to keep that ambiguity in mind
whenever we use binding in our specification. Suppose instead that
we wanted binding to return some error string on unbound keys.
Well, then we'd just have to write our own version of binding. But
then we'd lose much of the value of using a previously defined
book. As with any specification technique, certain tradeoffs are
necessary.
Why not take a look at the definitions of other alist functions and
see how they work together to provide the ability to construct and
search alists? We'll be using them rather heavily in what follows
so it will be good if you understand basically how they work.
Simply start up ACL2 and execute the form shown earlier, but
substituting our directory name for the top-level ACL2 directory
with yours. Alternatively, just
(include-book \"data-structures/alist-defthms\" :dir :system)
Then, you can use :[pe] to look at function definitions. You'll soon
discover that almost all of the definitions are built on
definitions of other, more primitive functions, as binding is built
on [assoc-equal]. You can look at those as well, of course, or in
many cases visit their documentation.
The other problem with using a predefined book is that it will seldom
be ``sufficiently complete,'' in the sense that the collection of
[rewrite] rules supplied won't be adequate to prove everything we'd
like to know about the interactions of the various functions. If it
were, there'd be no real reason to know that binding is built on
top of [assoc-equal], because everything we'd need to know about
binding would be nicely expressed in the collection of theorems
supplied with the book. However, that's very seldom the case.
Developing such a collection of rules is currently more art than
science and requires considerable experience. We'll encounter
examples later of ``missing'' facts about binding and our other
alist functions. So, let's get on with the example.
Notice that alists are mappings of keys to values; but, there is no
notion of a ``type'' associated with the keys or with the values.
Our phone book example, however, does have such a notion of types;
we map names to phone numbers. We can introduce these ``types'' by
explicitly defining them, e.g., names are strings and phone numbers
are integers. Alternatively, we can partially define or axiomatize
a recognizer for names without giving a full definition. A way to
safely introduce such ``constrained'' function symbols in ACL2 is
with the [encapsulate] form. For example, consider the following
form.
(encapsulate
;; Introduce a recognizer for names and give a ``type'' lemma.
(((namep *) => *))
;;
(local (defun namep (x)
;; This declare is needed to tell
;; ACL2 that we're aware that the
;; argument x is not used in the body
;; of the function.
(declare (ignore x))
t))
;;
(defthm namep-booleanp
(booleanp (namep x))))
This [encapsulate] form introduces the new function namep of one
argument and one result and constrains (namep x) to be Boolean, for
all inputs x. More generally, an encapsulation establishes an
environment in which functions can be defined and theorems and
rules added without necessarily introducing those functions,
theorems, and rules into the environment outside the encapsulation.
To be admissible, all the events in the body of an encapsulate must
be admissible. But the effect of an encapsulate is to assume only
the non-local events.
The first ``argument'' to encapsulate, ((namep (x) t)) above,
declares the intended [signature]s of new function symbols that
will be ``exported'' from the encapsulation without definition. The
[local] [defun] of name defines name within the encapsulation
always to return t. The defthm event establishes that namep is
Boolean. By making the defun local but the defthm non-local this
encapsulate constrains the undefined function namep to be Boolean;
the admissibility of the encapsulation establishes that there
exists a Boolean function (namely the constant function returning
t).
We can subsequently use namep as we use any other Boolean function,
with the proviso that we know nothing about it except that it
always returns either t or nil. We use namep to ``recognize'' legal
keys for our phonebook alist.
We wish to do something similar to define what it means to be a legal
phone number. We submit the following form to ACL2:
(encapsulate
;; Introduce a recognizer for phone numbers.
(((pnump *) => *))
;;
(local (defun pnump (x)
(not (equal x nil))))
;;
(defthm pnump-booleanp
(booleanp (pnump x)))
;;
(defthm nil-not-pnump
(not (pnump nil)))).
This introduces a Boolean-valued recognizer pnump, with the
additional proviso that the constant nil is not a pnump. We impose
this restriction to guarantee that we'll never bind a name to nil
in our phone book and thereby introduce the kind of ambiguity
described above regarding the use of binding.
Now a legal phone book is an alist mapping from nameps to pnumps. We
can define this as follows:
(defun name-phonenum-pairp (x)
;; Recognizes a pair of (name . pnum).
(and (consp x)
(namep (car x))
(pnump (cdr x))))
(defun phonebookp (l)
;; Recognizes a list of such pairs.
(if (not (consp l))
(null l)
(and (name-phonenum-pairp (car l))
(phonebookp (cdr l)))))
Thus, a phone book is really a list of pairs (name . pnum). Notice
that we have not assumed that the keys of the phone book are
distinct. We'll worry about that question later. (It is not always
desirable to insist that the keys of an alist be distinct. But it
may be a useful requirement for our specific example.)
Now we are ready to define some of the functions necessary for our
phonebook example. The functions we need are:
(IN-BOOK? NM BK) ; does NM have a phone number in BK
(FIND-PHONE NM BK) ; find NM's phone number in phonebook BK
(ADD-PHONE NM PNUM BK) ; give NM the phone number PNUM in BK
(CHANGE-PHONE NM PNUM BK) ; change NM's phone number to PNUM in BK
(DEL-PHONE NM PNUM) ; remove NM's phone number from BK
Given our underlying theory of alists, it is easy to write these
functions. But we must take care to specify appropriate
``boundary'' behavior. Thus, what behavior do we want when, say, we
try to change the phone number of a client who is not currently in
the book? As usual, there are numerous possibilities; here we'll
assume that we return the phone book unchanged if we try anything
``illegal.''
Possible definitions of our phone book functions are as follows.
(Remember, an include-book form such as the ones shown earlier must
be executed in order to provide definitions for functions such as
bound?.)
(defun in-book? (nm bk)
(bound? nm bk))
(defun find-phone (nm bk)
(binding nm bk))
(defun add-phone (nm pnum bk)
;; If nm already in-book?, make no change.
(if (in-book? nm bk)
bk
(bind nm pnum bk)))
(defun change-phone (nm pnum bk)
;; Make a change only if nm already has a phone number.
(if (in-book? nm bk)
(bind nm pnum bk)
bk))
(defun del-phone (nm bk)
;; Remove the binding from bk, if there is one.
(rembind nm bk))
Notice that we don't have to check whether a name is in the book
before deleting, because rembind is essentially a no-op if nm is
not bound in bk.
In some sense, this completes our specification. But we can't have
any real confidence in its correctness without validating our
specification in some way. One way to do so is by proving some
properties of our specification. Some candidate properties are:
1. A name will be in the book after we add it.
2. We will find the most recently added phone number for a client.
3. If we change a number, we'll find the change.
4. Changing and then deleting a number is the same as just deleting.
5. A name will not be in the book after we delete it.
Let's formulate some of these properties. The first one, for example,
is:
(defthm add-in-book
(in-book? nm (add-phone nm pnum bk))).
You may wonder why we didn't need any hypotheses about the ``types''
of the arguments. In fact, add-in-book is really expressing a
property that is true of alists in general, not just of the
particular variety of alists we are dealing with. Of course, we
could have added some extraneous hypotheses and proved:
(defthm add-in-book
(implies (and (namep nm)
(pnump pnum)
(phonebookp bk))
(in-book? nm (add-phone nm pnum bk)))),
but that would have yielded a weaker and less useful lemma because it
would apply to fewer situations. In general, it is best to state
lemmas in the most general form possible and to eliminate
unnecessary hypotheses whenever possible. The reason for that is
simple: lemmas are usually stored as rules and used in later
proofs. For a lemma to be used, its hypotheses must be relieved
(proved to hold in that instance); extra hypotheses require extra
work. So we avoid them whenever possible.
There is another, more important observation to make about our lemma.
Even in its simpler form (without the extraneous hypotheses), the
lemma add-in-book may be useless as a [rewrite] rule. Notice that
it is stated in terms of the non-recursive functions in-book? and
add-phone. If such functions appear in the left hand side of the
conclusion of a lemma, the lemma may not ever be used. Suppose in a
later proof, the theorem prover encountered a [term] of the form:
(in-book? nm (add-phone nm pnum bk)).
Since we've already proved add-in-book, you'd expect that this would
be immediately reduced to true. However, the theorem prover will
often ``expand'' the non-recursive definitions of in-book? and
add-phone using their definitions before it attempts rewriting with
lemmas. After this expansion, lemma add-in-book won't ``match'' the
[term] and so won't be applied. Look back at the proof script for
add-in-proof and you'll notice that at the very end the prover
warned you of this potential difficulty when it printed:
Warnings: Non-rec
Time: 0.18 seconds (prove: 0.05, print: 0.00, other: 0.13)
ADD-IN-BOOK
The ``Warnings'' line notifies you that there are non-recursive
function calls in the left hand side of the conclusion and that
this problem might arise. Of course, it may be that you don't ever
plan to use the lemma for rewriting or that your intention is to
[disable] these functions. [Disable]d functions are not expanded
and the lemma should apply. However, you should always take note of
such warnings and consider an appropriate response. By the way, we
noted above that binding is [disable]d. If it were not, none of the
lemmas about binding in the book we included would likely be of
much use for exactly the reason we just gave.
For our current example, let's assume that we're just investigating
the properties of our specifications and not concerned about using
our lemmas for rewriting. So let's go on. If we really want to
avoid the warnings, we can add :rule-classes nil to each defthm
event; see [rule-classes].
Property 2 is: we always find the most recently added phone number
for a client. Try the following formalization:
(defthm find-add-first-cut
(equal (find-phone nm (add-phone nm pnum bk))
pnum))
and you'll find that the proof attempt fails. Examining the proof
attempt and our function definitions, we see that the lemma is
false if nm is already in the book. We can remedy this situation by
reformulating our lemma in at least two different ways:
(defthm find-add1
(implies (not (in-book? nm bk))
(equal (find-phone nm (add-phone nm pnum bk))
pnum)))
(defthm find-add2
(equal (find-phone nm (add-phone nm pnum bk))
(if (in-book? nm bk)
(find-phone nm bk)
pnum)))
For technical reasons, lemmas such as find-add2, i.e., which do not
have hypotheses, are usually slightly preferable. This lemma is
stored as an ``unconditional'' [rewrite] rule (i.e., has no
hypotheses) and, therefore, will apply more often than find-add1.
However, for our current purposes either version is all right.
Property 3 says: If we change a number, we'll find the change. This
is very similar to the previous example. The formalization is as
follows.
(defthm find-change
(equal (find-phone nm (change-phone nm pnum bk))
(if (in-book? nm bk)
pnum
(find-phone nm bk))))
Property 4 says: changing and then deleting a number is the same as
just deleting. We can model this as follows.
(defthm del-change
(equal (del-phone nm (change-phone nm pnum bk))
(del-phone nm bk)))
Unfortunately, when we try to prove this, we encounter subgoals that
seem to be true, but for which the prover is stumped. For example,
consider the following goal. (Note: endp holds of lists that are
empty.)
Subgoal *1/4
(IMPLIES (AND (NOT (ENDP BK))
(NOT (EQUAL NM (CAAR BK)))
(NOT (BOUND? NM (CDR BK)))
(BOUND? NM BK))
(EQUAL (REMBIND NM (BIND NM PNUM BK))
(REMBIND NM BK))).
Our intuition about rembind and bind tells us that this goal should
be true even without the hypotheses. We attempt to prove the
following lemma.
(defthm rembind-bind
(equal (rembind nm (bind nm pnum bk))
(rembind nm bk)))
The prover proves this by induction, and stores it as a rewrite rule.
After that, the prover has no difficulty in proving del-change.
The need to prove lemma rembind-bind illustrates a point we made
early in this example: the collection of [rewrite] rules supplied
by a previously certified book will almost never be everything
you'll need. It would be nice if we could operate purely in the
realm of names, phone numbers, and phone books without ever having
to prove any new facts about alists. Unfortunately, we needed a
fact about the relation between rembind and bind that wasn't
supplied with the alists theory. Hopefully, such omissions will be
rare.
Finally, let's consider our property 5 above: a name will not be in
the book after we delete it. We formalize this as follows:
(defthm in-book-del
(not (in-book? nm (del-phone nm bk))))
This proves easily. But notice that it's only true because del-phone
(actually rembind) removes all occurrences of a name from the phone
book. If it only removed, say, the first one it encountered, we'd
need a hypothesis that said that nm occurs at most once in bk. Ah,
maybe that's a property you hadn't considered. Maybe you want to
ensure that any name occurs at most once in any valid phonebook.
To complete this example, let's consider adding an invariant to our
specification. In particular, suppose we want to assure that no
client has more than one associated phone number. One way to ensure
this is to require that the domain of the alist is a ``set'' (has
no duplicates).
(defun setp (l)
(if (atom l)
(null l)
(and (not (member-equal (car l) (cdr l)))
(setp (cdr l)))))
(defun valid-phonebookp (bk)
(and (phonebookp bk)
(setp (domain bk))))
Now, we want to show under what conditions our operations preserve
the property of being a valid-phonebookp. The operations in-book?
and find-phone don't return a phone book, so we don't really need
to worry about them. Since we're really interested in the ``types''
of values preserved by our phonebook functions, let's look at the
types of those operations as well.
(defthm in-book-booleanp
(booleanp (in-book? nm bk)))
(defthm in-book-namep
(implies (and (phonebookp bk)
(in-book? nm bk))
(namep nm))
:hints ((\"Goal\" :in-theory (enable bound?))))
(defthm find-phone-pnump
(implies (and (phonebookp bk)
(in-book? nm bk))
(pnump (find-phone nm bk)))
:hints ((\"Goal\" :in-theory (enable bound? binding))))
Note the ``:[hints]'' on the last two lemmas. Neither of these would
prove without these [hints], because once again there are some
facts about bound? and binding not available in our current
context. Now, we could figure out what those facts are and try to
prove them. Alternatively, we can [enable] bound? and binding and
hope that by opening up these functions, the conjectures will
reduce to versions that the prover does know enough about or can
prove by induction. In this case, this strategy works. The hints
tell the prover to [enable] the functions in question when
considering the designated goal.
Below we develop the theorems showing that add-phone, change-phone,
and del-phone preserve our proposed invariant. Notice that along
the way we have to prove some subsidiary facts, some of which are
pretty ugly. It would be a good idea for you to try, say,
add-phone-preserves-invariant without introducing the following
four lemmas first. See if you can develop the proof and only add
these lemmas as you need assistance. Then try
change-phone-preserves-invariant and del-phone-preserves-invariant.
They will be easier. It is illuminating to think about why
del-phone-preserves-invariant does not need any ``type''
hypotheses.
(defthm bind-preserves-phonebookp
(implies (and (phonebookp bk)
(namep nm)
(pnump num))
(phonebookp (bind nm num bk))))
(defthm member-equal-strip-cars-bind
(implies (and (not (equal x y))
(not (member-equal x (strip-cars a))))
(not (member-equal x (strip-cars (bind y z a))))))
(defthm bind-preserves-domain-setp
(implies (and (alistp bk)
(setp (domain bk)))
(setp (domain (bind nm num bk))))
:hints ((\"Goal\" :in-theory (enable domain))))
(defthm phonebookp-alistp
(implies (phonebookp bk)
(alistp bk)))
(defthm ADD-PHONE-PRESERVES-INVARIANT
(implies (and (valid-phonebookp bk)
(namep nm)
(pnump num))
(valid-phonebookp (add-phone nm num bk)))
:hints ((\"Goal\" :in-theory (disable domain-bind))))
(defthm CHANGE-PHONE-PRESERVES-INVARIANT
(implies (and (valid-phonebookp bk)
(namep nm)
(pnump num))
(valid-phonebookp (change-phone nm num bk)))
:hints ((\"Goal\" :in-theory (disable domain-bind))))
(defthm remove-equal-preserves-setp
(implies (setp l)
(setp (remove-equal x l))))
(defthm rembind-preserves-phonebookp
(implies (phonebookp bk)
(phonebookp (rembind nm bk))))
(defthm DEL-PHONE-PRESERVES-INVARIANT
(implies (valid-phonebookp bk)
(valid-phonebookp (del-phone nm bk))))
As a final test of your understanding, try to formulate and prove an
invariant that says that no phone number is assigned to more than
one name. The following hints may help.
1. Define the appropriate invariant. (Hint: remember the function
range.)
2. Do our current definitions of add-phone and change-phone
necessarily preserve this property? If not, consider what
hypotheses are necessary in order to guarantee that they do
preserve this property.
3. Study the definition of the function range and notice that it is
defined in terms of the function [strip-cdrs]. Understand how
this defines the range of an alist.
4. Formulate the correctness theorems and attempt to prove them.
You'll probably benefit from studying the invariant proof
above. In particular, you may need some fact about the function
[strip-cdrs] analogous to the lemma
member-equal-strip-cars-bind above.
Below is one solution to this exercise. Don't look at the solution,
however, until you've struggled a bit with it. Notice that we
didn't actually change the definitions of add-phone and
change-phone, but added a hypothesis saying that the number is
``new.'' We could have changed the definitions to check this and
return the phonebook unchanged if the number was already in use.
(defun pnums-in-use (bk)
(range bk))
(defun phonenums-unique (bk)
(setp (pnums-in-use bk)))
(defun new-pnump (pnum bk)
(not (member-equal pnum (pnums-in-use bk))))
(defthm member-equal-strip-cdrs-rembind
(implies (not (member-equal x (strip-cdrs y)))
(not (member-equal x (strip-cdrs (rembind z y))))))
(defthm DEL-PHONE-PRESERVES-PHONENUMS-UNIQUE
(implies (phonenums-unique bk)
(phonenums-unique (del-phone nm bk)))
:hints ((\"Goal\" :in-theory (enable range))))
(defthm strip-cdrs-bind-non-member
(implies (and (not (bound? x a))
(alistp a))
(equal (strip-cdrs (bind x y a))
(append (strip-cdrs a) (list y))))
:hints ((\"Goal\" :in-theory (enable bound?))))
(defthm setp-append-list
(implies (setp l)
(equal (setp (append l (list x)))
(not (member-equal x l)))))
(defthm ADD-PHONE-PRESERVES-PHONENUMS-UNIQUE
(implies (and (phonenums-unique bk)
(new-pnump pnum bk)
(alistp bk))
(phonenums-unique (add-phone nm pnum bk)))
:hints ((\"Goal\" :in-theory (enable range))))
(defthm member-equal-strip-cdrs-bind
(implies (and (not (member-equal z (strip-cdrs a)))
(not (equal z y)))
(not (member-equal z (strip-cdrs (bind x y a))))))
(defthm CHANGE-PHONE-PRESERVES-PHONENUMS-UNIQUE
(implies (and (phonenums-unique bk)
(new-pnump pnum bk)
(alistp bk))
(phonenums-unique (change-phone nm pnum bk)))
:hints ((\"Goal\" :in-theory (enable range))))")
(TUTORIAL4-DEFUN-SK-EXAMPLE
(ANNOTATED-ACL2-SCRIPTS)
"Example of quantified notions
This example illustrates the use of [defun-sk] and [defthm] [events]
to reason about quantifiers. See [defun-sk]. For a more through,
systematic beginner's introduction to quantification in ACL2, see
[quantifier-tutorial].
Many users prefer to avoid the use of quantifiers, since ACL2
provides only very limited support for reasoning about quantifiers.
Here is a list of [events] that proves that if there are arbitrarily
large numbers satisfying the disjunction (OR P R), then either
there are arbitrarily large numbers satisfying P or there are
arbitrarily large numbers satisfying R.
; Introduce undefined predicates p and r.
(defstub p (x) t)
(defstub r (x) t)
; Define the notion that something bigger than x satisfies p.
(defun-sk some-bigger-p (x)
(exists y (and (< x y) (p y))))
; Define the notion that something bigger than x satisfies r.
(defun-sk some-bigger-r (x)
(exists y (and (< x y) (r y))))
; Define the notion that arbitrarily large x satisfy p.
(defun-sk arb-lg-p ()
(forall x (some-bigger-p x)))
; Define the notion that arbitrarily large x satisfy r.
(defun-sk arb-lg-r ()
(forall x (some-bigger-r x)))
; Define the notion that something bigger than x satisfies p or r.
(defun-sk some-bigger-p-or-r (x)
(exists y (and (< x y) (or (p y) (r y)))))
; Define the notion that arbitrarily large x satisfy p or r.
(defun-sk arb-lg-p-or-r ()
(forall x (some-bigger-p-or-r x)))
; Prove the theorem promised above. Notice that the functions open
; automatically, but that we have to provide help for some rewrite
; rules because they have free variables in the hypotheses. The
; ``witness functions'' mentioned below were introduced by DEFUN-SK.
(thm
(implies (arb-lg-p-or-r)
(or (arb-lg-p)
(arb-lg-r)))
:hints ((\"Goal\"
:use
((:instance some-bigger-p-suff
(x (arb-lg-p-witness))
(y (some-bigger-p-or-r-witness
(max (arb-lg-p-witness)
(arb-lg-r-witness)))))
(:instance some-bigger-r-suff
(x (arb-lg-r-witness))
(y (some-bigger-p-or-r-witness
(max (arb-lg-p-witness)
(arb-lg-r-witness)))))
(:instance arb-lg-p-or-r-necc
(x (max (arb-lg-p-witness)
(arb-lg-r-witness))))))))
; And finally, here's a cute little example. We have already
; defined above the notion (some-bigger-p x), which says that
; something bigger than x satisfies p. Let us introduce a notion
; that asserts that there exists both y and z bigger than x which
; satisfy p. On first glance this new notion may appear to be
; stronger than the old one, but careful inspection shows that y and
; z do not have to be distinct. In fact ACL2 realizes this, and
; proves the theorem below automatically.
(defun-sk two-bigger-p (x)
(exists (y z) (and (< x y) (p y) (< x z) (p z))))
(thm (implies (some-bigger-p x) (two-bigger-p x)))
; A technical point: ACL2 fails to prove the theorem above
; automatically if we take its contrapositive, unless we disable
; two-bigger-p as shown below. That is because ACL2 needs to expand
; some-bigger-p before applying the rewrite rule introduced for
; two-bigger-p, which contains free variables. The moral of the
; story is: Don't expect too much automatic support from ACL2 for
; reasoning about quantified notions.
(thm (implies (not (two-bigger-p x)) (not (some-bigger-p x)))
:hints ((\"Goal\" :in-theory (disable two-bigger-p))))")
(TUTORIAL5-MISCELLANEOUS-EXAMPLES
(ANNOTATED-ACL2-SCRIPTS)
"Miscellaneous ACL2 examples
The following examples are more advanced examples of usage of ACL2.
They are included largely for reference, in case someone finds them
useful.
Subtopics
[File-reading-example]
Example of reading files in ACL2
[Functional-instantiation-example]
A small proof demonstrating functional instantiation
[Guard-example]
A brief transcript illustrating [guard]s in ACL2
[Mutual-recursion-proof-example]
A small proof about mutually recursive functions")
(TYPE
(POINTERS)
"Disambiguation page for type-related concepts.
The word type might mean many things in ACL2.
Built-in Types
ACL2 can reason about and compute with certain different kinds of
objects, such as [numbers], [strings], [characters], and
[conses]. See [About_Types] for basic background on the
different kinds of ACL2 objects.
User-Defined Types
When modeling systems with ACL2, you may often want to introduce
certain concepts as new data types. For instance, if you are
modeling a network, you might want host and connection objects.
ACL2 does not directly support introducing new types. Instead,
such types are usually ``emulated'' by introducing a new
recognizer function, say hostp, and perhaps some related
constructor and accessor functions, say make-host and
host->name. Macro libraries can help to assist with introducing
common types. See for instance [std/util], [defdata], or [fty].
Type Declarations
For more efficient Common Lisp execution, ACL2 functions can be
annotated with Common Lisp type specifiers (see [type-spec])
that may boost performance by reducing run-time type checking.
This mechanism is integrated with ACL2's [guard] mechanism, so
you can prove your type declarations are correct. See also
[declare] and [the], and also [patbind-the].
Type Prescriptions
ACL2 includes a limited but efficient ``[type-set] reasoning engine
for determining whether objects are of certain built-in types.
This engine can be extended with [type-prescription] rules.
Such rules are often inferred automatically when new functions
are introduced with [defun]. Type-set reasoning can assist
other reasoning engines like [forward-chaining],
[linear-arithmetic], and rewriting. Type-set information is
stored in a [type-alist] data structure.
Tau
ACL2 includes another reasoning engine, the [tau-system], for
reasoning about type-like predicates. Unlike [type-set], Tau
can also be used for reasoning about user-defined types, and
can also carry out certain interval arithmetic reasoning. See
the [introduction-to-the-tau-system] for more information about
Tau.")
(TYPE-ALIST
(TYPE-SET)
"An ACL2 representation of contextual knowledge
The ACL2 prover maintains many structures that need not be understood
by the user. One of these, the type-alist structure, is usually in
this category. But some utilities refer to the type-alist, so we
summarize it here.
A type-alist is is an association list, each element of which is of
the form (u ts . ttree), where u is a [term] (in internal,
``translated'' form), ts is a [type-set], and ttree is a tag-tree
(see [ttree]). Such an element means that the term u has the
type-set ts, which is a number. While you are welcome to see the
[documentation] of [type-set] for details, this is not necessary,
since user-level utilities generally display a type-alist without
displaying numeric type-sets. Instead, they often use a symbol of
the form *TS-typ* to denote the type described by typ, and for
complements they use (TS-COMPLEMENT *TS-typ*). For example, a
context in which the terms (p x y), (no-duplicatesp-equal y), and
(natp x) are assumed to be true (i.e., non-nil) may be displayed
using the following lines.
-----
Terms with type *TS-T*:
(NO-DUPLICATESP-EQUAL Y)
-----
Terms with type (TS-COMPLEMENT *TS-NIL*):
(P X Y)
-----
Terms with type *TS-NON-NEGATIVE-INTEGER*:
X
-----
These lines says that (no-duplicatesp-equal y) is the symbol t, (p x
y) is not the symbol nil, and x is a non-negative integer (i.e., a
[natp]).
ACL2 computes a type-alist based on contextual information including
the hypotheses of the current goal (technically: the negations of
the literals in the goal that are not currently being rewritten),
[forward-chaining] from those literals, and the surrounding tests
in calls of if. The type-alist is of course not all that is known,
since an entire logical [world] of facts is also known; and
additional known information may be recorded in the current
database of [linear] rules.")
(TYPE-PRESCRIPTION
(RULE-CLASSES)
"Make a rule that specifies the type of a term
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description. In
this topic we focus on user-defined type-prescription rules, but
note that ACL2 also introduces type-prescription rules when
introducing a function with [defun]; see
[type-prescription-debugging] for discussion of how to influence
the generation of such rules.
Examples:
(defthm integerp-foo ; Assumes that foo has been
(integerp (foo x y)) ; defined; then, states that
:rule-classes :type-prescription) ; (foo x y) is of type integer.
(defthm characterp-nth-type-prescription ; (Nth n lst) is of type character
(implies ; provided the hypotheses can be
(and (character-listp lst) ; established by type reasoning.
(<= 0 n)
(< n (len lst)))
(characterp (nth n lst)))
:rule-classes :type-prescription)
(defthm characterp-nth-type-prescription-alt ; equivalent to the above
(implies
(and (character-listp lst)
(<= 0 n)
(< n (len lst)))
(characterp (nth n lst)))
:rule-classes ((:type-prescription :typed-term (nth n lst))))
(defthm demodulize-type-for-quote-value ; (Demodulize a lst 'value ans) is
(implies ; either a nonnegative integer or
(and (atom a) ; of the same type as ans, provided
(true-listp lst) ; the hyps can be established by type
(member-equal a lst)) ; reasoning
(or (and (integerp (demodulize a lst 'value ans))
(>= (demodulize a lst 'value ans) 0))
(equal (demodulize a lst 'value ans) ans)))
:rule-classes :type-prescription)
To specify the term whose type (see [type-set]) is described by the
rule, provide that term as the value of the :typed-term field of
the rule class object.
General Form (after preprocessing; see below):
(implies hyps
(or type-restriction1-on-pat
...
type-restrictionk-on-pat
(equal pat var1)
...
(equal pat varj)))
where pat is the application of some function symbol to some
arguments, each type-restrictioni-on-pat is a term involving pat
and containing no variables outside of the occurrences of pat, and
each vari is one of the variables of pat. Generally speaking, the
type-restriction terms ought to be terms that inform us as to the
type of pat. Ideally, they should be ``primitive recognizing
expressions'' about pat; see [compound-recognizer]. We describe
preprocessing at the end of this topic.
If the :typed-term is not provided in the rule class object, it is
computed heuristically by looking for a term in the conclusion
whose type is being restricted. An error is caused if no such term
is found.
Roughly speaking, the effect of adding such a rule is to inform the
ACL2 typing mechanism that pat has the type described by the
conclusion, when the hypotheses are true. In particular, the type
of pat is within the union of the types described by the several
disjuncts. The ``type described by'' (equal pat vari) is the type
of vari.
More operationally, when asked to determine the type of a term that
is an instance of pat, ACL2 will first attempt to establish the
hypotheses. This is done by type reasoning alone, not rewriting!
However, if some hypothesis is a call of [force], then forcing may
occur, which may ultimately invoke the rewriter; see [force] and
see [case-split]. So-called free variables in hypotheses are
treated specially; see [free-variables]. Provided the hypotheses
are established by type reasoning, ACL2 then unions the types
described by the type-restrictioni-on-pat terms together with the
types of those subexpressions of pat identified by the vari. The
final type computed for a term is the intersection of the types
implied by each applicable rule. Type prescription rules may be
disabled.
You can limit the recursive establishment of hypotheses of rules; see
[set-backchain-limit].
Because only type reasoning is used to establish the hypotheses of
:type-prescription rules, some care must be taken with the
hypotheses. Suppose, for example, that the non-recursive function
my-statep is defined as
(defun my-statep (x)
(and (true-listp x)
(equal (len x) 2)))
and suppose (my-statep s) occurs as a hypothesis of a
:type-prescription rule that is being considered for use in the
proof attempt for a conjecture with the hypothesis (my-statep s).
Since the hypothesis in the conjecture is rewritten, it will become
the conjunction of (true-listp s) and (equal (len s) 2). Those two
terms will be assumed to have type t in the context in which the
:type-prescription rule is tried. But type reasoning will be unable
to deduce that (my-statep s) has type t in this context. Thus,
either my-statep should be disabled (see [disable]) during the
proof attempt or else the occurrence of (my-statep s) in the
:type-prescription rule should be replaced by the conjunction into
which it rewrites.
While this example makes it clear how non-recursive predicates can
cause problems, non-recursive functions in general can cause
problems. For example, if (mitigate x) is defined to be (if
(rationalp x) (1- x) x) then the hypothesis (pred (mitigate s)) in
the conjecture will rewrite, opening mitigate and splitting the
conjecture into two subgoals, one in which (rationalp s) and (pred
(1- x)) are assumed and the other in which (not (rationalp s)) and
(pred x) are assumed. But (pred (mitigate s)) will not be typed as
t in either of these contexts. The moral is: beware of
non-recursive functions occuring in the hypotheses of
:type-prescription rules.
Because of the freedom one has in forming the conclusion of a
type-prescription, we have to use heuristics to recover the
pattern, pat, whose type is being specified. In some cases our
heuristics may not identify the intended term and the
:type-prescription rule will be rejected as illegal because the
conclusion is not of the correct form. When this happens you may
wish to specify the pat directly. This may be done by using a
suitable rule class token. In particular, when the token
:type-prescription is used it means ACL2 is to compute pat with its
heuristics; otherwise the token should be of the form
(:type-prescription :typed-term pat), where pat is the term whose
type is being specified.
The defun event may generate a :type-prescription rule. Suppose fn is
the name of the function concerned. Then (:type-prescription fn) is
the rune given to the type-prescription, if any, generated for fn
by [defun]. (The trivial rule, saying fn has unknown type, is not
stored, but [defun] still allocates the rune and the corollary of
this rune is known to be t.)
We close with a discussion of how, before a term is parsed into a
:type-prescription rule, it is preprocessed. We describe this
preprocessing in some detail below, but first consider the
following (contrived) example.
(defthm append-tp-example
(let ((result (append x y)))
(implies (nat-listp x)
(implies (let ((second-hyp (integer-listp y)))
second-hyp)
(true-listp result))))
:rule-classes :type-prescription)
This theorem is parsed into a type-prescription rule with the
following hypotheses and conclusion.
(nat-listp x) ; first hypothesis
((lambda (second-hyp) second-hyp) (integer-listp y)) ; second hypothesis
(true-listp (binary-append x y)) ; conclusion
Notice that the top-level [let] was expanded, i.e., (append x y) was
substituted for result --- more accurately, (binary-append x y) was
substituted for result, since [append] is a macro that abbreviates
[binary-append]. Also notice that the two hypotheses were
``flattened'' in the sense that they were gathered up into a list.
Finally, notice that the [let] in the second hypothesis was not
expanded (it was merely translated to internal form, using LAMBDA).
If you actually submit the theorem above, you will get warnings,
which you may choose to ignore; the application of
type-prescription rules is somewhat subtle, so if you use them then
you may wish to experiment to see which forms work best for you.
Here is the detail promised above, for parsing a term into a
:type-prescription rule. There are two steps. (1) ACL2 first
translates the term, expanding all macros (see [trans]) and also
removing [guard-holders]. (2) Then the the translated term is
traversed top-down, expanding away lambdas ([let], [let*], and
[mv-let] expressions) and flattening the [implies] structure, until
the conclusion is exposed; then the conclusion's lambdas are also
expanded away. The simplest way to understand (2) may be to look at
the definition of ACL2 source function unprettyify-tp, which
implements Step (2), say by evaluating :[pe] unprettyify-tp.
Subtopics
[Backchain-limit]
Limiting the effort expended on relieving hypotheses
[Case-split]
Like force but immediately splits the top-level goal on the
hypothesis
[Force]
Identity function used to force a hypothesis
[Type-prescription-debugging]
Improve a built-in [type-prescription] rule")
(TYPE-PRESCRIPTION-DEBUGGING
(DEBUGGING TYPE-PRESCRIPTION)
"Improve a built-in [type-prescription] rule
A [type-prescription] rule is introduced automatically when a
function is defined (see [defun]). However, that rule might not be
what you expect. In this topic we explore how you might be able to
improve that rule, by way of an example.
First consider the following definition.
ACL2 !>(defun f (x) (alistp x))
Since F is non-recursive, its admission is trivial. We observe that
the type of F is described by the theorem
(OR (EQUAL (F X) T) (EQUAL (F X) NIL)). We used the :type-prescription
rule ALISTP.
Summary
Form: ( DEFUN F ...)
Rules: ((:TYPE-PRESCRIPTION ALISTP))
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.00)
F
ACL2 !>
Notice in particular the phrase, ``We used the :type-prescription
rule ALISTP,'' and the corresponding [rune] (:TYPE-PRESCRIPTION
ALISTP) in the list of rules printed in the summary. These are
telling us that ACL2 used the indicated rule during the process of
computing a (@see type-prescription) rule for f.
Now suppose that in a different session we instead proceed as
follows.
ACL2 !>(in-theory (disable (:type-prescription alistp)))
Summary
Form: ( IN-THEORY (DISABLE ...))
Rules: NIL
Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
(:NUMBER-OF-ENABLED-RUNES 3298)
ACL2 !>(defun f (x) (alistp x))
Since F is non-recursive, its admission is trivial. We could deduce
no constraints on the type of F.
Summary
Form: ( DEFUN F ...)
Rules: NIL
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
F
ACL2 !>
Notice that this time ``We could deduce no constraints on the type of
F,'' because in this context, [type-set] reasoning does not see
that the body of f is a Boolean, because (:type-prescription
alistp) has been [disable]d. Thus, the ``Rules'' field of the
summary is empty this time.
Consider the following story. On Monday, you run the first session,
and a subsequent proof uses [type-set] reasoning to conclude that
(f x) is Boolean, even after you [disable] the [definition] of f.
Then on Tuesday, you run the second session, and are surprised to
find that ACL2 no longer reasons (during that same subsequent proof
attempt) that (f x) is Boolean. You want to debug this problem, so
you look back in the log where you defined f, and you see the
``deduce no constraints'' message --- but then you look further
back, at Monday's log, where you find the definition of f ``used
the :type-prescription rule ALISTP'' to conclude that ``the type of
F is described by the theorem (OR (EQUAL (F X) T) (EQUAL (F X)
NIL))''. The mention of ALISTP in that definition's output from
Monday, together with the corresponding mention of
(:TYPE-PRESCRIPTION ALISTP) in the ``Rules'' field of the summary,
leads you to resolve the issue as follows. On Monday, when
(:TYPE-PRESCRIPTION ALISTP) was [enable]d, ACL2 used type-set
reasoning to conclude that the body of f is Boolean, but on
Tuesday, (:TYPE-PRESCRIPTION ALISTP) was disabled at that point and
hence the body of f was not known to be Boolean by type-set
reasoning. Hence on Tuesday, no Boolean type-prescription rule was
stored for f at definition time, which is why the subsequent proof
attempt failed to use such a rule. So you avoid disabling
(:TYPE-PRESCRIPTION ALISTP) until after submitting the [defun] for
f, and now ACL2's type reasoning knows that f returns a Boolean.")
(TYPE-SET
(MISCELLANEOUS)
"How type information is encoded in ACL2
To help you experiment with type-sets we briefly note the following
utility functions.
(type-set-quote x) will return the type-set of the object x. For
example, (type-set-quote \"test\") is 2048 and (type-set-quote '(a b
c)) is 512.
(type-set 'term nil nil nil (ens state) (w state) nil nil nil) will
return the type-set of term. For example,
(type-set '(integerp x) nil nil nil (ens state) (w state) nil nil nil)
will return (mv 192 nil). 192, otherwise known as *ts-boolean*, is
the type-set containing t and nil. The second result may be ignored
in these experiments. Term must be in the translated, internal form
shown by :[trans]. See [trans] and see [term].
(type-set-implied-by-term 'x nil 'term (ens state)(w state) nil) will
return the type-set deduced for the variable symbol x assuming the
translated term, term, true. The second result may be ignored in
these experiments. For example,
(type-set-implied-by-term 'v nil '(integerp v)
(ens state) (w state) nil)
returns 11.
(convert-type-set-to-term 'x ts (ens state) (w state) nil) will
return a term whose truth is equivalent to the assertion that the
term x has type-set ts. The second result may be ignored in these
experiments. For example
(convert-type-set-to-term 'v 523 (ens state) (w state) nil)
returns a term expressing the claim that v is either an integer or a
non-nil true-list. 523 is the logical-or of 11 (which denotes the
integers) with 512 (which denotes the non-nil true-lists).
The ``actual primitive types'' of ACL2 are listed in
*actual-primitive-types*, whose elements are shown below. Each
actual primitive type denotes a set --- sometimes finite and
sometimes not --- of ACL2 objects and these sets are pairwise
disjoint. For example, *ts-zero* denotes the set containing 0 while
*ts-positive-integer* denotes the set containing all of the
positive integers.
*TS-ZERO* ;;; {0}
*TS-POSITIVE-INTEGER* ;;; positive integers
*TS-POSITIVE-RATIO* ;;; positive non-integer rationals
*TS-NEGATIVE-INTEGER* ;;; negative integers
*TS-NEGATIVE-RATIO* ;;; negative non-integer rationals
*TS-COMPLEX-RATIONAL* ;;; complex rationals
*TS-NIL* ;;; {nil}
*TS-T* ;;; {t}
*TS-NON-T-NON-NIL-SYMBOL* ;;; symbols other than nil, t
*TS-PROPER-CONS* ;;; null-terminated non-empty lists
*TS-IMPROPER-CONS* ;;; conses that are not proper
*TS-STRING* ;;; strings
*TS-CHARACTER* ;;; characters
The actual primitive types were chosen by us to make theorem proving
convenient. Thus, for example, the actual primitive type *ts-nil*
contains just nil so that we can encode the hypothesis ``x is nil''
by saying ``x has type *ts-nil*'' and the hypothesis ``x is
non-nil'' by saying ``x has type complement of *ts-nil*.'' We
similarly devote a primitive type to t, *ts-t*, and to a third
type, *ts-non-t-non-nil-symbol*, to contain all the other ACL2
symbols.
Let *ts-other* denote the set of all Common Lisp objects other than
those in the actual primitive types. Thus, *ts-other* includes such
things as floating point numbers and CLTL array objects. The actual
primitive types together with *ts-other* constitute what we call
*universe*. Note that *universe* is a finite set containing one
more object than there are actual primitive types; that is, here we
are using *universe* to mean the finite set of primitive types, not
the infinite set of all objects in all of those primitive types.
*Universe* is a partitioning of the set of all Common Lisp objects:
every object belongs to exactly one of the sets in *universe*.
Abstractly, a ``type-set'' is a subset of *universe*. To say that a
term, x, ``has type-set ts'' means that under all possible
assignments to the variables in x, the value of x is a member of
some member of ts. Thus, (cons x y) has type-set {*ts-proper-cons*
*ts-improper-cons*}. A term can have more than one type-set. For
example, (cons x y) also has the type-set {*ts-proper-cons*
*ts-improper-cons* *ts-nil*}. Extraneous types can be added to a
type-set without invalidating the claim that a term ``has'' that
type-set. Generally we are interested in the smallest type-set a
term has, but because the entire theorem-proving problem for ACL2
can be encoded as a type-set question, namely, ``Does p have
type-set complement of *ts-nil*?,'' finding the smallest type-set
for a term is an undecidable problem. When we speak informally of
``the'' type-set we generally mean ``the type-set found by our
heuristics'' or ``the type-set assumed in the current context.''
Note that if a type-set, ts, does not contain *ts-other* as an
element then it is just a subset of the actual primitive types. If
it does contain *ts-other* it can be obtained by subtracting from
*universe* the complement of ts. Thus, every type-set can be
written as a (possibly complemented) subset of the actual primitive
types.
By assigning a unique bit position to each actual primitive type we
can encode every subset, s, of the actual primitive types by the
nonnegative integer whose ith bit is on precisely if s contains the
ith actual primitive type. The type-sets written as the complement
of s are encoded as the twos-complement of the encoding of s. Those
type-sets are thus negative integers. The bit positions assigned to
the actual primitive types are enumerated from 0 in the same order
as the types are listed in *actual-primitive-types*. At the
concrete level, a type-set is an integer between *min-type-set* and
*max-type-set*, inclusive.
For example, *ts-nil* has bit position 6. The type-set containing
just *ts-nil* is thus represented by 64. If a term has type-set 64
then the term is always equal to nil. The type-set containing
everything but *ts-nil* is the twos-complement of 64, which is -65.
If a term has type-set -65, it is never equal to nil. By ``always''
and ``never'' we mean under all, or under no, assignments to the
variables, respectively.
Here is a more complicated example. Let s be the type-set containing
all of the symbols and the natural numbers. The relevant actual
primitive types, their bit positions and their encodings are:
actual primitive type bit value
*ts-zero* 0 1
*ts-positive-integer* 1 2
*ts-nil* 6 64
*ts-t* 7 128
*ts-non-t-non-nil-symbol* 8 256
Thus, the type-set s is represented by (+ 1 2 64 128 256) = 451. The
complement of s, i.e., the set of all objects other than the
natural numbers and the symbols, is -452.
Subtopics
[Type-alist]
An ACL2 representation of contextual knowledge")
(TYPE-SET-INVERTER
(RULE-CLASSES)
"Exhibit a new decoding for an ACL2 type-set
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Example Rule Class:
(:type-set-inverter
:corollary (equal (and (counting-number x) (not (equal x 0)))
(and (integerp x) (< 0 x)))
:type-set 2)
General Forms of Rule Class:
:type-set-inverter, or
(:type-set-inverter :type-set n)
General Form of Theorem or Corollary:
(EQUAL new-expr old-expr)
where n is a [type-set] (see [type-set]) and old-expr is the term
containing x as a free variable that ACL2 currently uses to
recognize [type-set] n. For a given n, the exact form of old-expr
is generated by
(convert-type-set-to-term 'x n (ens state) (w state) nil)].
If the :[type-set] field of the rule-class is omitted, we attempt to
compute it from the right-hand side, old-expr, of the corollary.
That computation is done by type-set-implied-by-term (see
[type-set]). However, it is possible that the type-set we compute
from lhs does not have the required property that when inverted
with convert-type-set-to-term the result is lhs. If you omit
:[type-set] and an error is caused because lhs has the incorrect
form, you should manually specify both :[type-set] and the lhs
generated by convert-type-set-to-term.
The rule generated will henceforth make new-expr be the term used by
ACL2 to recognize type-set n. If this rule is created by a [defthm]
event named name then the rune of the rule is (:type-set-inverter
name) and by disabling that rune you can prevent its being used to
decode type-sets.
Type-sets are inverted when forced assumptions are turned into
formulas to be proved. In their internal form, assumptions are
essentially pairs consisting of a context and a goal term, which
was forced. Abstractly a context is just a list of hypotheses which
may be assumed while proving the goal term. But actually contexts
are alists which pair terms with type-sets, encoding the current
hypotheses. For example, if the original conjecture contained the
hypothesis (integerp x) then the context used while working on that
conjecture will include the assignment to x of the type-set
*ts-integer*.")
(TYPE-SPEC
(DECLARE THE)
"Type specifiers can be used in Common Lisp type declarations and
[the] forms, and may result in improved efficiency of execution.
ACL2 permits the use of type declarations in certain contexts; see
[declare] for background. Here is an example of a type declaration;
here the symbol, integer, is what we refer to as a ``type-spec'':
(let ((x (+ a b)))
(declare (type integer x)) ;; <-- type declaration
(+ 1 x))
A Common Lisp compiler might be able to use the above declaration to
improve the execution efficiency of the resulting code. In
particular, the Common Lisp [+] operation is rather elaborate: it
must be capable of adding together integers, rationals, floats,
etc. When we tell the compiler that this x is surely an integer, it
may be able to use a more efficient version of (+ 1 x) that only
deals with the integer case.
Type declarations can be added to functions, [let] bindings, and
other places as described in [declare], and interact with the
ACL2's [guard] mechanism. For instance, during guard verification,
the above type declaration will result in a guard obligation: we
will need to prove that (+ a b) is always an integer. Type
declarations about the formals of a function generally become part
of the guard of the function, but see also [split-types] for a way
to gain more control over this.
Whether or not a particular type declaration will actually improve
the efficiency of your functions depends on the Lisp compiler. For
instance, many Lisp compilers will not benefit much from a plain
integer declaration. If you are trying to optimize code by adding
type declarations, it may be useful to use [disassemble$] to
inspect the impact that your declarations have on the resulting
code.
Type Specs
The syntax that Common Lisp compilers use for these type
declarations---e.g., the symbol integer above---is different than
the usual syntax of ACL2.
We use the name type-spec to refer to the supported types that can be
mentioned in declarations. For instance:
Declaration | Type-Spec |
(type string x y z) | string |
(type (integer 0 7) x) | (integer 0 7) |
(type rational x) | rational |
(type (rational 1 *) x) | (rational 1 *) |
The supported type-specs and their meanings (when applied to the
variable x as in (declare (type type-spec x)) are given below.
type-spec meaning
----------------------------------------------------------------------
(AND type1 ... typek) (AND (p1 X) ... (pk X))
where (pj x) is the meaning for type-spec typej
ATOM (ATOM X)
BIT (OR (EQUAL X 1) (EQUAL X 0))
CHARACTER (CHARACTERP X)
COMPLEX (AND (COMPLEX-RATIONALP X)
(RATIONALP (REALPART X))
(RATIONALP (IMAGPART X)))
(COMPLEX RATIONAL) same as COMPLEX, above
(COMPLEX type) (AND (COMPLEX-RATIONALP X)
(p (REALPART X))
(p (IMAGPART X)))
where (p x) is the meaning for type-spec type
CONS (CONSP X)
INTEGER (INTEGERP X)
(INTEGER i j) (AND (INTEGERP X) ; See notes below
(<= i X)
(<= X j))
(MEMBER x1 ... xn) (MEMBER X '(x1 ... xn))
(MOD i) same as (INTEGER 0 i-1)
NIL NIL
(NOT type) (NOT (p X))
where (p x) is the meaning for type-spec type
NULL (EQ X NIL)
(OR type1 ... typek) (OR (p1 X) ... (pk X))
where (pj x) is the meaning for type-spec typej
RATIO (AND (RATIONALP X) (NOT (INTEGERP X)))
RATIONAL (RATIONALP X)
(RATIONAL i j) (AND (RATIONALP X) ; See notes below
(<= i X)
(<= X j))
REAL (RATIONALP X) ; (REALP X) in ACL2(r)
(REAL i j) (AND (RATIONALP X) ; See notes below
(<= i X)
(<= X j))
(SATISFIES pred) (pred X) ; Lisp requires a unary function, not a macro
SIGNED-BYTE (INTEGERP X)
(SIGNED-BYTE i) same as (INTEGER k m) where k=-2^(i-1), m=2^(i-1)-1
STANDARD-CHAR (STANDARD-CHARP X)
STRING (STRINGP X)
(STRING max) (AND (STRINGP X) (EQUAL (LENGTH X) max))
SYMBOL (SYMBOLP X)
T T
UNSIGNED-BYTE same as (INTEGER 0 *)
(UNSIGNED-BYTE i) same as (INTEGER 0 (2^i)-1)
----------------------------------------------------------------------
Notes
In general, (integer i j) means
(AND (INTEGERP X)
(<= i X)
(<= X j)).
But if i is the symbol *, the first inequality is omitted. If j is
the symbol *, the second inequality is omitted. If instead of being
an integer, the second element of the type specification is a list
containing an integer, (i), then the first inequality is made
strict. An analogous remark holds for the (j) case. The rational
and real type specifiers are similarly generalized.
Common Lisp itself supports richer type specifiers than ACL2. Some
resources:
* A {nice picture of the Common Lisp Type Hierarchy |
http://sellout.github.io/2012/03/03/common-lisp-type-hierarchy/}
by Greg Pfeil.")
(TYPESPEC-CHECK (POINTERS)
"See [meta-extract].")
(U
(HISTORY)
"Undo last [command], without a query
Example:
:u
The keyword [command] :u is the same as :[ubt!] :x. :[Oops] will undo
the last :u. See [ubt!].")
(UBT
(HISTORY)
"Undo the [command]s back through a [command] descriptor
Examples:
:ubt :max ; undo back through the most recent command
; (which just means undo the most recent command)
:ubt :x ; same as :ubt :max
:u ; same as :ubt :max with no questions asked
:ubt fn ; undo back through the introduction of fn
; (including all the other events in fn's block)
:ubt 5 ; undo back through the fifth command executed
:ubt (:max -4) ; undo back through the most recent five commands
:ubt (:x -4) ; undo back through the most recent five commands
See [command-descriptor].
Ubt takes one argument, a [command] descriptor, and undoes the
[command]s from :[max] (aka :x) through the one described. See
[command-descriptor]. [Pbt] will print the [command]s that ubt will
undo. :[Oops] will undo the undo. See [oops].
Ubt can cause errors but not queries. To get queries as well, see
[ubt?]. To get neither errors nor queries, see [ubt!]..
It is important to remember that a [command] may create several
[events]. That is, the [command] that introduces fn1 may also
introduce fn2. Undoing the [command] that created either of these
will undo them both. The [events] created by a [command] constitute
the [command]'s ``block'' and we can only undo entire blocks. Use
[pcb] to print the [command] block of a [command] if you wish to
see what will be lost by undoing the [command].
Ubt will not undo into ``prehistory''. :Ubt 1 will undo all of your
[command]s. But :ubt -5 will cause an error, warning you that :ubt
cannot undo system initialization.
See [u] for how to undo just the latest command. See [ubu], [ubu!],
and [ubu?] for how to undo back up to, but not including, the
current command.")
(UBT!
(HISTORY)
"Undo [command]s, without a query or an error
Example:
:ubt! :x-4
The keyword [command] :ubt! is the same as :[ubt], but with a
guarantee that it is ``error-free.'' More precisely, the value
returned by :ubt! will always be of the form (mv nil val state).
:[Oops] will undo the last :ubt!. See [ubt], [ubt?], [ubu!], [ubu],
[ubu?], and [u].")
(UBT-PREHISTORY
(HISTORY)
"Undo the [command]s back through the last [reset-prehistory] event
This command is only used to eliminate a [reset-prehistory] event. If
your most recent reset-prehistory event does not have a flag
argument of t, then :ubt-prehistory undoes all command back
through, and including, that reset-prehistory event.")
(UBT?
(HISTORY)
"Undo [command]s, with queries as appropriate
Example:
:ubt? :x-4
The keyword [command] :ubt? is the same as :[ubt], but with
appropriate queries made. :[Oops] will undo the last :ubt?. See
[ubt!], [ubt], [ubu!], [ubu], [ubu?], and [u].")
(UBU
(HISTORY)
"Undo the [command]s back up to (not including) a [command] descriptor
Examples:
:ubu :x-3 ; undo the last three commands (same as :ubt :x-2)
:ubu (:x -3) ; same as above
:ubu fn ; undo back up to, but not including the introduction of fn
; (so fn will continue to be defined)
:ubu 5 ; undo back up to, but not including, the fifth command
; executed (leaving the first five commands in place)
See [command-descriptor].
Ubu takes one argument, a [command] descriptor, and undoes the
[command]s from :[max] (aka :x) up to, but not including, the
indicated command. See [command-descriptor].
Ubu can cause errors. To avoid these, see [ubu!].
For appropriate queries to be made, see [ubu?].
Also see [ubt], which is similar but also undoes the indicated
command. As for :[ubt], :[oops] will undo the undo (see [oops]) and
[ubu] will not undo into ``prehistory''.
See [u] for how to undo just the latest command, and see [ubt],
[ubt!], and [ubt?] for how to undo back through (that is,
including) the current command.")
(UBU!
(HISTORY)
"Undo [command]s, without a query or an error
Example:
:ubu! :x-4
The keyword [command] :ubu! is the same as :[ubu], but with a
guarantee that it is ``error-free.'' More precisely, the
[error-triple] returned by :ubu! will always be of the form (mv nil
val state). :[Oops] will undo the last :ubu!. Also see [ubu],
[ubu?], [ubt], [ubt!], [ubt?], and [u].")
(UBU?
(HISTORY)
"Undo [command]s, with queries as appropriate
Example:
:ubu? :x-4
The keyword [command] :ubu? is the same as :[ubu], but with
appropriate queries made. :[Oops] will undo the last :ubu?. Also
see [ubu!], [ubu], [ubt!], [ubt], [ubt?], and [u].")
(UNARY--
(NUMBERS ACL2-BUILT-INS)
"Arithmetic negation function
Completion Axiom (completion-of-unary-minus):
(equal (unary-- x)
(if (acl2-numberp x)
(unary-- x)
0))
[Guard] for (unary-- x):
(acl2-numberp x)
Notice that like all arithmetic functions, unary-- treats non-numeric
inputs as 0.
Calls of the macro [-] on one argument expand to calls of unary--;
see [-].")
(UNARY-/
(NUMBERS ACL2-BUILT-INS)
"Reciprocal function
Completion Axiom (completion-of-unary-/):
(equal (unary-/ x)
(if (and (acl2-numberp x)
(not (equal x 0)))
(unary-/ x)
0))
[Guard] for (unary-/ x):
(and (acl2-numberp x)
(not (equal x 0)))
Notice that like all arithmetic functions, unary-/ treats non-numeric
inputs as 0.
Calls of the macro [/] on one argument expand to calls of unary-/;
see [/].")
(UNCERTIFIED-BOOKS
(BOOKS)
"Invalid [certificate]s and uncertified [books]
For relevant background see [books], see [certificate], and see
[portcullis].
[Include-book] has a special provision for dealing with an
uncertified book, i.e., a file with no [certificate] or an invalid
[certificate] (i.e., one whose check sums describe files other than
the ones actually read). In this case, a warning is printed and the
book is otherwise processed much as though it were certified and
had an open [portcullis].
If a book B.lisp is uncertified and a file B.port exists, then the
forms in B.port are evaluated before the forms in B.lisp. Such a
file B.port is typically created calling [certify-book] on book \"B\"
with argument :write-port t, so that B.port contains the
[portcullis] [command]s for B (the commands present in the [world]
when that certification was attempted). To avoid loading .port
files, see [compilation].
Inclusion of uncertified books can be handy, but it can have
disastrous consequences.
The provision allowing uncertified [books] to be included can have
disastrous consequences, ranging from hard lisp errors, to damaged
memory, to quiet logical inconsistency.
It is possible for the inclusion of an uncertified book to render the
logic inconsistent. For example, one of its non-[local] [events]
might be (defthm t-is-nil (equal t nil)). It is also possible for
the inclusion of an uncertified book to cause hard errors or
[breaks] into raw Common Lisp. For example, if the file has been
edited since it was certified, it may contain too many open
parentheses, causing Lisp to read past ``end of file.'' Similarly,
it might contain non-ACL2 objects such as 3.1415 or ill-formed
event forms that cause ACL2 code to break.
Even if a book is perfectly well formed and could be certified (in a
suitable extension of ACL2's initial [world]), its uncertified
inclusion might cause Lisp errors or inconsistencies! For example,
it might mention packages that do not exist in the host [world],
especially if the .port file (discussed above) does not exist from
an earlier certification attempt. The [portcullis] of a certified
book ensures that the correct [defpkg]s have been admitted, but if
a book is read without actually raising its [portcullis], symbols
in the file, e.g., acl2-arithmetic::fn, could cause ``unknown
package'' errors in Common Lisp. Perhaps the most subtle disaster
occurs if the host [world] does have a [defpkg] for each package
used in the book but the host [defpkg] imports different symbols
than those required by the [portcullis]. In this case, it is
possible that formulas which were theorems in the certified book
are non-theorems in the host [world], but those formulas can be
read without error and will then be quietly assumed.
In short, if you include an uncertified book, all bets are off
regarding the validity of the future behavior of ACL2.
That said, it should be noted that ACL2 is pretty tough and if errors
don't occur, the chances are that deductions after the inclusion of
an uncertified book are probably justified in the (possibly
inconsistent) logical extension obtained by assuming the
admissibility and validity of the definitions and conjectures in
the book.")
(UNDOCUMENTED_TOPIC
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Undocumented Topic
This topic has not yet been documented. Sorry")
(UNION$
(LISTS ACL2-BUILT-INS)
"Elements of one list that are not elements of another
General Forms:
(union$ l1 l2 ... lk)
(union$ l1 l2 ... lk :test 'eql) ; same as above
(union$ l1 l2 ... lk :test 'eq) ; same, but eq is equality test
(union$ l1 l2 ... lk :test 'equal) ; same, but equal is equality test
(Union$ x y) equals a list that contains both the members of x and
the members of y. More precisely, the resulting list is the same as
one would get by first deleting the members of y from x, and then
concatenating the result to the front of y. The optional keyword,
:TEST, has no effect logically, but provides the test (default
[eql]) used for comparing members of the two lists.
Union$ need not take exactly two arguments: (union$) is nil, (union$
x) is x, (union$ x y z ... :test test) is (union$ x (union$ y z ...
:test test) :test test), and if :TEST is not supplied, then (union$
x y z ...) is (union$ x (union$ y z ...)). For the discussion below
we restrict ourselves, then, to the cases (union$ x y) and (union$
x y :test test).
The [guard] for a call of union$ (in the two cases just above)
depends on the test. In all cases, both arguments must satisfy
[true-listp]. If the test is [eql], then one of the arguments must
satisfy [eqlable-listp]. If the test is [eq], then one of the
arguments must satisfy [symbol-listp].
See [equality-variants] for a discussion of the relation between
union$ and its variants:
(union-eq x lst) is equivalent to (union$ x lst :test 'eq);
(union-equal x lst) is equivalent to (union$ x lst :test 'equal).
In particular, reasoning about any of these primitives reduces to
reasoning about the function union-equal.
Function: <union-equal>
(defun
union-equal (l1 l2)
(declare (xargs :guard (and (true-listp l1) (true-listp l2))))
(cond ((endp l1) l2)
((member-equal (car l1) l2)
(union-equal (cdr l1) l2))
(t (cons (car l1)
(union-equal (cdr l1) l2)))))
Note that union-eq can take any number of arguments, in analogy to
union$; indeed, (union-eq ...) expands to (union$ ... :test 'eq).
However, union-equal is a function, not a macro, and takes exactly
two arguments.
Union$ is similar to the Common Lisp primitive union. However, Common
Lisp does not specify the order of elements in the result of a call
of union.")
(UNION-EQ (POINTERS) "See [union$].")
(UNION-EQUAL (POINTERS) "See [union$].")
(UNION-THEORIES
(THEORIES THEORY-FUNCTIONS)
"Union two [theories]
Example:
(union-theories (current-theory 'lemma3)
(theory 'arith-patch))
General Form:
(union-theories th1 th2)
where th1 and th2 are theories (see [theories]). To each of the
arguments there corresponds a runic theory. This function returns
the union of those two runic [theories], represented as a list and
ordered chronologically.
This ``function'' is actually a macro that expands to a term
mentioning the single free variable [world]. When theory
expressions are evaluated by [in-theory] or the :[in-theory] hint,
[world] is bound to the current ACL2 [world].")
(UNIVERSAL-THEORY
(THEORIES THEORY-FUNCTIONS)
"All rules as of logical name
Examples:
(universal-theory :here)
(universal-theory 'lemma3)
See [logical-name].
General Form:
(universal-theory logical-name)
Returns the theory consisting of all the [rune]s that existed
immediately after [logical-name] was introduced. See [theories] and
see [logical-name]. The theory includes [logical-name] itself (if
there is a rule by that name). (Note that since some [events] do
not introduce rules (e.g., [defmacro], [defconst] or [defthm] with
:[rule-classes] nil), the universal-theory does not necessarily
include a [rune] for every event name.) The universal-theory is
very long and you will probably regret printing it.
You may experience a fencepost problem in deciding which
[logical-name] to use. [Deflabel] can always be used to mark
unambiguously for future reference a particular point in the
development of your theory. This is convenient because [deflabel]
does not introduce any rules and hence it doesn't matter if you
count it as being in the interval or not. The order of [events] in
the vicinity of an [encapsulate] is confusing. See [encapsulate].
This ``function'' is actually a macro that expands to a term
mentioning the single free variable [world]. When theory
expressions are evaluated by [in-theory] or the :[in-theory] hint,
[world] is bound to the current ACL2 [world].
Also see [current-theory]. Current-theory is much more commonly used
than universal-theory. The former includes only the [enable]d
[rune]s as of the given [logical-name], which is probably what you
want, while the latter includes [disable]d ones as well.")
(UNMEMOIZE
(MEMOIZE PROGRAMMING HONS-AND-MEMOIZATION EVENTS)
"Turn off memoization for the specified function
Example:
(unmemoize 'foo) ; turn off memoization of foo
General Form:
(unmemoize fn)
where fn evaluates to a function symbol that is currently memoized;
see [memoize]. An exception is that as with [memoize], fn may
evaluate to the name of a macro that is associated with such a
function symbol; see [macro-aliases-table].
Calls of this macro generate events of the form (table memoize-table
fn nil). When successful, the returned value is of the form (mv nil
function-symbol state).
To remove the effects of all [memoize] [events], evaluate:
(clear-memo-table). To save and restore memoization, see
[save-and-clear-memoization-settings] and see
[restore-memoization-settings].")
(UNMONITOR
(BREAK-REWRITE)
"To stop monitoring a rule name
Examples:
(unmonitor '(:rewrite assoc-of-app))
:unmonitor (:rewrite assoc-of-app)
:unmonitor :all
General Forms:
(unmonitor rune)
(unmonitor :all)
Here, rune is a [rune] that is currently among those with break
points installed. This function removes the break.
Subtle point: Because you may want to unmonitor a ``[rune]'' that is
no longer a [rune] in the current ACL2 [world], we don't actually
check this about [rune]. Instead, we simply check that [rune] is a
consp beginning with a keywordp. That way, you'll know you've made
a mistake if you try to :unmonitor binary-append instead of
:unmonitor (:definition binary-append), for example.")
(UNQUOTE
'ACL2-BUILT-INS
"Obtain the object being quoted
Unquote is just an abbrevation for [cadr]. Its intended use is to
obtain an object being quoted. For example, if x is (quote (3 4))
then (unquote x) is (3 4):
ACL2 !>(let ((x '(quote (3 4))))
(unquote x))
(3 4)
ACL2 !>")
(UNSAVE
(PROOF-CHECKER)
"Remove a [proof-checker] state
Example:
(unsave assoc-of-append)
General Form:
(unsave name)
Eliminates the association of a [proof-checker] state with name. See
[unsave] or see [ACL2-pc::unsave].
Also see [ACL2-pc::save] and see [retrieve].")
(UNSIGNED-BYTE-P
(NUMBERS ACL2-BUILT-INS)
"Recognizer for natural numbers that fit in a specified bit width
(Unsigned-byte-p bits x) is T when bits is a positive integer and x
is a nonnegative integer that fits into a bit-width of bits, i.e.,
0 <= x < 2^bits.
Note that a [type-spec] of (unsigned-byte i) for a variable x in a
function's [declare] form translates to a [guard] condition of
(unsigned-byte-p i x).
The [guard] for unsigned-byte-p is T.
Function: <unsigned-byte-p>
(defun unsigned-byte-p (bits x)
(declare (xargs :guard t))
(and (integerp bits)
(<= 0 bits)
(integer-range-p 0 (expt 2 bits) x)))")
(UNSUPPORTED-PARALLELISM-FEATURES
(PARALLELISM)
"ACL2 features not supported in ACL2(p)
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
See [parallelism-tutorial] for an introduction to parallel
programming in ACL2.
For proof features of ACL2 that are not yet supported when parallel
execution is enabled for the primary ACL2 proof process, generally
known as ``the waterfall'', see
[unsupported-waterfall-parallelism-features].
Please note that this topic discusses ACL2 features that are disabled
when using ACL2(p) (see [compiling-ACL2p]). These features are
disabled regardless of whether waterfall parallelism is enabled.
Calls of [observation-cw] simply convert to calls of [cw], so
suppressing [observation]s (see [set-inhibit-output-lst]) will not
suppress these messages.
Memoization is not supported when executing in parallel. See
[Unsupported-waterfall-parallelism-features] for memoization
details related to waterfall parallelism.
Since, as of April 2012, garbage collection is inherently sequential,
ACL2(p) minimizes the use of garbage collection by setting a high
garbage collection threshold. As a result, ACL2(p) is not expected
to perform well on machines with less memory than this threshold (1
gigabyte, as of April 2012).
In CCL, the underlying parallel execution engine is tuned for the
number of CPU cores (or hardware threads) actually available in the
machine. SBCL and LispWorks are tuned for a machine with 16 CPU
cores.
CCL is considered to be the ``flagship Lisp'' for parallel execution
in ACL2. The SBCL and LispWorks implementations are thought to be
generally stable. However, due to their relatively less common use,
the SBCL and LispWorks implementations are likely less robust than
the CCL implementation.
The [time-tracker] utility is a no-op for ACL2(p).")
(UNSUPPORTED-WATERFALL-PARALLELISM-FEATURES
(PARALLEL-PROOF)
"Proof features not supported with waterfall-parallelism enabled
For a general introduction to ACL2(p), an experimental extension of
ACL2 that supports parallel execution and proof, see [parallelism].
Please note that although this extension is usable and, we hope,
robust in its behavior, there are still known issues to address
beyond those listed explicitly below. While we expect ACL2(p) to
perform correctly, it may never have the same level of attention to
correctness as is given to ACL2; see [parallelism], specifically
the ``IMPORTANT NOTE'' there.
Below we list proof features of ACL2 that are not yet supported when
parallel execution is enabled for the primary ACL2 proof process,
generally known as ``the waterfall'', typically by calling
[set-waterfall-parallelism].
Please note that this topic is limited to the case that such
waterfall parallelism is enabled. We believe that all ACL2 proof
procedures are supported when waterfall parallelism is disabled,
even in executables that support parallelism (see
[compiling-ACL2p]).
Without a trust tag (see [defttag]): We support [clause-processor]s,
[computed-hints], and [custom-keyword-hints] that do not modify
[state], but we do not permit [override-hints], regardless of
whether they modify state. With a trust tag, the user can use
[clause-processor]s that modify state and can also use
[override-hints] (see [set-waterfall-parallelism-hacks-enabled] for
a convenient mechanism for adding a trust tag). See
[error-triples-and-parallelism] for a discussion of how to avoid
modifying state in such situations. Regardless of whether a trust
tag is active: We do not support checkers of [custom-keyword-hints]
to be anything but the default checker.
GNU Make versions 3.81 and 3.82 formerly caused a lot of problems
(version 3.80 somewhat less so), at least on Linux, when certifying
books with ACL2 built on a host Lisp of CCL using `make'. CCL was
updated around March 23, 2011 to fix this problem, so if you get
segfaults (for example) with CCL, try updating your CCL
installation.
Book certification should generally work but may present some issues,
including the following.
* The standard `make'-based process for book certification will not use
[waterfall-parallelism], which is disabled by default (even
when [compiling-ACL2p] by using the ACL2_PAR flag). See
[books-certification] and see [books-certification-classic],
which explain that [ACL2-customization] files are ignored
during that process unless specified explicitly on the command
line or in the environment.
* A book certified with ACL2(p) might subsequently cause an error when
included with ACL2. As of this writing, however, we have only
seen this for a book in which [deftheory-static] is used.
* In general, ACL2(p) is primarily intended to support more rapid
interactive development. While we are unaware of an unsoundness
likely to affect an ACL2(p) user, we suggest using ACL2 for
final book certification, rather than ACL2(p), to lower the
risk of unsound book certification.
Proof output can contain repeated printing of the same subgoal name.
[Gag-mode] isn't officially supported, although it has proved helpful
to use ACL2(p) in conjunction with (set-gag-mode t) (because this
setting suppresses the output that occurs outside the waterfall).
This being said, ACL2(p) also prints key checkpoints (for example
see [introduction-to-key-checkpoints]), but with a notion of ``key
checkpoint'' that does not take into account whether the goal is
later proved by induction. See [ACL2p-key-checkpoints] for further
explanation of these key checkpoints. Note that [pso] is also not
supported.
The :[brr] utility is not supported.
The [accumulated-persistence] utility is not supported.
Tracking for [forward-chaining-reports] is not supported (see
[set-fc-criteria]).
Time limits (see [with-prover-time-limit]) aren't supported.
The timing information printed at the end of a proof attempt, which
is intended to represent cpu time (not wall-clock time), may be
somewhat inaccurate when [waterfall-parallelism] is non-nil.
Consider using [time$] to obtain timing information.
The use of [wormhole]s is not recommended, as there may be race
conditions.
Output specific to :OR [hints] is disabled.
Proof trees are likely not to work as originally designed.
The use of [set-inhibit-output-lst] may not fully inhibit proof
output.
Reporting of [splitter] rules is currently unsupported when
waterfall-parallelism is on.
Interrupting a proof attempt is not yet properly supported. At a
minimum, interrupts are trickier with waterfall parallelism
enabled. For one, the user typically needs to issue the interrupt
twice before the proof attempt is actually interrupted.
Additionally, on rare occasions the theorem is registered as
proved, even though the prover did not finish the proof. If this
occurs, issue a :u (see [ubt]) and you will likely be at a stable
state.
Also with regards to interrupting a proof attempt, sometimes the user
may need to issue a :q and lp to reset properly the parallelism
implementation to a stable state. The primary symptom that the user
is experiencing this issue is that threads will continue to compute
in the background, even though there should be no proof attempt in
progress. The user can observe this symptom by examining the CPU
utilization of their ACL2 process, for example on Linux/Unix with
the shell process top. Lisp usage greater than a few percent is
indicative of this problem.
Because of how ACL2 [arrays] are designed, the user may find that, in
practice, ACL2 arrays work (but perhaps with some
[slow-array-warning] messages). However, we are aware of race
conditions that can cause problems.
Instead of dynamically monitoring rewrites, [dmr] instead dynamically
outputs information helpful for debugging the performance of proof
parallelism. The instructions concerning how to see this debugging
information are the same as the instructions for enabling [dmr]
mode.
If you are working with LispWorks 6.0 or 6.0.1, then you may see
messages about misaligned conses. The state of the system may be
corrupted after such a message has been printed. This LispWorks bug
is fixed in LispWorks 6.1.
The waterfall parallelism mode :resource-and-timing-based is not
fully supported when the host Lisp is other than CCL. It may work,
but we have not attempted to address a potential race condition.
Proof output for splitter rules (see [splitter]) is currently
unsupported when waterfall-parallelism is enabled.
Memoization may not work as intended when executing in parallel
(including the waterfall). In an effort to be helpful to the user,
the functions automatically memoized by ACL2 are unmemoized when
setting waterfall parallelism to anything but nil. Those exact
functions are again memoized once waterfall parallelism is
disabled. Additionally, any functions memoized within the ACL2 loop
(by a call of [memoize]) are also unmemoized when enabling
waterfall parallelism and once again memoized when disabling
waterfall parallelism. This is implemented by returning the
memoization state to what it was before enabling waterfall
parallelism. As such, the user should be aware that any changes
made to the memoization state while waterfall parallelism is
enabled will be lost once waterfall parallelism is disabled.")
(UNTRACE$
(TRACE)
"Untrace functions
Examples:
(untrace$) ; untrace all functions previously
; traced (e.g. with trace$ or trace!)
(untrace$ foo bar) ; as above, except only untrace foo and bar
General Forms:
(untrace$) ; untrace all (as noted above)
(untrace$ fn1 fn2 ... fnk) ; untrace the indicated functions
where the fni were previously traced (e.g. with [trace$] or
[trace!]).
Untrace$ undoes the effect of [trace$]. See [trace$]. The value
returned by untrace$ gives the list of functions for which tracing
is being removed.")
(UNTRANS-TABLE
(MACROS)
"Associates a function symbol with a macro for printing user-level
terms
Examples:
ACL2 !>(untrans-table (w state))
((BINARY-+ + . T)
(BINARY-* * . T)
(BINARY-APPEND APPEND . T)
(BINARY-LOGAND LOGAND . T)
(BINARY-LOGIOR LOGIOR . T)
(BINARY-LOGXOR LOGXOR . T)
(BINARY-LOGEQV LOGEQV . T)
(BINARY-POR POR . T)
(BINARY-PAND PAND . T))
See [table] for a general discussion of tables.
See [add-macro-fn] for a more general discussion of this [table] and
for a way to associate a macro name with a function name in theory
events.")
(UNTRANSLATE (POINTERS)
"See [user-defined-functions-table].")
(UNTRANSLATE-PREPROCESS (POINTERS)
"See [user-defined-functions-table].")
(UPDATE-NTH
(LISTS ACL2-BUILT-INS)
"Modify a list by putting the given value at the given position
(Update-nth key val l) returns a list that is the same as the list l,
except that the value at the 0-based position key (a natural
number) is val.
If key is an integer at least as large as the length of l, then l
will be padded with the appropriate number of nil elements, as
illustrated by the following example.
ACL2 !>(update-nth 8 'z '(a b c d e))
(A B C D E NIL NIL NIL Z)
We have the following theorem.
(implies (and (true-listp l)
(integerp key)
(<= 0 key))
(equal (length (update-nth key val l))
(if (< key (length l))
(length l)
(+ 1 key))))
The [guard] of update-nth requires that its first (position) argument
is a natural number and its last (list) argument is a true list.
Function: <update-nth>
(defun update-nth (key val l)
(declare (xargs :guard (true-listp l))
(type (integer 0 *) key))
(cond ((zp key) (cons val (cdr l)))
(t (cons (car l)
(update-nth (1- key) val (cdr l))))))
Subtopics
[Nth-aliases-table]
A [table] used to associate names for nth/update-nth printing")
(UPDATE-NTH-ARRAY
(STOBJ ACL2-BUILT-INS)
"Update a stobj array
Update-nth-array is called by [stobj] updaters to modify stobj array
fields. See [stobj-example-3] for a discussion of this function and
how it plays that role.
Function: <update-nth-array>
(defun update-nth-array (j key val l)
(declare (xargs :guard (and (integerp j)
(integerp key)
(<= 0 j)
(<= 0 key)
(true-listp l)
(true-listp (nth j l)))))
(update-nth j (update-nth key val (nth j l))
l))")
(UPPER-CASE-P
(CHARACTERS ACL2-BUILT-INS)
"Recognizer for upper case characters
(Upper-case-p x) is true if and only if x is an upper case character,
i.e., a member of the list #\\A, #\\B, ..., #\\Z.
The [guard] for upper-case-p requires its argument to be a standard
character (see [standard-char-p]).
Upper-case-p is a Common Lisp function. See any Common Lisp
documentation for more information.
Function: <upper-case-p>
(defun upper-case-p (x)
(declare (xargs :guard (and (characterp x)
(standard-char-p x))))
(and (member x
'(#\\A #\\B #\\C #\\D #\\E #\\F #\\G
#\\H #\\I #\\J #\\K #\\L #\\M #\\N #\\O #\\P #\\Q
#\\R #\\S #\\T #\\U #\\V #\\W #\\X #\\Y #\\Z))
t))")
(USE (POINTERS)
"See [hints] for keyword :use.")
(USER-DEFINED-FUNCTIONS-TABLE
(MACROS)
"An advanced [table] used to replace certain system functions
Examples:
(table user-defined-functions-table 'untranslate-preprocess 'my-preprocess)
(table user-defined-functions-table 'untranslate 'my-untranslate)
This feature should perhaps only be used by advanced users who have a
thorough understanding of the system functions being replaced.
There are currently two ways a user can affect the way ACL2 prints
terms.
The first example associates the user-defined function symbol
my-preprocess with untranslate-preprocess. As a result, when ACL2
prints a term, say during a proof, using its so-called
``untranslate'' process the first thing it does is to call
my-preprocess on two arguments: that term and the current ACL2
logical [world]. If the call produces a non-nil result, then that
result is passed to the untranslate process.
The second example associates the user-defined function symbol
my-untranslate with the built-in function symbol untranslate. As a
result, the code for my-untranslate will be run whenever the
untranslate process is run. The formals of the two functions must
agree and must not contain any [stobj] names. Note that these
overrides fail to occur upon guard violations and some other
evaluation errors.
The untranslate-preprocess approach may suffice for most cases in
which a user wants to modify the way output is produced by the
theorem prover. We present an example immediately below, but see
[untranslate-patterns] for a more elaborate example. If the
untranslate-preprocess approach does not seem sufficient for your
purposes, you are invited to look at community book
books/misc/rtl-untranslate.lisp or the source code for [define] for
an example of user-defined untranslate (i.e., following the second
example displayed above).
Suppose you have a large constant that you would prefer not to see in
proofs. For example, you may have submitted the following
definition (but imagine a much larger constant, say, a list of
length 1,000,000).
(defconst *a* '(a b c d))
If you submit the following (silly) theorem
(thm (equal (cons x *a*) (car (cons yyy zzz))))
then you will see the following output:
(EQUAL (CONS X '(A B C D)) YYY).
If *a* had represented a much larger structure, we would wish we
could see the following instead.
(EQUAL (CONS X *A*) YYY)
That can be accomplished as follows. First we make the following
definition.
(defun my-preprocess (term wrld)
(declare (ignore wrld))
(if (equal term (list 'quote *a*))
'*a*
nil))
Now we submit the following [table] event.
(table user-defined-functions-table
'untranslate-preprocess
'my-preprocess)
This will install my-preprocess as a preprocessor before the normal
untranslation routine is applied to printing a term. When the
untranslation routine encounters the constant (QUOTE (A B C D)), it
will replace it with *a*, and the usual untranlation routine will
print this as *A*.")
(USING-COMPUTED-HINTS
(COMPUTED-HINTS HINTS)
"How to use computed hints
Computed hints (see [computed-hints]) are extraordinarily powerful.
We show a few examples here to illustrate their use. We recommend
that the using-computed-hints-n topics be read in the order
using-computed-hints-1, using-computed-hints-2, and so on.
Subtopics
[Using-computed-hints-1]
Driving Home the Basics
[Using-computed-hints-2]
One Hint to Every Top-Level Goal in a Forcing Round
[Using-computed-hints-3]
Hints as a Function of the Goal (not its Name)
[Using-computed-hints-4]
Computing the Hints
[Using-computed-hints-5]
Debugging Computed Hints
[Using-computed-hints-6]
Using the computed-hint-replacement feature
[Using-computed-hints-7]
Using the stable-under-simplificationp flag
[Using-computed-hints-8]
Some Final Comments")
(USING-COMPUTED-HINTS-1
(USING-COMPUTED-HINTS)
"Driving Home the Basics
The common hint
(\"Subgoal 3.2.1''\" :use lemma42)
has the same effect as the computed hint
(if (equal id '((0) (3 2 1) . 2))
'(:use lemma42)
nil)
which, of course, is equivalent to
(and (equal id '((0) (3 2 1) . 2))
'(:use lemma42))
which is also equivalent to the computed hint
my-special-hint
provided the following defun has first been executed
(defun my-special-hint (id clause world)
(declare (xargs :mode :program)
(ignore clause world))
(if (equal id '((0) (3 2 1) . 2))
'(:use lemma42)
nil))
It is permitted for the defun to be in :LOGIC mode (see [defun-mode])
also.
Just to be concrete, the following three events all behave the same
way (if my-special-hint is as above):
(defthm main (big-thm a b c)
:hints ((\"Subgoal 3.2.1''\" :use lemma42)))
(defthm main (big-thm a b c)
:hints ((and (equal id '((0) (3 2 1) . 2)) '(:use lemma42))))
(defthm main (big-thm a b c)
:hints (my-special-hint))")
(USING-COMPUTED-HINTS-2
(USING-COMPUTED-HINTS)
"One Hint to Every Top-Level Goal in a Forcing Round
Suppose the main proof completes with a forcing round on three
subgoals, \"[1]Subgoal 3\", \"[1]Subgoal 2\", and \"[1]Subgoal 1\".
Suppose you wish to :use lemma42 in all top-level goals of the
first forcing round. This can be done supplying the hint
(if test '(:use lemma42) nil),
where test is an expression that returns t when ID is one of the
clause ids in question.
goal-spec (parse-clause-id goal-spec)
\"[1]Subgoal 3\" ((1) (3) . 0)
\"[1]Subgoal 2\" ((1) (2) . 0)
\"[1]Subgoal 1\" ((1) (1) . 0)
Recall (see [clause-identifier]) that parse-clause-id maps from a
goal spec to a clause id, so you can use that function on the goal
specs printed in the failed proof attempt to determine the clause
ids in question.
So one acceptable test is
(member-equal id '(((1) (3) . 0)
((1) (2) . 0)
((1) (1) . 0)))
or you could use parse-clause-id in your computed hint if you don't
want to see clause ids in your script:
(or (equal id (parse-clause-id \"[1]Subgoal 3\"))
(equal id (parse-clause-id \"[1]Subgoal 2\"))
(equal id (parse-clause-id \"[1]Subgoal 1\")))
or you could use the inverse function (see [clause-identifier]):
(member-equal (string-for-tilde-@-clause-id-phrase id)
'(\"[1]Subgoal 3\"
\"[1]Subgoal 2\"
\"[1]Subgoal 1\"))
Recall that what we've shown above are the tests to use in the
computed hint. The hint itself is (if test '(:use lemma42) nil) or
something equivalent like (and test '(:use lemma42)).
The three tests above are all equivalent. They suffer from the
problem of requiring the explicit enumeration of all the goal specs
in the first forcing round. A change in the script might cause more
forced subgoals and the ones other than those enumerated would not
be given the hint.
You could write a test that recognizes all first round top-level
subgoals no matter how many there are. Just think of the
programming problem: how do I recognize all the clause id's of the
form ((1) (n) . 0)? Often you can come to this formulation of the
problem by using parse-clause-id on a few of the candidate
goal-specs to see the common structure. A suitable test in this
case is:
(and (equal (car id) '(1)) ; forcing round 1, top-level (pre-induction)
(equal (len (cadr id)) 1) ; Subgoal n (not Subgoal n.i ...)
(equal (cddr id) 0)) ; no primes
The test above is ``overkill'' because it recognizes precisely the
clause ids in question. But recall that once a computed hint is
used, it is (by default) removed from the hints available to the
children of the clause. Thus, we can widen the set of clause ids
recognized to include all the children without worrying that the
hint will be applied to those children.
In particular, the following test supplies the hint to every
top-level goal of the first forcing round:
(equal (car id) '(1))
You might worry that it would also supply the hint to the subgoal
produced by the hint -- the cases we ruled out by the ``overkill''
above. But that doesn't happen since the hint is unavailable to the
children. You could even write:
(equal (car (car id)) 1)
which would supply the hint to every goal of the form \"[1]Subgoal
...\" and again, because we see and fire on the top-level goals
first, we will not fire on, say, \"[1]Subgoal *1.3/2\", i.e., the id
'((1 1 3) (2) . 0) even though the test recognizes that id.
Finally, the following test supplies the hint to every top-level goal
of every forcing round (except the 0th, which is the ``gist'' of
the proof, not ``really'' a forcing round):
(not (equal (car (car id)) 0))
Recall again that in all the examples above we have exhibited the
test in a computed hint of the form (if test '(:key1 val1 ...)
nil).")
(USING-COMPUTED-HINTS-3
(USING-COMPUTED-HINTS)
"Hints as a Function of the Goal (not its Name)
Sometimes it is desirable to supply a hint whenever a certain term
arises in a conjecture. For example, suppose we have proved
(defthm all-swaps-have-the-property
(the-property (swap x))
:rule-classes nil)
and suppose that whenever (SWAP A) occurs in a goal, we wish to add
the additional hypothesis that (THE-PROPERTY (SWAP A)). Note that
this is equivalent supplying the hint
(if test
'(:use (:instance all-swaps-have-the-property (x A)))
nil)
where test answers the question ``does the clause contain (SWAP A)?''
That question can be asked with (occur-lst '(SWAP A) clause).
Briefly, occur-lst takes the representation of a translated term,
x, and a list of translated terms, y, and determines whether x
occurs as a subterm of any term in y. (By ``subterm'' here we mean
proper or improper, e.g., the subterms of (CAR X) are X and (CAR
X).)
Thus, the computed hint:
(if (occur-lst '(swap a) clause)
'(:use (:instance all-swaps-have-the-property (x A)))
nil)
will add the hypothesis (THE-PROPERTY (SWAP A)) to every goal
containing (SWAP A) -- except the children of goals to which the
hypothesis was added.
A COMMON MISTAKE users are likely to make is to forget that they are
dealing with translated terms. For example, suppose we wished to
look for (SWAP (LIST 1 A)) with occur-lst. We would never find it
with
(occur-lst '(SWAP (LIST 1 A)) clause)
because that presentation of the term contains macros and other
abbreviations. By using :trans (see [trans]) we can obtain the
translation of the target term. Then we can look for it with:
(occur-lst '(SWAP (CONS '1 (CONS A 'NIL))) clause)
Note in particular that you must
* eliminate all macros and
* explicitly quote all constants.
We recommend using :trans to obtain the translated form of the terms
in which you are interested, before programming your hints.
An alternative is to use the expression (prettyify-clause clause nil
nil) in your hint to convert the current goal clause into the
s-expression that is actually printed. For example, the clause
((NOT (CONSP X)) (SYMBOLP Y) (EQUAL (CONS '1 (CAR X)) Y))
``prettyifies'' to
(IMPLIES (AND (CONSP X)
(NOT (SYMBOLP Y)))
(EQUAL (CONS 1 (CAR X)) Y))
which is what you would see printed by ACL2 when the goal clause is
that shown.
However, if you choose to convert your clauses to prettyified form,
you will have to write your own explorers (like our occur-lst),
because all of the ACL2 term processing utilities work on
translated and/or clausal forms. This should not be taken as a
terrible burden. You will, at least, gain the benefit of knowing
what you are really looking for, because your explorers will be
looking at exactly the s-expressions you see at your terminal. And
you won't have to wade through our still undocumented term/clause
utilities. The approach will slow things down a little, since you
will be paying the price of independently consing up the
prettyified term.
We make one more note on this example. We said above that the
computed hint:
(if (occur-lst '(swap a) clause)
'(:use (:instance all-swaps-have-the-property (x A)))
nil)
will add the hypothesis (THE-PROPERTY (SWAP A)) to every goal
containing (SWAP A) -- except the children of goals to which the
hypothesis was added.
It bears noting that the subgoals produced by induction and top-level
forcing round goals are not children. For example, suppose the hint
above fires on \"Subgoal 3\" and produces, say, \"Subgoal 3'\". Then
the hint will not fire on \"Subgoal 3'\" even though it (still)
contains (SWAP A) because \"Subgoal 3'\" is a child of a goal on
which the hint fired.
But now suppose that \"Subgoal 3'\" is pushed for induction. Then the
goals created by that induction, i.e., the base case and induction
step, are not considered children of \"Subgoal 3'\". All of the
original hints are available.
Alternatively, suppose that \"Subgoal 3' is proved but forces some
other subgoal, \"[1]Subgoal 1\" which is attacked in Forcing Round 1.
That top-level forced subgoal is not a child. All the original
hints are available to it. Thus, if it contains (SWAP A), the hint
will fire and supply the hypothesis, producing \"[1]Subgoal 1'\".
This may be unnecessary, as the hypothesis might already be present
in \"[1]Subgoal 1\". In this case, no harm is done. The hint won't
fire on \"[1]Subgoal 1'\" because it is a child of \"[1]Subgoal 1\" and
the hint fired on that.")
(USING-COMPUTED-HINTS-4
(USING-COMPUTED-HINTS)
"Computing the Hints
So far we have used computed hints only to compute when a fixed set
of keys and values are to be used as a hint. But computed hints
can, of course, compute the set of keys and values. You might, for
example, write a hint that recognizes when a clause ``ought'' to be
provable by a :BDD hint and generate the appropriate hint. You
might build in a set of useful lemmas and check to see if the
clause is provable :BY one of them. You can keep all function
symbols disabled and use computed hints to compute which ones you
want to :EXPAND. In general, you can write a theorem prover for use
in your hints, provided you can get it to do its job by directing
our theorem prover.
Suppose for example we wish to find every occurrence of an instance
of (SWAP x) and provide the corresponding instance of
ALL-SWAPS-HAVE-THE-PROPERTY. Obviously, we must explore the clause
looking for instances of (SWAP x) and build the appropriate
instances of the lemma. We could do this in many different ways,
but below we show a general purpose set of utilities for doing it.
The functions are not defined in ACL2 but could be defined as
shown.
Our plan is: (1) Find all instances of a given pattern (term) in a
clause, obtaining a set of substitutions. (2) Build a set of
:instance expressions for a given lemma name and set of
substitutions. (3) Generate a :use hint for those instances when
instances are found.
The pair of functions below find all instances of a given pattern
term in either a term or a list of terms. The functions each return
a list of substitutions, each substitution accounting for one of
the matches of pat to a subterm. At this level in ACL2
substitutions are lists of pairs of the form (var . term). All
terms mentioned here are presumed to be in translated form.
The functions take as their third argument a list of substitutions
accumulated to date and add to it the substitutions produced by
matching pat to the subterms of the term. We intend this
accumulator to be nil initially. If the returned value is nil, then
no instances of pat occurred.
(mutual-recursion
(defun find-all-instances (pat term alists)
(declare (xargs :mode :program))
(mv-let
(instancep alist)
(one-way-unify pat term)
(let ((alists (if instancep (add-to-set-equal alist alists) alists)))
(cond
((variablep term) alists)
((fquotep term) alists)
(t (find-all-instances-list pat (fargs term) alists))))))
(defun find-all-instances-list (pat list-of-terms alists)
(declare (xargs :mode :program))
(cond
((null list-of-terms) alists)
(t (find-all-instances pat
(car list-of-terms)
(find-all-instances-list pat
(cdr list-of-terms)
alists))))))
Caveat: The following aside has nothing to do with computed hints.
Does an instance of (CAR (CDR x)) occur in ((LAMBDA (V) (CAR V))
(CDR A))? It does if one beta-reduces the lambda-expression to (CAR
(CDR A)); the appropriate substitution is to replace x by A. But
the definition of find-all-instances above does not find this
instance because it does not do beta-reduction.
We now turn our attention to converting a list of substitutions into
a list of lemma instances, each of the form
(:INSTANCE name (var1 term1) ... (vark termk))
as written in :use hints. In the code shown above, substitutions are
lists of pairs of the form (var . term), but in lemma instances we
must write ``doublets.'' So here we show how to convert from one to
the other:
(defun pairs-to-doublets (alist)
(declare (xargs :mode :program))
(cond ((null alist) nil)
(t (cons (list (caar alist) (cdar alist))
(pairs-to-doublets (cdr alist))))))
Now we can make a list of lemma instances:
(defun make-lemma-instances (name alists)
(declare (xargs :mode :program))
(cond
((null alists) nil)
(t (cons (list* :instance name (pairs-to-doublets (car alists)))
(make-lemma-instances name (cdr alists))))))
Finally, we can package it all together into a hint function. The
function takes a pattern, pat, which must be a translated term, the
name of a lemma, name, and a clause. If some instances of pat occur
in clause, then the corresponding instances of name are :USEd in
the computed hint. Otherwise, the hint does not apply.
(defun add-corresponding-instances (pat name clause)
(declare (xargs :mode :program))
(let ((alists (find-all-instances-list pat clause nil)))
(cond
((null alists) nil)
(t (list :use (make-lemma-instances name alists))))))
The design of this particular hint function makes it important that
the variables of the pattern be the variables of the named lemma
and that all of the variables we wish to instantiate occur in the
pattern. We could, of course, redesign it to allow ``free
variables'' or some sort of renaming.
We could now use this hint as shown below:
(defthm ... ...
:hints ((add-corresponding-instances
'(SWAP x)
'ALL-SWAPS-HAVE-THE-PROPERTY
clause)))
The effect of the hint above is that any time a clause arises in
which any instance of (SWAP x) appears, we add the corresponding
instance of ALL-SWAPS-HAVE-THE-PROPERTY. So for example, if Subgoal
*1/3.5 contains the subterm (SWAP (SWAP A)) then this hint fires
and makes the system behave as though the hint:
(\"Subgoal *1/3.5\"
:USE ((:INSTANCE ALL-SWAPS-HAVE-THE-PROPERTY (X A))
(:INSTANCE ALL-SWAPS-HAVE-THE-PROPERTY (X (SWAP A)))))
had been present.")
(USING-COMPUTED-HINTS-5
(USING-COMPUTED-HINTS)
"Debugging Computed Hints
We have found that it is sometimes helpful to define hints so that
they print out messages to the terminal when they fire, so you can
see what hint was generated and which of your computed hints did
it.
To that end we have defined a macro we sometimes use. Suppose you
have a :hints specification such as:
:hints (computed-hint-fn (hint-expr id))
If you defmacro the macro below you could then write instead:
:hints ((show-hint computed-hint-fn 1)
(show-hint (hint-expr id) 2))
with the effect that whenever either hint is fired (i.e., returns
non-nil), a message identifying the hint by the marker (1 or 2,
above) and the non-nil value is printed.
(defmacro show-hint (hint &optional marker)
(cond
((and (consp hint)
(stringp (car hint)))
hint)
(t
`(let ((marker ,marker)
(ans ,(if (symbolp hint)
`(,hint id clause world stable-under-simplificationp)
hint)))
(if ans
(prog2$
(cw \"~%***** Computed Hint~#0~[~/ (from hint ~x1)~]~%~x2~%~%\"
(if (null marker) 0 1)
marker
(cons (string-for-tilde-@-clause-id-phrase id)
ans))
ans)
nil)))))
Note that when show-hint is applied to a hint that is a symbol, e.g.,
computed-hint-fn, it applies the symbol to the four computed-hint
arguments: id, clause, world, and stable-under-simplificationp. If
computed-hint-fn is of arity 3 the code above would cause an error.
One way to avoid it is to write
:hints ((show-hints (computed-hint-fn id clause world) 1)
(show-hint (hint-expr id) 2)).
If you only use computed hints of arity 3, you might eliminate the
occurrence of stable-under-simplificationp in the definition of
show-hint above.
Putting a show-hint around a common hint has no effect. If you find
yourself using this utility let us know and we'll consider putting
it into the system itself. But it does illustrate that you can use
computed hints to do unusual things.")
(USING-COMPUTED-HINTS-6
(USING-COMPUTED-HINTS)
"Using the computed-hint-replacement feature
So far none of our computed hints have used the
:COMPUTED-HINT-REPLACEMENT feature. We now illustrate that.
The :computed-hint-replacement feature can easily lead to loops. So
as you experiment with the examples in this section and your own
hints using this feature, be ready to interrupt the theorem prover
and abort!
A non-looping use of the :computed-hint-replacement feature would be
a hint like this:
(if (certain-terms-present clause)
'(:computed-hint-replacement t
:in-theory (enable lemma25))
'(:computed-hint-replacement t
:in-theory (disable lemma25)))
In this hint, if certain terms are present in clause, as determined
by the function with the obvious name (here undefined), then this
hint enables lemma25 and otherwise disables it. Lemma25 might be a
very expensive lemma, e.g., one that matches frequently and has an
expensive and rarely established hypothesis. One might wish it
enabled only under certain conditions. Recall that theories are
inherited by children. So once lemma25 is enabled it ``stays''
enabled for the children, until disabled; and vice versa. If the
:computed-hint-replacement feature were not present and computed
hints were always deleted after they had been used, then lemma25
would be left enabled (or disabled) for all the childen produced by
the first firing of the hint. But with the arrangement here, every
subgoal gets a theory deemed suitable by the hint, and the hint
persists.
Now we will set up a toy to allow us to play with computed hints to
understand them more deeply. To follow the discussion it is best to
execute the following events.
(defstub wrapper (x) t)
(defaxiom wrapper-axiom (wrapper x) :rule-classes nil)
Now submit the following event and watch what happens.
(thm (equal u v)
:hints (`(:use (:instance wrapper-axiom (x a)))))
The theorem prover adds (wrapper a) to the goal and then abandons the
proof attempt because it cannot prove the subgoal. Since the
computed hint is deleted upon use, the hint is not applied to the
subgoal (i.e., the child of the goal).
What happens if we do the following?
(thm (equal u v)
:hints (`(:computed-hint-replacement t
:use (:instance wrapper-axiom (x a)))))
As one might expect, this loops forever: The hint is applied to the
child and adds the hypothesis again. When the hint fires, nothing
is actually changed, since (wrapper a) is already in the subgoal.
So let's change the experiment a little. Let's make the hint add the
hypothesis (wrapper p) where p is the first literal of the clause.
This is silly but it allows us to explore the behavior of computed
hints a little more.
(thm (equal u v)
:hints (`(:use (:instance wrapper-axiom (x ,(car clause))))))
So in this case, the theorem prover changes the goal to
(IMPLIES (WRAPPER (EQUAL U V)) (EQUAL U V))
which then simplifies to
(IMPLIES (WRAPPER NIL) (EQUAL U V))
because the concluding equality can be assumed false in the
hypothesis (e.g., think of the contrapositive version). Nothing
else happens because the hint has been removed and so is not
applicable to the child.
Now consider the following -- and be ready to interrupt it and abort!
(thm (equal u v)
:hints (`(:computed-hint-replacement t
:use (:instance wrapper-axiom (x ,(car clause))))))
This time the hint is not removed and so is applied to the child. So
from Goal we get
Goal'
(IMPLIES (WRAPPER (EQUAL U V))
(EQUAL U V))
and then
Goal''
(IMPLIES (AND (WRAPPER (NOT (WRAPPER (EQUAL U V))))
(WRAPPER (EQUAL U V)))
(EQUAL U V))
etc.
First, note that the hint is repeatedly applied to its children. That
is because we wrote :computed-hint-replacement t. But second, note
that Goal' is not even being simplified before Goal'' is produced
from it. If it were being simplified, the (equal u v)'s in the
hypotheses would be replaced by nil. This is a feature. It means
after a computed hint has fired, other hints are given a chance at
the result, even the hint itself unless it is removed from the list
of hints.
As an exercise, let's arrange for the hint to stay around and be
applied indefinitely but with a simplification between each use of
the the hint. To do this we need to pass information from one
application of the hint to the next, essentially to say ``stay
around but don't fire.''
First, we will define a function to use in the hint. This is more
than a mere convenience; it allows the hint to ``reproduce itself''
in the replacement.
(defun wrapper-challenge (clause parity)
(if parity
`(:computed-hint-replacement ((wrapper-challenge clause nil))
:use (:instance wrapper-axiom (x ,(car clause))))
`(:computed-hint-replacement ((wrapper-challenge clause t)))))
Note that this function is not recursive, even though it uses its own
name. That is because the occurrence of its name is in a quoted
constant.
Now consider the following. What will it do?
(thm (equal u v)
:hints ((wrapper-challenge clause t)))
First, observe that this is a legal hint because it is a term that
mentions only the free variable CLAUSE. When defining hint
functions you may sometimes think their only arguments are the four
variables id, clause, world, and stable-under-simplificationp. That
is not so. But in your hints you must call those functions so that
those are the only free variables. Note also that the occurrence of
clause inside the :computed-hint-replacement is not an occurrence
of the variable clause but just a constant. Just store this note
away for a moment. We'll return to it momentarily.
Second, the basic cleverness of this hint is that every time it fires
it reproduces itself with the opposite parity. When the parity is t
it actually changes the goal by adding a hypothesis. When the
parity is nil it doesn't change the goal and so allows
simplification to proceed -- but it swaps the parity back to t.
What you can see with this simple toy is that we can use the
computed hints to pass information from parent to child.
Ok, so what happens when the event above is executed? Try it. You
will see that ACL2 applied the hint the first time. It doesn't get
around to printing the output because an error is caused before it
can print. But here is a blow-by-blow description of what happens.
The hint is evaluated on Goal with the clause ((equal u v)). It
produces a hint exactly as though we had typed:
(\"Goal\" :use (:instance wrapper-axiom (x (equal u v))))
which is applied to this goal. In addition, it produces the new hints
argument
:hints ((wrapper-challenge clause nil)).
By applying the \"Goal\" hint we get the new subgoal
Goal'
(implies (wrapper (equal u v))
(equal u v))
but this is not printed because, before printing it, the theorem
prover looks for hints to apply to it and finds
(wrapper-challenge clause nil)
That is evaluated and produces a hint exactly as though we had typed:
(\"Goal'\" )
and the new hints argument:
:hints ((wrapper-challenge clause nil)).
But if you supply the hint (\"Goal'\" ), ACL2 will signal an error
because it does not allow you to specify an empty hint!
So the definition of wrapper-challenge above is almost correct but
fatally flawed. We need a non-empty ``no-op'' hint. One such hint
is to tell the system to expand a term that will always be expanded
anyway. So undo wrapper-challenge, redefine it, and try the proof
again. Now remember the observation about clause that we asked you
to ``store'' above. The new definition of wrapper-challenge
illustrates what we meant. Note that the first formal parameter of
wrapper-challenge, below, is no longer named clause but is called
cl instead. But the ``call'' of wrapper-challenge in the
replacements is on clause. This may seem to violate the rule that a
function definition cannot use variables other than the formals.
But the occurrences of clause below are not variables but constants
in an object that will eventually be treated as hint term.
:ubt wrapper-challenge
(defun wrapper-challenge (cl parity)
(if parity
`(:computed-hint-replacement ((wrapper-challenge clause nil))
:use (:instance wrapper-axiom (x ,(car cl))))
`(:computed-hint-replacement ((wrapper-challenge clause t))
:expand ((atom zzz)))))
(thm (equal u v)
:hints ((wrapper-challenge clause t)))
This time, things go as you might have expected! Goal' is produced
and simplified, to
Goal''
(implies (wrapper nil)
(equal u v)).
Simplification gets a chance because when the new hint
(wrapper-challenge clause nil) is fired it does not change the
goal. But it does change the parity in the hints argument so that
before Goal'' is simplified again, the hint fires and adds the
hypothesis:
Goal'''
(IMPLIES (AND (WRAPPER (NOT (WRAPPER NIL)))
(WRAPPER NIL))
(EQUAL U V)).
This simplifies, replacing the first (NOT (WRAPPER NIL)) by NIL,
since (WRAPPER NIL) is known to be true here. Thus the goal
simplifies to
Goal'4'
(IMPLIES (WRAPPER NIL) (EQUAL U V)).
The process repeats indefinitely.
So we succeeded in getting a hint to fire indefinitely but allow a
full simplification between rounds.")
(USING-COMPUTED-HINTS-7
(USING-COMPUTED-HINTS)
"Using the stable-under-simplificationp flag
A problem with the example in [using-computed-hints-6] is that
exactly one simplification occurs between each (effective) firing
of the hint. Much more commonly we wish to fire a hint once a
subgoal has become stable under simplification.
A classic example of this is when we are dealing with an interpreter
for some state machine. We typically do not want the ``step''
function to open up on the symbolic representation of a state until
that state has been maximally simplified. We will illustrate with a
simple state machine.
Let us start by defining the step function, stp, and the
corresponding run function that applies it a given number of times.
(defun stp (s)
(+ 1 s))
(defun run (s n)
(if (zp n)
s
(run (stp s) (- n 1))))
The step function here is trivial: a state is just a number and the
step function increments it. In this example we will not be
interested in the theorems we prove but in how we prove them. The
formula we will focus on is
(thm (equal (run s 7) xxx))
This is not a theorem, of course. But we want to test our advice on
non-theorems because we do not want the advice to work only for
proofs that succeed. (In the past, we gave advice about using
computed hints and that advice caused the theorem prover to run
forever when given formulas that it couldn't prove -- but most of
the time the system is presented with formulas it cannot prove!)
Furthermore, without some kind of additional rules, the (run s 7)
expression in the conjecture above will not expand at all, because
ACL2's heuristics do not approve.
In fact, we do not want to take chances that run will be expanded --
we want to control its expansion completely. Therefore, disable
run.
(in-theory (disable run))
Now, what do we want? (That is always a good question to ask!) We
want (run s 7) to expand ``slowly.'' In particular, we want it to
expand once, to (run (stp s) 6). Then we want the stp to be
expanded and fully simplified before the run expression is expanded
again. That is, we want to force the expansion of run whenever the
goal is stable under simplification. This is sometimes called
``staged simplification.''
We can achieve staged simplification for any given function symbol by
defining the functions shown below and then using a simple computed
hint:
(thm (equal (run s 7) xxx)
:hints ((stage run)))
By inspecting how stage is defined you can see how to extend it, but
we explain as we go. To experiment, you can just paste the
definitions (and defmacro) below into your ACL2 shell and then try
the thm command.
First, define this pair of mutually recursive functions.
Find-first-call finds the first call of the function symbol fn in a
given term.
(mutual-recursion
(defun find-first-call (fn term)
; Find the first call of fn in term.
(cond ((variablep term) nil)
((fquotep term) nil)
((equal (ffn-symb term) fn)
term)
(t (find-first-call-lst fn (fargs term)))))
(defun find-first-call-lst (fn lst)
; Find the first call of fn in a list of terms.
(cond ((endp lst) nil)
(t (or (find-first-call fn (car lst))
(find-first-call-lst fn (cdr lst)))))))
We will arrange for the computed hint to generate an :EXPAND hint for
the first call of fn, whenever the goal becomes stable under
simplification. If no call is found, the hint will do nothing. To
make sure the hint will not loop indefinitely (for example, by
forcing fn to expand only to have the rewriter ``fold'' it back up
again), we will provide the hint with a bound that stops it after
some number of iterations. Here is the basic function that creates
the expand hint and replaces itself to count down.
(defun stage1 (fn max clause flg)
; If the clause is stable under simplification and there is a call of
; fn in it, expand it. But don't do it more than max times.
(let ((temp (and flg
(find-first-call-lst fn clause))))
(if temp
(if (zp max)
(cw \"~%~%HINT PROBLEM: The maximum repetition count of ~
your STAGE hint been reached without eliminating ~
all of the calls of ~x0. You could supply a larger ~
count with the optional second argument to STAGE ~
(which defaults to 100). But think about what is ~
happening! Is each stage permanently eliminating a ~
call of ~x0?~%~%\"
fn)
`(:computed-hint-replacement
((stage1 ',fn ,(- max 1)
clause
stable-under-simplificationp))
:expand (,temp)))
nil)))
Suppose that when stage1 is called, fn is the function we want to
expand, max is the maximum number of iterations of this expansion,
clause is the current goal clause, and flg is the value of the
stable-under-simplificationp flag. Then if clause is stable and we
can find a call of fn in it, we ask whether max is exhausted. If
so, we print an ``error message'' to the comment window with [cw]
and return nil (the value of cw). That nil means the hint does
nothing. But if max is not yet exhausted, we return a new hint. As
you can see above, the hint replaces itself with another stage1
hint with the same fn and a decremented max to be applied to the
new clause and the then-current value of
stable-under-simplificationp. The hint also contains an :expand
directive for the call of fn found.
Thus, if the computed hint was:
(stage1 'run 5 clause stable-under-simplificationp)
and (run s 7) occurs in the clause, then it will generate
(:computed-hint-replacement
((stage1 'run 4 clause stable-under-simplificationp))
:expand ((run s 7)))
which will in turn replace the old stage1 hint with the new one and
will apply :expand ((run s 7)) to the current goal.
We can make this more convenient by defining the macro:
(defmacro stage (fn &optional (max '100))
`(stage1 ',fn ,max clause stable-under-simplificationp))
Note that the macro allows us to either provide the maximum bound or
let it default to 100.
Henceforth, we can type
(thm (equal (run s 7) xxx)
:hints ((stage run)))
to stage the opening of run up to 100 times, or we can write
(thm (equal (run s 7) xxx)
:hints ((stage run 5)))
to stage it only 5 times. In the latter example, the system with
print a ``error message'' after the fifth expansion.
Note that if we executed
(set-default-hints '((stage run)))
then we could attack all theorems (involving run) with staged
simplification (up to bound 100), without typing an explicit hint.
(thm (equal (run s 7) xxx))
Using techniques similar to those above we have implemented
``priority phased simplification'' and provided it as a book. See
community book books/misc/priorities.lisp. This is an idea
suggested by Pete Manolios, by which priorities may be assigned to
rules and then the simplifier simplifies each subgoal maximally
under the rules of a given priority before enabling the rules of
the next priority level. The book above documents both how we
implement it with computed hints and how to use it.
Here is another example of using the stable-under-simplificationp
flag to delay certain actions. It defines a default hint, see
[default-hints], which will enable [non-linear-arithmetic] on
precisely those goals which are stable-under-simplificationp. It
also uses the HISTORY and PSPV variables to determine when toggling
[non-linear-arithmetic] is appropriate. These variables are
documented only in the source code. If you start using these
variables extensively, please contact the developers of ACL2 or
Robert Krug (rkrug@cs.utexas.edu) and let us know how we can help.
(defun nonlinearp-default-hint (stable-under-simplificationp hist pspv)
(cond (stable-under-simplificationp
(if (not (access rewrite-constant
(access prove-spec-var pspv :rewrite-constant)
:nonlinearp))
'(:computed-hint-replacement t
:nonlinearp t)
nil))
((access rewrite-constant
(access prove-spec-var pspv :rewrite-constant)
:nonlinearp)
(if (not (equal (caar hist) 'SETTLED-DOWN-CLAUSE))
'(:computed-hint-replacement t
:nonlinearp nil)
nil))
(t
nil)))")
(USING-COMPUTED-HINTS-8
(USING-COMPUTED-HINTS)
"Some Final Comments
None of the examples show the use of the variable WORLD, which is
allowed in computed hints. There are some (undocumented) ACL2
utilities that might be useful in programming hints, but these
utilities need access to the ACL2 logical world (see [world]).
A very useful fact to know is that (table-alist name world) returns
an alist representation of the current value of the [table] named
name.
The ACL2 source code is littered with :[program] mode functions for
manipulating world. In our source code, the world is usually bound
a variable named wrld; so searching our code for that name might be
helpful.
Using these utilities to look at the WORLD one can, for example,
determine whether a symbol is defined recursively or not, get the
body and formals of a defined function, or fetch the statement of a
given lemma. Because these utilities are not yet documented, we do
not expect users to employ WORLD in computed hints. But experts
might and it might lead to the formulation of a more convenient
language for computed hints.
None of our examples illustrated the 7 argument form of a computed
hint, (fn ID CLAUSE WORLD STABLE-UNDER-SIMPLIFICATIONP HIST PSPV
CTX). When used, the variables HIST, PSPV, and CTX, are bound to
the clause history, the package of ``special variables'' governing
the clause, and the ``error message context.'' These variables are
commonly used throughout our source code but are, unfortunately,
undocumented. Again, we expect a few experts will find them useful
in developing computed hints.
If you start using computed hints extensively, please contact the
developers of ACL2 and let us know what you are doing with them and
how we can help.")
(USING-ENABLED-RULES
(THEORIES)
"Avoiding :use [hints] for [enable]d :[rewrite] rules
Consider the following (admittedly silly) example.
(thm (equal (append (append x y) z) (append x y z))
:hints ((\"Subgoal *1/1\" :use cdr-cons)))
ACL2's output includes the following warning.
ACL2 Warning [Use] in ( THM ...): It is unusual to :USE an enabled
:REWRITE or :DEFINITION rule, so you may want to consider disabling
(:REWRITE CDR-CONS) in the hint provided for Subgoal *1/1.
The warning is saying that if you leave the rewrite rule enabled,
ACL2 may simplify away the hypothesis added by the :use hint. We
now explain this danger in more detail and show how disabling the
rule can solve this problem.
Recall (see [hints]) how :use [hints] work. Such a hint specifies a
formula, F, which is based on an existing lemma. Then the indicated
goal, G, is replaced by the implication (implies F G). The
intention is that the truth of F will help in the simplification of
G to T (true). The ``[Use]'' warning shown above is telling us of
the danger that F may be rewritten to T, reducing the implication
above to (implies T G) --- thus, sadly, F has disappeared and is
not available to help with the simplification of G.
Consider the following tiny example.
(defun p (x) (cons x x))
(defthm car-p
(equal (car (p x)) x))
(in-theory (disable p (:type-prescription p)))
(thm (implies (equal (p x1) (p x2))
(equal x1 x2))
:hints ((\"Goal\"
:use ((:instance car-p (x x1))
(:instance car-p (x x2))))))
The proof of the final [thm] form fails, because the new hypotheses
are rewritten to t using the :[rewrite] rule CAR-P, in the manner
described above. The following proof log shows the new hypotheses
and their disappearance via rewriting.
We augment the goal with the hypotheses provided by the :USE hint.
These hypotheses can be derived from CAR-P via instantiation. We are
left with the following subgoal.
Goal'
(IMPLIES (AND (EQUAL (CAR (P X1)) X1)
(EQUAL (CAR (P X2)) X2))
(IMPLIES (EQUAL (P X1) (P X2))
(EQUAL X1 X2))).
By the simple :rewrite rule CAR-P we reduce the conjecture to
Goal''
(IMPLIES (EQUAL (P X1) (P X2))
(EQUAL X1 X2)).
When we disable the rule CAR-P as follows, the proof succeeds.
(thm (implies (equal (p x1) (p x2))
(equal x1 x2))
:hints ((\"Goal\"
:use ((:instance car-p (x x1))
(:instance car-p (x x2)))
:in-theory (disable car-p))))
In general, then, a solution is to disable the rewrite rule that you
are supplying in a :use hint.")
(USING-TABLES-EFFICIENTLY
(TABLE)
"Notes on how to use tables efficiently
(Thanks to Jared Davis for contributing this [documentation] topic,
to which we have made only minor modifications.)
Suppose your book contains [table] [events], or macros that expand
into table events, of the following form:
(table my-table 'my-field <computation>)
Then <computation> will be evaluated twice during [certify-book] and
again every time you include the book with [include-book]. In some
cases this overhead can be avoided using [make-event].
See also [defconsts] for an analogous trick involving [defconst].
As an example, suppose we want to store numbers in a table only if
they satisfy some computationally expensive predicate. We'll
introduce a new book, number-table.lisp, and create a table to
store these numbers:
(table number-table 'data nil)
Instead of implementing a ``computationally expensive predicate,''
we'll write a function that just prints a message when it is called
and accepts even numbers:
(defun expensive-computation (n)
(prog2$ (cw \"Expensive computation on ~x0.~%\" n)
(evenp n)))
Now we'll implement a macro, add-number, which will add its argument
to the table only if it satisfies the expensive predicate:
(defmacro add-number (n)
`(table number-table 'data
(let ((current-data
(cdr (assoc-eq 'data (table-alist 'number-table world)))))
(if (expensive-computation ,n)
(cons ,n current-data)
current-data))))
Finally, we'll call add-number a few times to finish the book.
(add-number 1)
(add-number 2)
(add-number 3)
When we now invoke (certify-book \"number-table\"), we see the
expensive predicate being called twice for each number: once in
Step 2, the main pass, then again in Step 3, the admissibility
check. Worse, the computation is performed again for each number
when we use [include-book] to load number-table, e.g.,
ACL2 !>(include-book \"number-table\")
Expensive computation on 1.
Expensive computation on 2.
Expensive computation on 3.
To avoid these repeated executions, we can pull the test out of the
table event using [make-event]. Here's an alternate implementation
of add-number that won't repeat the computation:
(defmacro add-number (n)
`(make-event
(if (expensive-computation ,n)
'(table number-table 'data
(cons ,n (cdr (assoc 'data
(table-alist 'number-table world)))))
'(value-triple :expensive-computation-failed))))
When we recertify number-table.lisp, we'll see the expensive
computation is still called once for each number in Step 2, but is
no longer called during Step 3. Similarly, the [include-book] no
longer shows any calls of the expensive computation.")
(USING_THE_ASSOCIATIVITY_OF_APP_TO_PROVE_A_TRIVIAL_CONSEQUENCE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"Using the Associativity of App to Prove a Trivial Consequence
[{IMAGE}]
If we have proved the associativity-of-app rule, then the following
theorem is trivial:
(defthm trivial-consequence
(equal (app (app (app (app x1 x2) (app x3 x4)) (app x5 x6)) x7)
(app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7))))))
Below we show the proof
[{IMAGE}]")
(VALUE-TRIPLE
(EVENTS ACL2-BUILT-INS)
"Compute a value, optionally checking that it is not nil
Examples:
(value-triple (+ 3 4))
(value-triple (cw \"hi\") :on-skip-proofs t)
(value-triple (@ ld-pre-eval-print))
(value-triple (@ ld-pre-eval-print) :check t)
General Form:
(value-triple form
:on-skip-proofs sp ; optional; nil by default
:check chk ; optional; nil by default
)
Value-triple provides a convenient way to evaluate a form in an event
context, including [progn] and [encapsulate] and in [books]; see
[events]. The form should evaluate to a single, non-[stobj] value.
Calls of value-triple are generally skipped when proofs are being
skipped, in particular when ACL2 is performing the second pass
through the [events] of an [encapsulate] form or during an
[include-book], or indeed any time [ld-skip-proofsp] is non-nil. If
you want the call evaluated during those times as well, use a
non-nil value for :on-skip-proofs. Note that the argument to
:on-skip-proofs is not evaluated.
If you expect the form to evaluate to a non-nil value and you want an
error to occur when that is not the case, you can use :check t.
More generally, the argument of :check can be a form that evaluates
to a single, non-[stobj] value. If this value is not nil, then the
aforementioned test is made (that the given form is not nil). If an
error occurs and the value of :check is a string or indeed any
``message'' suitable for printing by [fmt] when supplied as a value
for tilde-directive ~@, then that string or message is printed.")
(VERBOSE-PSTACK
(PSTACK)
"Seeing what the prover is up to (for system hackers)
NOTE: This utility is a low-level debugging utility, which may not be
useful except to those familiar with ACL2 source code.
General Forms:
(verbose-pstack t) ; get trace-like information on prover during proofs
(verbose-pstack '(fn1 fn2 ...))
; as above, but omit calls of the indicated functions
(verbose-pstack nil) ; turn off trace-like information on prover
For example, (verbose-pstack '(ev-fncall)) will provide a trace of
various prover functions during proofs, except for the function
ev-fncall.
By evaluating (verbose-pstack t) one can get trace-like information
during subsequent proofs about prover functions, including time
summaries, printed to the screen during a proof. To turn off this
feature, evaluate (verbose-pstack nil). Also see [pstack].")
(VERIFY
(PROOF-CHECKER)
"Enter the interactive proof checker
For proof-checker command summaries, see [proof-checker].
Examples:
(VERIFY (implies (and (true-listp x) (true-listp y))
(equal (append (append x y) z)
(append x (append y z)))))
-- Attempt to prove the given term interactively.
(VERIFY (p x)
:event-name p-always-holds
:rule-classes (:rewrite :generalize)
:instructions ((rewrite p-always-holds-lemma)
change-goal))
-- Attempt to prove (p x), where the intention is to call the
resulting DEFTHM event by the name p-always-holds, with
rule-classes as indicated. The two indicated instructions
will be run immediately to start the proof.
(VERIFY)
-- Re-enter the proof-checker in the state at which is was last
left.
General Form:
(VERIFY &OPTIONAL raw-term
&KEY
event-name
rule-classes
instructions)
Verify is the function used for entering the [proof-checker]'s
interactive loop.")
(VERIFY-GUARDS
(EVENTS GUARD)
"Verify the [guard]s of a function
See [guard] for a general discussion of guards.
Before discussing the verify-guards event, we first discuss guard
verification, which can take place at definition time or, later,
using verify-guards. Typically, guard verification takes place at
definition time if a guard (or type, or [stobjs]) has been supplied
explicitly unless :verify-guards nil has been specified; see
[defun] and see [xargs], and see [set-verify-guards-eagerness] for
how to change this default. The point of guard verification is to
ensure that during evaluation of an expression without free
variables, no guard violation takes place.
Technical note: the first argument of verify-guards must be a
function symbol or the name of a [defthm] or [defaxiom] event, not
a macro-alias for a function symbol (see [macro-aliases-table]).
See [verify-guards+] for a utility that does not have this
restriction.
Guard verification is intended to guarantee that for any call of a
given function, if its [guard] holds for that call then the [guard]
will hold for every function call in the body of that function.
Moreover, in order to avoid guard violations during evaluation of
the function's guard itself, guard verification also is intended to
guarantee that the guards are satisfied for all calls in the guard
itself. Consider the following simple example.
(defun f (x)
(declare (xargs :guard (and (consp x)
(integerp (car x)))))
(if (rationalp (cdr x))
(+ (car x) (cdr x))
17))
If you evaluate (f t), for example, in the top-level loop, you will
(by default) get a guard error. The point of guard verification is
to guarantee the absence of guard errors, and we start by using
this example to illustrate the proof obligations that guarantee
such absence.
The body of the above definition has the following function calls,
where the first is the entire body.
(if (rationalp (cdr x))
(< (car x) (cdr x))
17)
(rationalp (cdr x)) ; the test of the top-level IF call
(cdr x) ; from (rationalp (cdr x))
(< (car x) (cdr x)) ; the true branch of the top-level IF call
(car x) ; from (< (car x) (cdr x))
(cdr x) ; from (< (car x) (cdr x))
We thus see potentially six conditions to prove, one for each call.
The guards of the function symbols of those calls are t for [if]
and [rationalp], (or (consp x) (equal x nil)) for both (car x) and
(cdr x), and finally that both arguments are rationals for <.
Moreover, we can take advantage of ``contextual assumptions'': the
if-test conditions and the top-level :guard. Thus, for
verify-guards the proof obligation from the body of f is as
follows.
(implies
(and (consp x) (integerp (car x))) ; from the :guard
(and t ; from the top-level IF call
t ; from (rationalp (cdr x))
(or (consp x) (equal x nil)) ; from the first (cdr x)
(implies
(rationalp (cdr x)) ; IF-test for calls in the true branch
(and (or (consp x) (equal x nil)) ; from (car x)
(or (consp x) (equal x nil)) ; from the second (cdr x)
(and (rationalp (car x)) (rationalp (cdr x))) ; from the < call
))))
But the :guard itself generates a similar sort of proof obligation.
Note that the guard (and (consp x) (integerp (car x))) is really an
abbreviation (i.e. via the macro [and]) for the term (if (consp x)
(integerp (car x)) nil). The guard proof obligation for the guard
itself is thus as follows.
(and t ; from (consp x)
(implies (consp x)
(and t ; from (integerp (car x)) ;
(consp x) ; from (car x) ;
)))
All of the above proof obligations are indeed theorems, and guard
verification succeeds for the above definition of f.
The example above illustrates the general procedure for generating
the guard proof obligation. Each function call is considered in the
body or guard of the function, and it is required that the guard is
met for that call, under certain ``contextual assumptions'', which
are as follows. In the case of the body of the named function, it
is assumed that the guard holds for that function on its formal
parameters. And in both cases --- the body of the named function
and also its guard --- the governing tests from superior calls of
[if] are also assumed.
As mentioned above, if the guard on a function is not t, then guard
verification requires not only consideration of the body under the
assumption that the guard is true, but also consideration of the
guard itself. Thus, for example, guard verification fails in the
following example, even though there are no proof obligations
arising from the body, because the guard itself can cause a guard
violation when evaluated for an arbitrary value of x:
(defun foo (x)
(declare (xargs :guard (car x)))
x)
We turn now to the verify-guards event as a way of verifying the
[guard]s for a function or theorem.
Examples:
(verify-guards flatten)
(verify-guards flatten
:hints ((\"Goal\" :use (:instance assoc-of-app)))
:guard-debug t ; default = nil
:otf-flg t)
General Form:
(verify-guards name
:hints hints
:guard-debug t ; typically t, but any value is legal
:otf-flg otf-flg)
In the General Form above, name is the name of a :[logic] function
(see [defun-mode]) or of a theorem or axiom. In the most common
case name is the name of a function that has not yet had its
[guard]s verified, each subroutine of which has had its [guard]s
verified. The values [hints], [otf-flg], and [guard-debug] are as
described in the corresponding [documentation] entries. The keyword
arguments above are all optional. To admit this event, the
conjunction of the guard proof obligations must be proved. If that
proof is successful, name is considered to have had its [guard]s
verified.
See [verify-guards-formula] for a utility that lets you view the
formula to be proved by verify-guards, but without creating an
event.
If name is one of several functions in a mutually recursive clique,
verify-guards will attempt to verify the [guard]s of all of the
functions.
If name is a theorem or axiom name, verify-guards verifies the guards
of the associated formula. When a theorem has had its guards
verified then you know that the theorem will evaluate to non-nil in
all Common Lisps, without causing a runtime error (other than
possibly a resource error). In particular, you know that the
theorem's validity does not depend upon ACL2's arbitrary completion
of the domains of partial Common Lisp functions.
For example, if app is defined as
(defun app (x y)
(declare (xargs :guard (true-listp x)))
(if (endp x)
y
(cons (car x) (app (cdr x) y))))
then we can verify the guards of app and we can prove the theorem:
(defthm assoc-of-app
(equal (app (app a b) c) (app a (app b c))))
However, if you go into almost any Common Lisp in which app is
defined as shown and evaluate
(equal (app (app 1 2) 3) (app 1 (app 2 3)))
we get an error or, perhaps, something worse like nil! How can this
happen since the formula is an instance of a theorem? It is
supposed to be true!
It happens because the theorem exploits the fact that ACL2 has
completed the domains of the partially defined Common Lisp
functions like [car] and [cdr], defining them to be nil on all
non-conses. The formula above violates the guards on app. It is
therefore ``unreasonable'' to expect it to be valid in Common Lisp.
But the following formula is valid in Common Lisp:
(if (and (true-listp a)
(true-listp b))
(equal (app (app a b) c) (app a (app b c)))
t)
That is, no matter what the values of a, b and c the formula above
evaluates to t in all Common Lisps (unless the Lisp engine runs out
of memory or stack computing it). Furthermore the above formula is
a theorem:
(defthm guarded-assoc-of-app
(if (and (true-listp a)
(true-listp b))
(equal (app (app a b) c) (app a (app b c)))
t))
This formula, guarded-assoc-of-app, is very easy to prove from
assoc-of-app. So why prove it? The interesting thing about
guarded-assoc-of-app is that we can verify the guards of the
formula. That is, (verify-guards guarded-assoc-of-app) succeeds.
Note that it has to prove that if a and b are true lists then so is
(app a b) to establish that the guard on the outermost app on the
left is satisfied. By verifying the guards of the theorem we know
it will evaluate to true in all Common Lisps. Put another way, we
know that the validity of the formula does not depend on ACL2's
completion of the partial functions or that the formula is
``well-typed.''
One last complication: The careful reader might have thought we could
state guarded-assoc-of-app as
(implies (and (true-listp a)
(true-listp b))
(equal (app (app a b) c)
(app a (app b c))))
rather than using the if form of the theorem. We cannot! The reason
is technical: [implies] is defined as a function in ACL2. When it
is called, both arguments are evaluated and then the obvious truth
table is checked. That is, implies is not ``lazy.'' Hence, when we
write the guarded theorem in the implies form we have to prove the
guards on the conclusion without knowing that the hypothesis is
true. It would have been better had we defined implies as a macro
that expanded to the if form, making it lazy. But we did not and
after we introduced guards we did not want to make such a basic
change.
Recall however that verify-guards is almost always used to verify the
guards on a function definition rather than a theorem. We now
return to that discussion.
Verify-guards must often be used when the value of a recursive call
of a defined function is given as an argument to a subroutine that
is [guard]ed. An example of such a situation is given below.
Suppose app (read ``append'') has a [guard] requiring its first
argument to be a [true-listp]. Consider
(defun rev (x)
(declare (xargs :guard (true-listp x)))
(cond ((endp x) nil)
(t (app (rev (cdr x)) (list (car x))))))
Observe that the value of a recursive call of rev is being passed
into a [guard]ed subroutine, app. In order to verify the [guard]s
of this definition we must show that (rev (cdr x)) produces a
[true-listp], since that is what the [guard] of app requires. How
do we know that (rev (cdr x)) is a [true-listp]? The most elegant
argument is a two-step one, appealing to the following two lemmas:
(1) When x is a [true-listp], (cdr x) is a [true-listp]. (2) When z
is a [true-listp], (rev z) is a [true-listp]. But the second lemma
is a generalized property of rev, the function we are defining.
This property could not be stated before rev is defined and so is
not known to the theorem prover when rev is defined.
Therefore, we might break the admission of rev into three steps:
define rev without addressing its [guard] verification, prove some
general properties about rev, and then verify the [guard]s. This
can be done as follows:
(defun rev (x)
(declare (xargs :guard (true-listp x)
:verify-guards nil)) ; Note this additional xarg.
(cond ((endp x) nil)
(t (app (rev (cdr x)) (list (car x))))))
(defthm true-listp-rev
(implies (true-listp x2)
(true-listp (rev x2))))
(verify-guards rev)
The ACL2 system can actually admit the original definition of rev,
verifying the [guard]s as part of the [defun] event. The reason is
that, in this particular case, the system's heuristics just happen
to hit upon the lemma true-listp-rev. But in many more complicated
functions it is necessary for the user to formulate the inductively
provable properties before [guard] verification is attempted.
Remark on computation of guard conjectures and evaluation. When ACL2
computes the [guard] conjecture for the body of a function, it
evaluates any ground subexpressions (those with no free variables),
for calls of functions whose :[executable-counterpart] [rune]s are
[enable]d. Note that here, ``enabled'' refers to the current global
[theory], not to any :[hints] given to the guard verification
process; after all, the guard conjecture is computed even before
its initial goal is produced. Also note that this evaluation is
done in an environment as though :set-guard-checking :all had been
executed, so that we can trust that this evaluation takes place
without guard violations; see [set-guard-checking].
If you want to verify the [guard]s on functions that are built into
ACL2, you will first need to put them into :[logic] mode. See
[verify-termination], specifically the ``Remark on system
functions'' in that [documentation].")
(VERIFY-GUARDS+
(EVENTS)
"Verify the [guard]s of a function
We assume familiarity with [guard] verification; see [verify-guards].
Unlike verify-guards, the macro call (verify-guards+ mac ...) will
verify guards for a function, fn, such that the macro mac is
associated with the function symbol fn in [macro-aliases-table]
(also see [add-macro-alias]). For example, if you define a macro
app and list append function binary-app, and you associate macro
app with function symbol binary-app in [macro-aliases-table], then
evaluation of the form (verify-guards+ app) will have the effect of
evaluating (verify-guards fn). Note that in this setting,
evaluation of (verify-guards app) would cause an error, because app
is a macro and verify-guards, unlike verify-guards+, cannot handle
macros.
The rest of this [documentation] topic discusses why we do not simply
arrange that verify-guards be permitted to take a macro alias. The
following example shows a soundness issue in doing so.
(encapsulate
()
(defun f1 (x)
(declare (xargs :guard (consp x)
:verify-guards nil))
(car x))
(defun f2 (x)
(declare (xargs :guard t
:verify-guards nil))
(cdr x))
(defmacro mac (x)
x)
(add-macro-alias mac f2) ; silly macro alias ;
(local (add-macro-alias mac f1)) ; alternate silly macro alias ;
(verify-guards mac))
If we were to allow macro aliases in [verify-guards], this event
would be admitted, because on the first pass we are verifying
guards of f1. But after the [encapsulate] form completes
evaluation, it would appear that f2 is guard-verified. That could
of course cause a raw Lisp error.
The enhanced functionality provided by verify-guards+ does not have
the above problem, because it takes advantage of [make-event] to
avoid taking advantage of the contradictory results produced by the
two calls of add-macro-alias. See [make-event]. If the specific
example above is modified by replacing verify-guards with
verify-guards+, then the first pass through the [encapsulate] form
will expand the form (verify-guards+ mac) to (verify-guards f1).
That same expansion will be used for the verify-guards+ call during
the second pass through the encapsulate form, which is evaluated
successfully and leaves us in a [world] where f1 is guard-verified
and f2 is not.")
(VERIFY-GUARDS-EAGERNESS (POINTERS)
"See [set-verify-guards-eagerness].")
(VERIFY-GUARDS-FORMULA
(GUARD)
"View the guard proof obligation, without proving it
See [verify-guards] and see [guard] for a discussion of guards. This
utility is provided for viewing a guard proof obligation, without
doing a proof.
Example Forms:
(verify-guards-formula foo)
(verify-guards-formula foo :guard-debug t)
(verify-guards-formula foo :otf-flg dont-care :xyz whatever)
(verify-guards-formula (+ (foo x) (bar y)) :guard-debug t)
Verify-guards-formula allows all keywords, but only pays attention to
:guard-debug, which has the same effect as in [verify-guards] (see
[guard-debug]). Apply verify-guards-formula to a name just as you
would use [verify-guards], but when you only want to view the
formula rather than creating an event. If the first argument is not
a symbol, then it is treated as the body of a [defthm] event for
which you want the guard proof obligation.
See [guard-obligation] if you want to obtain guard proof obligations
for use in a program.")
(VERIFY-TERMINATION
(EVENTS)
"Convert a function from :program mode to :logic mode
Example:
(verify-termination fact)
General Forms:
(verify-termination fn dcl ... dcl)
(verify-termination (fn1 dcl ... dcl)
(fn2 dcl ... dcl)
...)
where fn and the fni are function symbols having :[program] mode (see
[defun-mode]) and all of the dcls are either [declare] forms or
[documentation] strings. The first form above is an abbreviation
for
(verify-termination (fn dcl ... dcl))
so we limit our discussion to the second form. Each of the fni must
be in the same clique of mutually recursively defined functions,
but not every function in the clique need be among the fni.
Verify-termination attempts to establish the admissibility of the
fni. Verify-termination retrieves their definitions, creates
modified definitions using the dcls supplied above, and resubmits
these definitions. You could avoid using verify-termination by
typing the new definitions yourself. So in that sense,
verify-termination adds no new functionality. But if you have
prototyped your system in :[program] mode and tested it, you can
use verify-termination to resubmit your definitions and change
their [defun-mode]s to :[logic], addings [hints] without having to
retype or recopy the code.
The [defun] [command] executed by verify-termination is obtained by
retrieving the [defun] (or [mutual-recursion]) [command] that
introduced the clique in question and then possibly modifying each
definition as follows. Consider a function, fn, in the clique. If
fn is not among the fni above, its definition is left unmodified
other than to add (declare (xargs :mode :logic)). Otherwise, fn is
some fni and we modify its definition by inserting into it the
corresponding dcls listed with fni in the arguments to
verify-termination, as well as (declare (xargs :mode :logic)). In
addition, we throw out from the old declarations in fn the :mode
specification and anything that is specified in the new dcls.
For example, suppose that fact was introduced with:
(defun fact (n)
(declare (type integer n)
(xargs :mode :program))
(if (zp n) 1 (* n (fact (1- n))))).
Suppose later we do (verify-termination fact). Then the following
definition is submitted.
(defun fact (n)
(declare (type integer n))
(if (zp n) 1 (* n (fact (1- n))))).
Observe that this is the same definition as the original one, except
the old specification of the :mode has been deleted so that the
[defun-mode] now defaults to :[logic]. Although the termination
proof succeeds, ACL2 also tries to verify the [guard], because we
have (implicitly) provided a [guard], namely (integerp n), for this
function. (See [guard] for a general discussion of guards, and see
[type-spec] for a discussion of how type declarations are used in
guards.) Unfortunately, the [guard] verification fails, because the
subterm (zp n) requires that n be nonnegative, as can be seen by
invoking :args zp. (For a discussion of termination issues relating
to recursion on the naturals, see [zero-test-idioms].) So we might
be tempted to submit the following:
(verify-termination
fact
(declare (xargs :guard (and (integerp n) (<= 0 n))))).
However, this is considered a changing of the guard (from (integerp
n)), which is illegal. If we instead change the guard in the
earlier defun after undoing that earlier definition with :[ubt]
fact, then (verify-termination fact) will succeed.
Remark on system functions. There may be times when you want to apply
verify-termination (and also, perhaps, [verify-guards]) to
functions that are predefined in ACL2. It may be necessary in such
cases to modify the system code first. See Part II of the {open
architecture page for ACL2 |
http://www.cs.utexas.edu/users/moore/acl2/open-architecture/} for a
discussion of the process for contributing updates to the system
code and [books] with such verify-termination or [verify-guards]
[events], perhaps resulting in more system functions being built-in
as [guard]-verified. To see which built-in functions have already
received such treatment, see community books directory
books/system/; or, evaluate the constant
*system-verify-guards-alist*, each of whose entries associates the
name of a community book with a list of functions whose
guard-verification is proved by including that book. See the above
URL for more details.
Note that if fn1 is already in :[logic] mode, then the
verify-termination call has no effect. It is generally considered
to be redundant, in the sense that it returns without error; but if
the fn1 is a constrained function (i.e., introduced in the
signature of an [encapsulate], or by [defchoose]), then an error
occurs. This error is intended to highlight unintended uses of
verify-termination; but if you do not want to see an error in this
case, you can write and use your own macro in place of
verify-termination. The following explanation of the implementation
of verify-termination may help with such a task.
We conclude with a discussion of the use of [make-event] to implement
verify-termination. This discussion can be skipped; we include it
only for those who want to create variants of verify-termination,
or who are interested in seeing an application of [make-event].
Consider the following proof of nil, which succeeded up through
Version_3.4 of ACL2.
(encapsulate
()
(defun foo (x y)
(declare (xargs :mode :program))
(if (or (zp x) (zp y))
(list x y)
(foo (1+ x) (1- y))))
(local (defun foo (x y)
(declare (xargs :measure (acl2-count y)))
(if (or (zp x) (zp y))
(list x y)
(foo (1+ x) (1- y)))))
(verify-termination foo))
(defthm bad-lemma
(zp x)
:hints ((\"Goal\" :induct (foo x 1)))
:rule-classes nil)
How did this work? In the first pass of the [encapsulate], the second
[defun] of foo promoted foo from :program to :logic mode, with y as
the unique measured variable. The following call to
verify-termination was then redundant. However, on the second pass
of the [encapsulate], the second ([local]) definition of foo was
skipped, and the verify-termination event then used the first
definition of foo to guess the measure, based (as with all guesses
of measures) on a purely syntactic criterion. ACL2 incorrectly
chose (acl2-count x) as the measure, installing x as the unique
measured variable, which in turn led to an unsound induction scheme
subsequently used to prove nil (lemma bad-lemma, above)
Now, verify-termination is a macro whose calls expand to [make-event]
calls. So in the first pass above, the verify-termination call
generated a defun event identical to the [local] [defun] of foo,
which was correctly identified as redundant. That expansion was
recorded, and on the second pass of the [encapsulate], the
expansion was recalled and used in place of the verify-termination
call (that is how [make-event] works). So instead of a measure
being guessed for the verify-termination call on the second pass,
the same measure was used as was used on the first pass, and a
sound induction scheme was stored. The attempt to prove nil (lemma
bad-lemma) then failed.")
(VERSION
(ABOUT-ACL2)
"ACL2 Version Number
To determine the version number of your copy of ACL2, evaluate the
form (@ acl2-version). The value will be a string. For example,
ACL2 !>(@ acl2-version)
\"ACL2 Version 3.4\"
The part of the string after \"ACL2 Version \" is of the form x.y or
x.y.z, optionally followed by a succession of values in
parentheses, where x, y, and z are natural numbers. If z is omitted
then it is implicitly 0. We refer to X, y, and z as the ``major'',
``minor'', and ``incrl'' fields, respectively. The incrl field is
used for incremental releases. The discussion just below assumes
that incremental releases are not employed at the user's site,
i.e., the incrl fields are always 0. We remove this assumption when
we discuss incremental releases at the end of this documenttation
topic.
[Books] are considered certified only in the same version of ACL2 in
which the certification was done. The [certificate] file records
the version number of the certifying ACL2 and [include-book]
considers the book uncertified if that does not match the current
version number. Thus, each time we release a new version of ACL2,
previously certified books should be recertified.
Note that there are over 150 constants in the system, most having to
do with the fact that ACL2 is coded in ACL2. Many of these, for
example *common-lisp-specials-and-constants* and *acl2-exports*,
may change from version to version, and this can cause unsoundness.
For example, the symbol 'set-difference-eq was added to
*acl2-exports* in Version_2.9, so we can certify a book in
Version_2.8 containing the following theorem, which is false in
Version_2.9.
(null (member 'set-difference-eq *acl2-exports*))
Therefore, we need to disallow inclusion of such a book in a
Version_2.9 session, which otherwise would allow us to prove nil.
Furthermore, it is possible that from one version of the system to
another we might change, say, the default values on some system
function or otherwise make ``intentional'' changes to the axioms.
It is even possible one version of the system is discovered to be
unsound and we release a new version to correct our error.
Therefore we adopted the draconian policy that books are certified by
a given version of ACL2 and ``must'' be recertified to be used in
other versions. We put ``must'' in quotes because in fact, ACL2
allows a book that was certified in one ACL2 version to be included
in a later version, using [include-book]. But ACL2 does not allow
[certify-book] to succeed when such an [include-book] is executed
on its behalf. Also, you may experience undesirable behavior if you
avoid recertification when moving to a different version. Hence we
recommend that you stick to the draconion policy of recertifying
books when updating to a new ACL2 version.
Furthermore, all bets are off if you certify a book using ACL2 built
on one host Lisp implementation and include the book using ACL2
built on a different host Lisp implementation. For example, for
most host Lisp implementations, the Lisp reader will interpret the
token 2f as a symbol; however, Common Lisp allows for the
possibility that 2f is read as a number. In such a case, one could
use the former ACL2 executable to certify a book containing the
form
(defthm my-thm
(symbolp '2f)
:rule-classes nil)
but then use the latter ACL2 executable to include the book, even
though for the latter ACL2 executable, 2f is a number, not a
symbol. Of course, one would expect a checksum error in that case;
but checksums do not provide guaranteed protection against
including uncertified books.
Incremental releases.
From time to time, so-called ``incremental releases'' of ACL2 are
made available. These releases are thoroughly tested on at least
two platforms; ``normal'' releases, on the other hand, are
thoroughly tested on many more platforms (perhaps a dozen or so)
and are accompanied by updates to the ACL2 home page. We provide
incremental releases in order to provide timely updates for ACL2
users who want them, without imposing unnecessary burdens on either
on the ACL2 implementors or on ACL2 users who prefer to update less
frequently. The implementors expect users to update their copies of
ACL2 when normal releases are made available, but not necessarily
when incremental releases are made available.
Incremental releases are accompanied by a bump in the incrl field of
the version field, while normal releases are accompanied by a bump
in the minor or (much less frequently) major field and zeroing out
of the incrl field. Note that incremental releases are full-fledged
releases.")
(WALKABOUT
(DEBUGGING)
"Explore an ACL2 cons tree
By typing (walkabout x state) for an ACL2 term x whose value is a
[cons] tree, you can walk around that tree. For example, ACL2
developers often use this utility to explore the ACL2 logical
[world].
When you issue a walkabout command, a summary of commands will be
printed before you enter an interactive loop.
Commands:
0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.
In the interactive walkabout loop, a positive integer n takes you to
the nth position, while 0 takes you up a level. The commands nx and
bk take you to the next and previous position, respectively, at the
same level. The command pp prints the current object in full, while
(pp level length) hides sub-objects below the indicated level and
past the indicated length, if non-nil; see [evisc-tuple]. The
command (pp n) abbreviates (pp n n), so in particular (pp nil) is
equivalent to pp.
Note that the commands above work in any package: nx, bk, pp, =, and
q are converted to the \"ACL2\" package if the current package is not
\"ACL2\".
The following example illustrates the commands described above.
ACL2 !>(walkabout (append '(a (b1 b2 b3)) '(c d e f)) state)
Commands:
0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.
(A (B1 B2 B3) C ...)
:2
(B1 B2 B3)
:3
B3
:0
(B1 B2 B3)
:nx
C
:nx
D
:0
(A (B1 B2 B3) C ...)
:pp
(A (B1 B2 B3) C D E F)
:(pp 4)
(A (B1 B2 B3) C D ...)
:(pp 1 4)
(A # C D ...)
:(pp nil 2)
(A (B1 B2 ...) ...)
:q
ACL2 !>
Finally we describe the commands q, =, and (= symb), where symb is a
symbol. The command q simply causes an exit from the walkabout
loop. The command = also exits, but causes the current object to be
printed in full. The command (= symb) saves an association of symb
with the current object, which can be retrieved outside the
walkabout loop using the macro walkabout=, as illustrated below.
:2
(B1 B2 B3)
:(= my-list)
(walkabout= MY-LIST) is
(B1 B2 B3)
:q
ACL2 !>(walkabout= MY-LIST)
(B1 B2 B3)
ACL2 !>
Finally, we remark that for trees that are not true-lists, walkabout
treats the dot as an object that can be ``walked about''. The
following example illustrates this point.
ACL2 !>(walkabout '(c d e . f) state)
Commands:
0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.
(C D E . F)
:3
E
:nx
.
:nx
F
:0
(C D E . F)
:4
.
:0
(C D E . F)
:5
F
:")
(WARNINGS
(PROVER-OUTPUT)
"Warnings emitted by the ACL2 proof process
The prover can emit many warnings when processing [events]. See
[set-inhibit-warnings] and see [set-inhibit-output-lst] for how to
disable and enable them.")
(WATERFALL (POINTERS)
"See [hints-and-the-waterfall].")
(WATERFALL-PARALLELISM
(PARALLEL-PROOF)
"For ACL2(p): configuring the parallel execution of the waterfall
See [set-waterfall-parallelism].")
(WATERFALL-PARALLELISM-FOR-BOOK-CERTIFICATION
(PARALLELISM)
"For ACL2(p): using waterfall parallelism during book certification
This [documentation] topic relates to the experimental extension of
ACL2 supporting parallel execution and proof; see [parallelism].
There are books whose certification can be sped up significantly by
using waterfall parallelism. (See [parallelism], including the
caveat in its \"IMPORTANT NOTE\".) One such example in the ACL2
community books is models/jvm/m5/apprentice.lisp, which is
typically excluded from regressions because of how long it takes to
certify. In order to use waterfall parallelism during certification
of a book <book-name>.lisp using `make' (see [books-certification]
and see [books-certification-classic]), we recommend creating a
file <book-name>.acl2 that includes the following forms.
#+acl2-par
(set-waterfall-parallelism t)
(certify-book <book-name> ? t) ; other arguments may be preferable
Note that there are books that will not certify when
waterfall-parallelism is enabled. See file
acl2-customization-files/README for more information, including how
to certify essentially all books using waterfall parallelism.")
(WATERFALL-PRINTING
(PARALLEL-PROOF)
"For ACL2(p): configuring the printing within the parallelized
waterfall
See [set-waterfall-printing].")
(WELL-FORMEDNESS-GUARANTEE
(RULE-CLASSES)
"Guarantee that a metafunction or clause-processor returns a
well-formed answer
A :well-formedness-guarantee is a keyword attribute available in the
:[meta] and :[clause-processor] :[rule-classes]. By default, when a
metafunction or clause processor is applied, ACL2 checks that the
output is well-formed (and does not contain certain ``forbidden''
functions; see [set-skip-meta-termp-checks]). By providing a
:well-formedness-guarantee when you store a :meta or
:clause-processor rule, you can cause ACL2 to skip these runtime
checks.
This is considered an advanced feature that requires that you prove
certain theorems; this is probably only worthwhile if your
metafunctions or clause processors produce very large terms.
Henceforth, we assume you are familiar with metafunctions and
clause processors.
This topic first exhibits a simple example of a well-formedness
guarantee for a metafunction. Then we describe the acceptable
values of the :well-formedness-guarantee keyword of both the :meta
and :clause-processor rule-classes. Next we show the forms of the
theorems you must prove to provide such guarantees. Finally, we
discuss the runtime effects of providing such guarantees.
Example
Suppose that fn is a vanilla metafunction that rewrites terms with
top function symbol TARGET, of [arity] 1. The event storing fn as a
metafunction would normally be something like this:
(defthm fn-is-correct
(implies (and (pseudo-termp x)
(alistp a))
(equal (evl x a)
(evl (fn x) a)))
:rule-classes
((:meta :trigger-fns (TARGET))))
where evl is an evaluator for all the function symbols known to fn.
Suppose that to prove this theorem, evl must be able to interpret
the symbols TARGET, CONS, and IF. While the metatheorem for fn
establishes that fn returns something with the same ``meaning''
(under evl) as its input, it does not answer the question: does fn
return a well-formed term? Given the above :rule-class, whenever
the simplifier fires the :meta rule fn-is-correct by applying fn to
a term, it checks that the value, val, is well-formed, by
evaluating (termp val (w state)).
This check can be avoided if, before you store the rule
fn-is-correct, you prove:
(defthm fn-is-well-formed
(implies (and (termp x w)
(arities-okp '((TARGET . 1)
(CONS . 2)
(IF . 3))
w))
(termp (fn x) w))
:rule-classes nil)
and then you store fn-is-correct this way:
(defthm fn-is-correct
(implies (and (pseudo-termp x)
(alistp a))
(equal (evl x a)
(evl (fn x) a)))
:rule-classes
((:meta :trigger-fns (TARGET)
:well-formedness-guarantee fn-is-well-formed)))
Acceptable Values
Now we describe the values you may provide with the
:well-founded-guarantee keyword of the :meta and the
:clause-processor rule-classes.
General Forms:
:well-formedness-guarantee thm-name1
:well-formedness-guarantee (thm-name1)
:well-formedness-guarantee (thm-name1 thm-name2)
where both thm-name1 and thm-name2 are the names of previously
proved ``well-formedness theorems'' (see the next section);
furthermore, thm-name1 must be about the metafunction or clause
processor being introduced, and thm-name2 must be about the
hypothesis metafunction (if any) associated with the metafunction.
For :meta rules, all three forms are accepted, but the last form is
required if the :meta rule involves a hypothesis metafunction. That
is, to provide a :well-formedness-guarantee for a metatheorem with
a hypothesis metafunction, you must supply both thm-name1 and
thm-name2. For :clause-processor rules, you must use the first
form.
Each well-formedness theorem provides an ``arity alist'' that
specifies the assumed arities of the function symbols known to the
metafunction or clause processor. The arities shown for the
function symbols listed in that alist must be the same as the
arities of those functions in the actual ACL2 logical [world]
current at the time the :meta or :clause-processor is stored.
Furthermore, none of the function symbols in the arity alists should
be ``forbidden'' function symbols as explained in
[set-skip-meta-termp-checks].
When the :meta or :clause-processor rule is stored, notes are made
that will prevent the function symbols on the arity alists from
becoming untouchable (and thus forbidden). See [push-untouchable].
The only way a function's arity or forbidden status can change is if
the user has engaged in redefinition or activated a trust tag to
add or remove untouchables. Thus, the restrictions above are
unimportant to most users.
Well-Formedness Theorems
Theorems must be proved to establish that metafunctions and clause
processors return well-formed results. These are called
``well-formedness theorems.'' Note: To say a theorem is a
``well-formedness theorem'' is a remark about the shape of the
formula, not its rule-class. There is no :well-formedness-theorem
rule-class and a well-formedness theorem may be stored with any
:[rule-classes] that accept the syntax of the formula or as
:rule-classes nil. Indeed, if one of your metafunctions uses
another function to produce a subterm of the metafunction's answer,
you might need to prove a well-formedness theorem for the
sub-function and make it a :rewrite rule.
Well-formedness theorems for metafunctions and clause processors are
similar but slightly different. We deal with metafunctions and
their corresponding hypothesis metafunctions (if any) first. The
shapes of the well-formedness theorems for a metafunction and
hypothesis metafunction are identical, but remember that you must
prove a well-formedness theorem for both the metafunction and the
associated hypothesis metafunction. So suppose fn is a metafunction
or a hypothesis metafunction and let (fn x ...) be a legal call on
distinct variable symbols. (Recall that extended metafunctions and
their hypothesis functions can take three arguments.) Then the
general form a well-formedness theorem for fn states that fn
returns a [termp] when given one, provided the arities of certain
function symbols are as expected:
General Form of Well-Formedness Theorem for a Metafunction:
(implies (and (termp x w)
(arities-okp '<alist> w))
(termp (fn x ...) w))
where <alist> is an alist pairing function symbols with their
assumed arities as illustrated in the opening example. Note that
the first argument of arities-okp in the theorem is a quoted
constant. You may omit or reorder the hypotheses above and you may
use different variable symbols in place of x and w, but they must
be distinct and different from the variables in the ``....''
An example of <alist> is ((TARGET . 1) (CONS . 2) (IF . 3)).
Generally, the <alist> you provide should assign arities to every
symbol known to fn, i.e., every function symbol known to the
evaluator used in your correctness theorem. If you inspect the
definition of [termp] you will see that it uses w to obtain arities
of the function symbols in x. The [arities-okp] hypothesis
restricts w to worlds where the function symbols known to fn have
the arities you expect. For example, given the (arities-okp
'<alist> w) hypothesis for the <alist> above, the theorem prover
will rewrite (arity 'IF w) to 3. By default [arity] and
[arities-okp] are disabled and a rewrite rule that is part of
ACL2's initial world will take care of calls like (arity 'IF w).
Now we turn to the well-formedness theorem for a clause processor,
cl-proc. Let (cl-proc x ...) be a legal call on distinct variable
symbols. The theorem establishes that cl-proc returns a list of
clauses when given a clause, provided certain functions have the
expected arities. But the recognizer for a clause is the function
[term-listp] and the recognizer for a list of clauses is
[term-list-listp]:
General Forms of Well-Formedness Theorem for a Clause Processor
(implies (and (term-listp x w)
(arities-okp '<alist> w))
(term-list-listp (cl-proc x ...) w))
(implies (and (term-listp x w)
(arities-okp '<alist> w))
(term-list-listp (clauses-result (cl-proc x ...)) w))
The first form above is for a cl-proc that returns a single value
and the second form is for a cl-proc that returns multiple values.
The discussion about metafunctions, above, applies here as well.
<Alist> is an alist pairing function symbols with their assumed
arities. You may omit or reorder the hypotheses and you may use
different variable symbols in place of x and w, but they must be
distinct and different from the variables in the ``....''
Runtime Effects
In the absence of a :well-formedness-guarantee, if a metafunction or
clause processor is applied during a proof and produces val, then
certain checks are made on val before it is used in the proof
attempt. In the case of a metafunction, (termp val (w state)) is
checked and val is scanned to ensure that it contains no forbidden
function symbols. In the case of a clause processor,
(term-list-listp val (w state)) is checked and val is scanned to
ensure that it contains no forbidden function symbols.
If val is large (e.g., because the input is large), these checks can
take more time than the metafunction or clause processor did to
produce val! It is for this reason that we provide for
:well-formedness-guarantees.
When a :well-formedness-guarantee is provided no checks are made on
val. However, ACL2 will check that the arity alist(s) involved in
the guarantee still correctly shows the arities of the function
symbols listed. Because those function symbols were not forbidden
when the guarantee was made and are prohibited from being forbidden
thereafter, no check is necessary to ensure that no forbidden
symbols are introduced into the proof.")
(WELL-FOUNDED-RELATION
(RULE-CLASSES)
"Show that a relation is well-founded on a set
See [rule-classes] for a general discussion of rule classes,
including how they are used to build rules from formulas and a
discussion of the various keywords in a rule class description.
Example:
(defthm lex2p-is-well-founded-relation
(and (implies (pairp x) (o-p (ordinate x)))
(implies (and (pairp x)
(pairp y)
(lex2p x y))
(o< (ordinate x) (ordinate y))))
:rule-classes :well-founded-relation)
The example above creates a :well-founded-relation rule, where of
course the functions pairp, lex2p, and ordinate would have to be
defined first. It establishes that lex2p is a well-founded relation
on pairps. We explain and give details below.
Exactly two general forms are recognized:
General Forms
(AND (IMPLIES (mp x) (O-P (fn x))) ; Property 1
(IMPLIES (AND (mp x) ; Property 2
(mp y)
(rel x y))
(O< (fn x) (fn y)))),
or
(AND (O-P (fn x)) ; Property 1
(IMPLIES (rel x y) ; Property 2
(O< (fn x) (fn y))))
where mp, fn, and rel are function symbols, x and y are distinct
variable symbols, and no other :well-founded-relation theorem about
fn has been proved. When the second general form is used, we act as
though the first form were used with mp being the function that
ignores its argument and returns t. The discussion below therefore
considers only the first general form.
Note: We are very rigid when checking that the submitted formula is
of one of these forms. For example, in the first form, we insist
that all the conjuncts appear in the order shown above. Thus,
interchanging the two properties in the top-level conjunct or
rearranging the hyptheses in the second conjunct both produce
unrecognized forms. The requirement that each fn be proved
well-founded at most once ensures that for each well-founded
relation, fn, there is a unique mp that recognizes the domain on
which rel is well-founded. We impose this requirement simply so
that rel can be used as a short-hand when specifying the
well-founded relations to be used in definitions; otherwise the
specification would have to indicate which mp was to be used.
We also insist that the new ordering be embedded into the ordinals as
handled by [o-p] and [o<] and not some into previously admitted
user-defined well-founded set and relation. This restriction should
pose no hardship. If mp and rel were previously shown to be
well-founded via the embedding fn, and you know how to embed some
new set and relation into mp and rel, then by composing fn with
your new embedding and using the previously proved well-founded
relation lemma you can embed the new set and relation into the
ordinals.
Mp is a predicate that recognizes the objects that are supposedly
ordered in a well-founded way by rel. We call such an object an
``mp-measure'' or simply a ``measure'' when mp is understood.
Property 1 tells us that every measure can be mapped into an ACL2
ordinal. (See [o-p].) This mapping is performed by fn. Property 2
tells us that if the measure x is smaller than the measure y
according to rel then the image of x under fn is a smaller than
that of y, according to the well-founded relation [o<]. (See [o<].)
Thus, the general form of a :well-founded-relation formula
establishes that there exists a rel-order preserving embedding
(namely via fn) of the mp-measures into the ordinals. We can thus
conclude that rel is well-founded on mp-measures.
Such well-founded relations are used in the admissibility test for
recursive functions, in particular, to show that the recursion
terminates. To illustrate how such information may be used,
consider a generic function definition
(defun g (x) (if (test x) (g (step x)) (base x))).
If rel has been shown to be well-founded on mp-measures, then g's
termination can be ensured by finding a measure, (m x), with the
property that m produces a measure:
(mp (m x)), ; Defun-goal-1
and that the argument to g gets smaller (when measured by m and
compared by rel) in the recursion,
(implies (test x) (rel (m (step x)) (m x))). ; Defun-goal-2
If rel is selected as the :well-founded-relation to be used in the
definition of g, the definitional principal will generate and
attempt to prove defun-goal-1 and defun-goal-2 to justify g. We
show later why these two goals are sufficient to establish the
termination of g. Observe that neither the ordinals nor the
embedding, fn, of the mp-measures into the ordinals is involved in
the goals generated by the definitional principal.
Suppose now that a :well-founded-relation theorem has been proved for
mp and rel. How can rel be ``selected as the
:well-founded-relation'' by [defun]? There are two ways. First, an
[xargs] keyword to the [defun] event allows the specification of a
:well-founded-relation. Thus, the definition of g above might be
written
(defun g (x)
(declare (xargs :well-founded-relation (mp . rel)))
(if (test x) (g (step x)) (base x)))
Alternatively, rel may be specified as the
:default-well-founded-relation in [ACL2-defaults-table] by
executing the event
(set-well-founded-relation rel).
When a [defun] event does not explicitly specify the relation in its
[xargs] the default relation is used. When ACL2 is initialized, the
default relation is [o<].
Finally, though it is probably obvious, we now show that defun-goal-1
and defun-goal-2 are sufficient to ensure the termination of g
provided property-1 and property-2 of mp and rel have been proved.
To this end, assume we have proved defun-goal-1 and defun-goal-2 as
well as property-1 and property-2 and we show how to admit g under
the primitive ACL2 definitional principal (i.e., using only the
ordinals). In particular, consider the definition event
(defun g (x)
(declare (xargs :well-founded-relation o<
:measure (fn (m x))))
(if (test x) (g (step x)) (base x)))
Proof that g is admissible: To admit the definition of g above we
must prove
(o-p (fn (m x))) ; *1
and
(implies (test x) ; *2
(o< (fn (m (step x))) (fn (m x)))).
But *1 can be proved by instantiating property-1 to get
(implies (mp (m x)) (o-p (fn (m x)))),
and then relieving the hypothesis with defun-goal-1, (mp (m x)).
Similarly, *2 can be proved by instantiating property-2 to get
(implies (and (mp (m (step x)))
(mp (m x))
(rel (m (step x)) (m x)))
(o< (fn (m (step x))) (fn (m x))))
and relieving the first two hypotheses by appealing to two instances
of defun-goal-1, thus obtaining
(implies (rel (m (step x)) (m x))
(o< (fn (m (step x))) (fn (m x)))).
By chaining this together with defun-goal-2,
(implies (test x)
(rel (m (step x)) (m x)))
we obtain *2. Q.E.D.")
(WET
(TRACE)
"Evaluate a form and print subsequent error trace
The acronym ``wet'' stands for ``with-error-trace''. Wet provides a
convenient way to obtain a backtrace when evaluation causes a guard
violation or other error.
The basic idea is that (wet form) evaluates form and, if there is an
error, shows a backtrace of calls that led to that error. Note
however that by default only calls of user-defined (not built-in)
functions ``supporting'' form in the following sense will show up
in the backtrace: those that occur in the macroexpansion of form or
(recursively) support any of those functions. So for example, since
(make-event form) macroexpands to (make-event-fn (quote form) ...),
calls of functions occurring in form will likely not show up in the
backtrace by default. The option :fns all overrides this default,
with potential loss of speed; more on this below.
The following example explains the use of wet. First, submit the
following three definitions:
(defun foo (x) (declare (xargs :guard (consp x))) (car x))
(defun bar (x) (foo (cdr x)))
(defun g (x) (bar (cdr x)))
Now imagine you have obtained the following guard violation:
ACL2 !>(g '(3 4))
ACL2 Error in TOP-LEVEL: The guard for the function call (FOO X),
which is (CONSP X), is violated by the arguments in the call (FOO NIL).
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet. See
:DOC set-guard-checking for information about suppressing this check
with (set-guard-checking :none), as recommended for new users.
ACL2 !>
With wet, you can get a backtrace of user-defined functions. The
package prefixes shown below, ACL2_*1*_, indicate that the
executable (logical) counterparts of the corresponding raw Lisp
functions are being called; see [guard]. Don't forget to start with
(include-book \"misc/wet\" :dir :system).
ACL2 !>(wet (g '(3 4)))
; Fast loading /projects/acl2/devel/books/misc/wet.fasl
TTAG NOTE: Adding ttag :TRACE! from the top level loop.
ACL2 Error in WET: The guard for the function call (FOO X), which
is (CONSP X), is violated by the arguments in the call (FOO NIL).
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet. See
:DOC set-guard-checking for information about suppressing this check
with (set-guard-checking :none), as recommended for new users.
Backtrace stack:
----------------
1. (ACL2_*1*_ACL2::FOO NIL)
2. (ACL2_*1*_ACL2::BAR (4))
3. (ACL2_*1*_ACL2::G (3 4))
ACL2 !>
By default, large structures are hidden during the printing of the
backtrace stack. But you can supply a value for keyword argument
:evisc-tuple to modify the printing: nil to avoid hiding, else a
suitable evisc-tuple, as shown below (see [evisc-tuple]).
ACL2 !>(wet (g '(3 4)) :evisc-tuple (evisc-tuple 1 1 nil nil))
; Fast loading /projects/acl2/devel/books/misc/wet.fasl
TTAG NOTE: Adding ttag :TRACE! from the top level loop.
ACL2 Error in WET: The guard for the function call (FOO X), which
is (CONSP X), is violated by the arguments in the call (FOO NIL).
To debug see :DOC print-gv, see :DOC trace, and see :DOC wet. See
:DOC set-guard-checking for information about suppressing this check
with (set-guard-checking :none), as recommended for new users.
Backtrace stack:
----------------
1. (ACL2_*1*_ACL2::FOO ...)
2. (ACL2_*1*_ACL2::BAR ...)
3. (ACL2_*1*_ACL2::G ...)
ACL2 !>
For a backtrace as a data object, evaluate the form (@ wet-stack).
But note that this object may not be a legal ACL2 value, for
example because of the ``*1*'' symbols shown above.
General Form:
(wet form ; an arbitrary form
:book bk-form ; optional, not evaluated
;;; the rest are optional and evaluated:
:evisc-tuple e ; an evisc-tuple
:fns fns ; :all, or a list of functions to show in a backtrace
:compile c ; :same, t, or nil; default :same (nil if :fns supplied)
Form is evaluated. If there is an error, a backtrace stack is printed
to the standard output ([*standard-co*]), containing (by default)
the user-defined function calls made before the error. Such
printing is controlled by the :evisc-tuple if supplied; otherwise,
hiding of large structures will occur. (Technical detail: by
default the global abbrev-evisc-tuple is used, if bound; see
[set-evisc-tuple].
The :fns option. As mentioned above, by default the wet backtrace
shows user-defined functions that syntactically ``support'' the
form being evaluated. This default can be overridden by supplying
an explicit list, fns, of functions, using option :fns fns; these
will then be the functions whose calls are eligible for inclusion
in the backtrace. The special value :fns :all will allow all
user-defined function calls in the backtrace. This value can be
useful when using [oracle-apply], for example, since the function
being applied isn't typically included as a syntactic supporter of
the form being evaluated.
The :compile option. Wet uses the [trace$] utility to modify the
definitions of affected functions so that they can record
information for the backtrace. As described above, these affected
functions are those that syntactically ``support'' the form unless
specified by the :fns option. As is the case for trace$ --- see
[trace$] --- the new definitions of these affected functions may or
may not be compiled. For trace$ and for wet, the default is to
compile the new definition if and only if the original definition
was compiled, except: For wet, if option :fns :all is provided,
then the default is not to compile the affected definitions. And
for trace$ and wet, the :compile option overrides the default, to
specify what will be compiled: value :same to compile each affected
function if and only if its original definition was compiled, value
t to compile all affected functions, and value nil to skip
compilation.
The :book option. Wet actually works by temporarily including a
community book,
(include-book \"misc/wet\" :dir :system)
and then passing its arguments to macro wet!, defined in that book.
The keyword argument :book allows you to specify a different book
that defines a macro wet! to which to pass its arguments. If the
value of :book is a string, then the book named by that string is
temporarily included using [include-book]: (include-book \"bk\").
Otherwise :book should be a list of arguments, to be provided
(unevaluated) to [include-book], for example (\"my-wet\" :dir
:my-utils). Thus you can experiment by copying community book
books/misc/wet.lisp to your own directory and making modifications
to the copy. If you make changes, we invite you to share them with
the ACL2 community (see [books]). Note that you can also supply
:book nil, in which case the definition of wet! in your current
session will be used without including a book.
Also see [trace$] for a general tracing utility. As mentioned above,
wet is implemented using trace$. Wet actually first applies
[untrace$]; upon completion, wet then applies [trace$] to re-trace
any functions that it had untraced, using their original trace
specs.")
(WHAT_IS_ACL2{Q}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"What Is ACL2?
[{IMAGE}]
ACL2 is a mathematical logic together with a mechanical theorem
prover to help you reason in the logic.
The logic is just a subset of applicative [Common Lisp]. (This link
takes you off the main route of the tour. You'll see some Common
Lisp on the tour, so visit this later!)
The theorem prover is an ``industrial strength'' version of the
Boyer-Moore theorem prover, Nqthm.
Models of all kinds of computing systems can be built in ACL2, just
as in Nqthm, even though the formal logic is Lisp.
Once you've built an ACL2 model of a system, you can run it.
You can also use ACL2 to prove theorems about the model.
[{IMAGE}]")
(WHAT_IS_A_MATHEMATICAL_LOGIC{Q}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"What is a Mathematical Logic?
[{IMAGE}]
{IMAGE}
A mathematical logic is a formal system of formulas (axioms) and
rules for deriving other formulas, called theorems.
A proof is a derivation of a theorem. To see a concrete proof tree,
click [here].
Why should you care? The neat thing about Theorems is that they are
``true.'' More precisely, if all the axioms are valid and the rules
are validity preserving, then anything derived from the axioms via
the rules is valid.
So, if you want to determine if some formula is true, prove it.
[{IMAGE}]")
(WHAT_IS_A_MECHANICAL_THEOREM_PROVER{Q}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"What is a Mechanical Theorem Prover?
[{IMAGE}]
A mechanical theorem prover is a computer program that finds proofs
of theorems.
{IMAGE}
The ideal mechanical theorem prover is automatic: you give it a
formula and it gives you a proof of that formula or tells you there
is no proof.
Unfortunately, automatic theorem provers can be built only for very
simple logics (e.g., propositional calculus) and even then
practical considerations (e.g., how many centuries you are willing
to wait) limit the problems they can solve.
[{IMAGE}]")
(WHAT_IS_A_MECHANICAL_THEOREM_PROVER{Q}_{CONT}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"What is a Mechanical Theorem Prover? (cont)
[{IMAGE}] To get around this, mechanical theorem provers often
require help from the user.
{IMAGE}
Click [here] to continue downward.
[{IMAGE}]")
(WHAT_IS_REQUIRED_OF_THE_USER{Q}
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"What is Required of the User?
[{IMAGE}]
It is not easy to build ACL2 models of complex systems. To do so, the
user must understand
* the system being modeled, and
* ACL2, at least as a programming language.
It is not easy to get ACL2 to prove hard theorems. To do so, the user
must understand
* the model,
* ACL2 as a mathematical logic, and
* be able to construct a proof (in interaction with ACL2).
ACL2 will help construct the proof but its primary role is to prevent
logical mistakes. The creative burden --- the mathematical insight
into why the model has the desired property --- is the user's
responsibility.
[{IMAGE}]")
(WHY-BRR
(BREAK-REWRITE)
"An explanation of why ACL2 has an explicit [brr] mode
Why isn't [brr] mode automatically disabled when there are no
monitored runes? The reason is that the list of monitored runes is
kept in a wormhole state.
See [wormhole] for more information on wormholes in general. But the
fundamental property of the wormhole function is that it is a
logical no-op, a constant function that does not take state as an
argument. When entering a wormhole, arbitrary information can be
passed in (including the external state). That information is used
to construct a near copy of the external state and that ``wormhole
state'' is the one with respect to which interactions occur during
breaks. But no information is carried by ACL2 out of a wormhole ---
if that were allowed wormholes would not be logical no-ops. The
only information carried out of a wormhole is in the user's head.
[Break-rewrite] interacts with the user in a wormhole state because
the signature of the ACL2 rewrite function does not permit it to
modify [state]. Hence, only wormhole interaction is possible. (This
has the additional desirable property that the correctness of the
rewriter does not depend on what the user does during interactive
breaks within it; indeed, it is logically impossible for the user
to affect the course of [rewrite].)
Now consider the list of monitored runes. Is that kept in the
external state as a normal state global or is it kept in the
wormhole state? If it is in the external state then it can be
inspected within the wormhole but not changed. This is
unacceptable; it is common to change the [monitor]ed rules as the
proof attempt progresses, installing monitors when certain rules
are about to be used in certain contexts. Thus, the list of
monitored runes must be kept as a wormhole variable. Hence, its
value cannot be determined outside the wormhole, where the proof
attempt is ongoing.
This raises another question: If the list of monitored runes is
unknown to the rewriter operating on the external state, how does
the rewriter know when to break? The answer is simple: it breaks
every time, for every rune, if [brr] mode is enabled. The wormhole
is entered (silently), computations are done within the wormhole
state to determine if the user wants to see the break, and if so,
interactions begin. For unmonitored runes and runes with false
break conditions, the silent wormhole entry is followed by a silent
wormhole exit and the user perceives no break.
Thus, the penalty for running with [brr] mode enabled when there are
no monitored runes is high: a wormhole is entered on every
application of every rune and the user is simply unware of it. The
user who has finally unmonitored all runes is therefore strongly
advised to carry this information out of the wormhole and to do
:[brr] nil in the external state when the next opportunity arises.")
(WITH-BRR-ENS
(BREAK-REWRITE BRR-COMMANDS)
"Inside [break-rewrite], evaluate with respect to the theory currently
installed in the prover
Example Forms:
(with-brr-ens (pe 'nth))
(with-brr-ens (pl 'nth))
(with-brr-ens (disabledp 'nth))
General Form:
(with-brr-ens form)
where form is any form that evaluates either to a single value, val,
or to an [error-triple], (mv erp val state). The return value ---
which might be irrelevant if the form is evaluated for side-effect,
such as a call of a [history] command such as [pe] or [pl] --- is
(mv nil val state) in the first case and also, if erp is nil, in
the second case.
At the :[brr] prompt, evaluation of utilities such as :[pe] display
whether or not a rule is globally [disable]d. However, inside the
[break-rewrite] loop one might wish to know instead whether or not
the rule is disabled at the current stage of the proof attempt that
is underway. The wrapper with-brr-ens binds the so-called ``global
enabled structure'' to the corresponding structure that is
currently installed during the proof in progress, which will thus
be used for [history] queries such as [pe]. In order to take
advantage of this feature, you must state the query as an ordinary
expression, not as a keyword command (see [keyword-commands]), for
example as (with-brr-ens (pe 'nth)), not as (with-brr-ens :pe
'nth).")
(WITH-FAST-ALIST
(FAST-ALISTS ACL2-BUILT-INS)
"(with-fast-alist name form) causes name to be a fast alist for the
execution of form.
Logically, with-fast-alist just returns form.
Under the hood, we cause alist to become a fast alist before
executing form. If doing so caused us to introduce a new hash
table, the hash table is automatically freed after form completes.
More accurately, under the hood (with-fast-alist name form)
essentially expands to something like:
(if (already-fast-alist-p name)
form
(let ((<temp> (make-fast-alist name)))
(prog1 form
(fast-alist-free <temp>))))
Practically speaking, with-fast-alist is frequently a better choice
then just using [make-fast-alist], and is particularly useful for
writing functions that can take either fast or slow alists as
arguments. That is, consider the difference between:
(defun bad (alist ...)
(let* ((fast-alist (make-fast-alist alist))
(answer (expensive-computation fast-alist ...)))
(prog2$ (fast-alist-free fast-alist)
answer)))
(defun good (alist ...)
(with-fast-alist alist
(expensive-computation alist ...)))
Either approach is fine if the caller provides a slow alist. But if
the input alist is already fast, bad will (perhaps unexpectedly)
free it! On the other hand, good is able to take advantage of an
already-fast argument and will not cause it to be inadvertently
freed.
See also the macro with-fast-alists defined in the community book
\"books/centaur/misc/hons-extra.lisp\", which allows you to call
[with-fast-alist] on several alists simultaneously.
The community book \"books/centaur/misc/hons-extra.lisp\" extends the
[b*] macro with the with-fast pattern binder. That is, after
executing (include-book \"centaur/misc/hons-extra.lisp\" :dir
:system) you may write something like this:
(b* (...
((with-fast a b c ...))
...)
...)
which causes a, b, and c to become fast alists until the completion
of the b* form.
Note that with-fast-alist will cause logically tail-recursive
functions not to execute tail-recursively if its cleanup phase
happens after the tail-recursive call returns.")
(WITH-GUARD-CHECKING
(GUARD ACL2-BUILT-INS)
"Suppressing or enable guard-checking for a form
Example:
; Turn off all guard-checking for the indicated calls of append and car:
(with-guard-checking :none
(append 3 4))
General Form:
(with-guard-checking val form)
where val evaluates to a legal [guard]-checking value (see
[set-guard-checking], or evaluate *guard-checking-values* to see
the list of such values), and form is a form that does not mention
[state] (unless there is an active trust tag, in which case mention
of state can be unsound; see below). See
[with-guard-checking-error-triple] for an analogous utility for
forms that mention state. Form is to be evaluated in a scope such
that, in essence, (set-guard-checking val) is first executed
locally in that scope. However, this guard-checking setting is
ignored once evaluation passes into raw Lisp functions (see
[guards-and-evaluation]).
The remainder of this topic provides a remark for advanced users.
With-guard-checking is implemented using [return-last], which you
can in principle call directly; use :[trans] or :[trans1] to see
how a call of with-guard-checking expands to a corresponding call
of return-last. However, ACL2 enforces a couple of checks that can
only be circumvented if there is an active trust tag. The following
example from Jared Davis shows why those checks are required (in
particular, it shows how cirmventing them with a trust tag can be
unsound). We start by defining our own version of the utility,
which omits the check that the form has no occurrences of state.
(defmacro my-with-guard-checking (val form)
`(with-guard-checking1 (chk-with-guard-checking-arg ,val)
,form))
Submitting the following event results in the error shown just below
it.
(defun foo (state)
(declare (xargs :stobjs state
:guard (f-boundp-global 'guard-checking-on state)))
(my-with-guard-checking :all (f-get-global 'guard-checking-on state)))
ACL2 Error in ( DEFUN FOO ...): The form
(RETURN-LAST 'WITH-GUARD-CHECKING1-RAW
(CHK-WITH-GUARD-CHECKING-ARG :ALL)
(F-GET-GLOBAL 'GUARD-CHECKING-ON STATE))
is essentially a call of WITH-GUARD-CHECKING, but without certain checks
performed. This is illegal unless there is an active trust tag; see
:DOC defttag. To avoid this error without use of a trust tag, call
WITH-GUARD-CHECKING directly. Note: this error occurred in the context
(WITH-GUARD-CHECKING1 (CHK-WITH-GUARD-CHECKING-ARG :ALL)
(F-GET-GLOBAL 'GUARD-CHECKING-ON
STATE)).
But if we first evaluate (defttag t), then the [defun] event above is
admitted, and we can subsequently prove something that is not true.
(thm (equal (foo state)
(f-get-global 'guard-checking-on state)))
(assert-event (not (equal (foo state)
(f-get-global 'guard-checking-on state))))")
(WITH-GUARD-CHECKING-ERROR-TRIPLE
(GUARD ACL2-BUILT-INS)
"Suppressing or enable guard-checking for a form
Example:
; Turn off all guard-checking for the indicated calls of append and car:
(with-guard-checking-error-triple :none
(value (append 3 4)))
General Form:
(with-guard-checking-error-triple val form)
where val evaluates to a legal guard-checking value (see
[set-guard-checking], or evaluate *guard-checking-values* to see
the list of such values), and form is a form that returns an error
triple, (mv erp val state); see [error-triple]. Thus,
with-guard-checking-error-triple is much like
[with-guard-checking], but the former is to be used if form
mentions the ACL2 [state]; indeed, with-guard-checking-error-triple
requires form to evaluate to an error triple. As with
with-guard-checking, form is evalated in a context where
guard-checking has been set to the value of val, but this
guard-checking setting is ignored once evaluation passes into raw
Lisp functions (see [guards-and-evaluation]).")
(WITH-LIVE-STATE
(PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
"Allow a reference to state in raw Lisp
The macro with-live-state is an advanced feature that very few users
will need (basically, only system hackers). Indeed, it is
untouchable; see [remove-untouchable] for how to enable calling
with-live-state in the ACL2 loop.
Example Form:
(with-live-state (assign y 3))
General form:
(with-live-state form)
where form is an arbitrary form with a free reference to the variable
[state].
Logically, (with-live-state FORM) macroexpands to FORM. However, in
raw Lisp it expands to:
(let ((state *the-live-state*))
FORM)
If a form that mentions the variable [state] might be executed in raw
Lisp --- that is, either outside the ACL2 loop or in raw mode (see
[set-raw-mode]) --- then the surrounding the form with
with-live-state as shown above can avoid potential warnings or
(much less likely) errors. Note however that if state is lexically
bound to a state other than the usual ``live'' state, surprising
behavior may occur when evaluating a call of with-live-state in raw
Lisp or raw mode (either directly by evaluation or at compile
time), because with-live-state will override that lexical binding
of [state] by a lexical binding of state to the usual ``live''
state.")
(WITH-LOCAL-STATE
(STOBJ ACL2-BUILT-INS)
"Locally bind state
This is an advanced topic, probably of interest only to system
developers.
Consider the following example form:
(with-local-state
(mv-let (result state)
(compute-with-state x state)
result))
This is equivalent to the following form.
(with-local-stobj
state
(mv-let (result state)
(compute-with-state x state)
result))
By default, this form is illegal, because ACL2 does not have a way to
unwind all changes to the ACL2 [state]; we say more on this issue
below. There may however be situations where you are willing to
manage or overlook this issue. In that case you may execute the
following form to enable the use of with-local-state, by enabling
the use of [with-local-stobj] on state; but note that it requires
an active trust tag (see [defttag]).
(remove-untouchable create-state t)
Please be aware that no local [state] is actually created, however!
In particular, users of with-local-state need either to ensure that
channels are closed and state global variables are returned to
their original values, or else be willing to live with changes made
to state that are not justified by the code that has been
evaluated. You are welcome to look in the the ACL2 source code at
the definition of macro channel-to-string, which employs
with-local-state to create a local [state] for the purpose of
creating a string.
Here is an example use of with-local-state. Notice the use of
[defttag] --- and indeed, please understand that we are just
hacking here, and in general it takes significant effort to be sure
that one is using with-local-state correctly!
(defttag t)
(remove-untouchable create-state t)
(set-state-ok t)
(defun foo (state)
(declare (xargs :mode :program))
(mv-let
(channel state)
(open-input-channel \"my-file\" :object state)
(mv-let (eofp obj state)
(read-object channel state)
(declare (ignore eofp))
(let ((state (close-input-channel channel state)))
(mv obj state)))))
(defun bar ()
(declare (xargs :mode :program))
(with-local-state (mv-let (result state)
(foo state)
result)))
; Multiple-value return version:
(defun foo2 (state)
(declare (xargs :mode :program))
(mv-let
(channel state)
(open-input-channel \"my-file\" :object state)
(mv-let (eofp obj state)
(read-object channel state)
(let ((state (close-input-channel channel state)))
(mv eofp obj state)))))
(defun bar2 ()
(declare (xargs :mode :program))
(with-local-state (mv-let (eofp result state)
(foo2 state)
(mv eofp result))))")
(WITH-LOCAL-STOBJ
(STOBJ ACL2-BUILT-INS)
"Locally bind a single-threaded object
See [stobj] for an introduction to single-threaded objects.
Example Form:
(with-local-stobj
st
(mv-let (result st)
(compute-with-st x st)
result))
With-local-stobj can be thought of as a macro, where the example form
above expands as follows.
(mv-let (result st)
(let ((st (create-st)))
(compute-with-st x st))
(declare (ignore st))
result)
However, ACL2 expects you to use with-local-stobj, not its expansion.
More precisely, stobj creator functions are not allowed except
(implicitly) via with-local-stobj and in logic-only situations
(like theorems and hints). Moreover, neither with-local-stobj nor
its expansions are legal when typed directly at the top-level loop.
See [top-level] for a way to use with-local-stobj in the top-level
loop.
General Forms:
(with-local-stobj stobj-name mv-let-form)
(with-local-stobj stobj-name mv-let-form creator-name)
where stobj-name is the name of a [stobj], mv-let-form is a call of
[mv-let], and if creator-name is supplied then it should be the
name of the creator function for stobj-name; see [defstobj]. For
the example form above, its expansion would use creator-name, if
supplied, in place of create-st. Note that stobj-name must not be
[state] (the ACL2 state), except in special situations probably of
interest only to system developers; see [with-local-state].
With-local-stobj can be useful when a stobj is used to memoize
intermediate results during a computation, yet it is desired not to
make the stobj a formal parameter for the function and its callers.
ACL2 can reason about these ``local stobjs,'' and in particular about
stobj creator functions. For technical reasons, ACL2 will not allow
you to enable the :EXECUTABLE-COUNTERPART [rune] of a stobj creator
function.
Finally, here is a small example concocted in order to illustrate
that with-local-stobj calls can be nested.
(defstobj st fld1)
(defun foo ()
(with-local-stobj
st ; Let us call this the ``outer binding of st''.
(mv-let (val10 val20 st)
(let ((st (update-fld1 10 st)))
;; At this point the outer binding of st has fld1 = 10.
(let ((result (with-local-stobj
st ; Let us call this the ``inner binding of st''.
(mv-let (val st)
(let ((st (update-fld1 20 st)))
;; Now fld1 = 20 for the inner binding of st.
(mv (fld1 st) st))
val))))
;; So result has been bound to 20 above, but here we are once again
;; looking at the outer binding of st, where fld1 is still 10.
(mv (fld1 st) result st)))
(mv val10 val20))))
(thm (equal (foo) (mv 10 20))) ; succeeds")
(WITH-OUTPUT
(PROVER-OUTPUT)
"Suppressing or turning on specified output for an event
Examples:
; Turn off all output during evaluation of the indicated thm form.
(with-output
:off :all
:gag-mode nil
(thm (equal (app (app x y) z) (app x (app y z)))))
; Prove the indicated theorem with the event summary turned off and
; using the :goals setting for gag-mode.
(with-output
:off summary
:gag-mode :goals
(defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))
; Same effect as just above:
(with-output
:on summary
:summary nil
:gag-mode :goals
(defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))
; Turn on only the indicated parts of the summary.
(with-output
:on summary
:summary (time rules)
:gag-mode :goals ; use gag-mode, with goal names printed
(defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))
; Same as specifying :off :all, but showing all output types
; (i.e., the value of constant *valid-output-names*):
(with-output
:off (error warning warning! observation prove proof-checker event history
summary proof-tree)
:gag-mode nil
(thm (equal (app (app x y) z) (app x (app y z)))))
; Same as above, but :stack :push says to save the current
; inhibit-output-lst, which can be restored in a subsidiary with-output call
; that specifies :stack :pop.
(with-output
:stack :push
:off :all
:gag-mode nil
(thm (equal (app (app x y) z) (app x (app y z)))))
; Abbreviate printing in gag-mode for guard goals and induction schemes, but
; defeat abbreviated printing (if any) for terms.
(with-output
:evisc (:gag-mode (evisc-tuple 3 4 nil nil)
:term nil)
(defun h (x)
(declare (xargs :guard t))
(append (cons (make-list 10) x) x)))
General Form:
(with-output :key1 val1 ... :keyk valk form)
where each :keyi is either :off, :on, :stack, :summary, :gag-mode, or
:evisc; form evaluates to an [error-triple]; and vali is as
follows. If :keyi is :off or :on, then vali is either :all, or else
a symbol or non-empty list of symbols representing output types
that can be inhibited; see [set-inhibit-output-lst]. Note that vali
is not evaluated if :keyi is :off or :on. If :keyi is :summary,
then vali is either :all or a true-list of symbols each of which
belongs to the list *summary-types*. Note that vali is not
evaluated if :keyi is :summary. If :keyi is :gag-mode, then vali
should evaluate to one of the legal values for :[set-gag-mode]. If
:keyi is :evisc, then vali should be a [keyword-value-listp], where
each key is a legal keyword for the :sites keyword argument of
[set-evisc-tuple] other than :trace (that is, a member of the list
(:term :ld :abbrev :gag-mode)), and each value evaluates to a legal
[evisc-tuple] for that keyword. Otherwise :keyi is :stack, in which
case :vali is :push or :pop; for now assume that :stack is not
specified (we'll return to it below). The result of evaluating the
General Form above is to evaluate form, but in an environment where
output occurs as follows. If :on :all is specified, then every
output type is turned on except as inhibited by :off; else if :off
:all is specified, then every output type is inhibited except as
specified by :on; and otherwise, the currently-inhibited output
types are reduced as specified by :on and then extended as
specified by :off. If :gag-mode and/or :evisc are specified, then
before modifying how output is inhibited, [gag-mode] and/or the
appropriate [evisc-tuple]s are set for the evaluation of form as
specified by the values of those keywords; see [set-gag-mode] and
[set-evisc-tuple]. If summary is among the output types that are
turned on (not inhibited), then if :summary is specified, the only
parts of the summary to be printed will be those specified by the
value of :summary. The correspondence should be clear, except
perhaps that header refers to the line containing only the word
Summary, and value refers to the value of the form printed during
evaluation of sequences of events as for [progn] and [encapsulate].
Note that the handling of the :stack argument pays no attention to
the :summary argument.
Note: When the scope of with-output is exited, then all modifications
are undone: that is, the states of each of [gag-mode], the
[evisc-tuple]s, and output inhibition are all restored to those
which were present before the with-output call was entered.
The :stack keyword's effect is illustrated by the following example,
where ``(encapsulate nil)'' may replaced by ``(progn'' without any
change to the output that is printed.
(with-output
:stack :push :off :all
(encapsulate ()
(defun f1 (x) x)
(with-output :stack :pop (defun f2 (x) x))
(defun f3 (x) x)
(with-output :stack :pop :off warning (in-theory nil))
(defun f4 (x) x)))
The outer with-output call saves the current output settings (as may
have been modified by earlier calls of [set-inhibit-output-lst]),
by pushing them onto a stack, and then turns off all output. Each
inner with-output call temporarily pops that stack, restoring the
starting output settings, until it completes and undoes the effects
of that pop. Unless event output was inhibited at the top level
(see [set-inhibit-output-lst]), the following output is shown:
Since F2 is non-recursive, its admission is trivial. We observe that
the type of F2 is described by the theorem (EQUAL (F2 X) X).
And then, if summary output was not inhibited at the top level, we
get the rest of this output:
Summary
Form: ( DEFUN F2 ...)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Summary
Form: ( IN-THEORY NIL)
Rules: NIL
Warnings: None
Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
Note that the use of :off warning suppresses a \"Theory\" warning for
the (in-theory nil) event, and that in no case will output be
printed for definitions of f1, f3, or f4, or for the [encapsulate]
event itself.
The following more detailed explanation of :stack is intended only
for advanced users. After :gag-mode and :evisc are handled (if
present) but before :on or :off is handled, the value of :stack is
handled as follows. If the value is :push, then [state] global
inhibit-output-lst-stack is modified by pushing the value of
[state] global inhibit-output-lst onto the value of [state] global
inhibit-output-lst-stack, which is nil at the top level. If the
value is :pop, then [state] global inhibit-output-lst-stack is
modified only if non-nil, in which case its top element is popped
and becomes the value of of [state] global inhibit-output-lst.
Warning: With-output has no effect in raw Lisp (other than to expand
to the provided form argument), and hence is disallowed in function
bodies. However, you can probably get the effect you want as
illustrated below, where <form> must return an error-triple (mv erp
val state); see [ld] and see [error-triple].
Examples avoiding with-output, for use in function definitions:
; Inhibit all output:
(state-global-let*
((inhibit-output-lst *valid-output-names*))
<form>)
; Inhibit all warning output:
(state-global-let*
((inhibit-output-lst
(union-eq (f-get-global 'inhibit-output-lst state)
'(warning warning!))))
<form>)
Note that with-output is allowed in books. See [embedded-event-form].")
(WITH-OUTPUT-LOCK
(PARALLEL-PROGRAMMING ACL2-BUILT-INS)
"Provides a mutual-exclusion mechanism for performing output in
parallel
This documentation topic relates to an experimental extension of
ACL2, ACL2(p), created initially by David L. Rager. See
[compiling-ACL2p] for how to build an executable image that
supports parallel execution. Also see community books directory
books/parallel/ for examples.
One may wish to perform output while executing code in parallel. If
threads are allowed to print concurrently, the output will be
interleaved and often unreadable. To avoid this, the user can
surround forms that perform output with the with-output-lock macro.
Warning: with-output-lock may not perform as expected when called
directly in the loop; see [parallelism-at-the-top-level].
Take the following definition of pfib as an example.
(defun pfib (x)
(declare (xargs :guard (natp x)))
(cond ((mbe :logic (or (zp x) (<= x 0))
:exec (<= x 0))
0)
((= x 1) 1)
(t (plet (declare (granularity t))
((a (prog2$ (cw \"Computing pfib ~x0~%\" (- x 1))
(pfib (- x 1))))
(b (prog2$ (cw \"Computing pfib ~x0~%\" (- x 2))
(pfib (- x 2)))))
(+ a b)))))
With [parallel-execution] enabled, a call of (pfib 5)results in
non-deterministically interleaved output, for example as follows.
ACL2 !>(pfib 5)
CComputing pfib 4
omputing pfib 3
ComCpuotmipnugt ipnfgi bp fib3
2
Computing pCfiobm put2i
ng pfib 1
Computing pfib Co1mp
uting pfib 0
CCoommppuuttiinngg ppffiibb 12
ComCpuotmipnugt ipnfgi bp fib1
0
CoCmopmuptuitnign gp fpifbi b 1
0
5
ACL2 !>
If the user instead surrounds the calls to [cw] with the macro
with-output-lock, as in the following session, the output will no
longer be interleaved.
ACL2 !>
(defun pfib (x)
(declare (xargs :guard (natp x)))
(cond ((mbe :logic (or (zp x) (<= x 0))
:exec (<= x 0))
0)
((= x 1) 1)
(t (plet (declare (granularity t))
((a (prog2$ (with-output-lock
(cw \"Computing pfib ~x0~%\" (- x 1)))
(pfib (- x 1))))
(b (prog2$ (with-output-lock
(cw \"Computing pfib ~x0~%\" (- x 2)))
(pfib (- x 2)))))
(+ a b)))))
<snip>
ACL2 !>(pfib 5)
Computing pfib 4
Computing pfib 3
Computing pfib 3
Computing pfib 2
Computing pfib 2
Computing pfib 1
Computing pfib 2
Computing pfib 1
Computing pfib 1
Computing pfib 0
Computing pfib 1
Computing pfib 0
Computing pfib 1
Computing pfib 0
5
ACL2 !>")
(WITH-PROVER-STEP-LIMIT
(MISCELLANEOUS)
"Limit the number of steps for proofs
Logically, (with-prover-step-limit expr form) is equivalent to form,
except that if the number of ``prover steps'' executed during
evaluation of form exceeds a bound specified by the value of expr,
then that proof will abort. See [set-prover-step-limit] for a
related utility that sets the limit on prover steps globally
instead of setting it for just one form, and for a discussion of
the notion of ``prover steps'', which could change in future ACL2
releases. For a related utility based on time instead of prover
steps, see [with-prover-time-limit]; but as discussed in the
[documentation] for [set-prover-step-limit], there is at best a
loose connection between the counting of steps and
[with-prover-time-limit].
The arguments of (with-prover-step-limit expr form) are evaluated.
However, the (optional) argument flg is not evaluated in
(with-prover-step-limit expr flg form).
Depending on the machine you are using, you may have less than a
half-hour of time before the number of prover steps exceeds the
maximum limit on prover steps that may be imposed, which is one
less than the value of *default-step-limit*. But there is no limit
unless you explicitly call with-prover-step-limit or
[set-prover-step-limit].
For examples of how step-limits work besides those presented below,
see the community book books/misc/misc2/step-limits.lisp.
For a utility that returns an indicator of the number of prover steps
most recently taken, see [last-prover-steps].
Note that with-prover-step-limit may not be called inside
definitions, and that it is simply the identity macro in raw Lisp.
However, with-prover-step-limit! may be called in place of
with-prover-step-limit, with the effect described here even in raw
Lisp.
Examples:
; Limit (mini-proveall) to 100,000 prover steps (which happens to suffice)
(with-prover-step-limit 100000 (mini-proveall))
; Same as above for the inner call of with-prover-step-limit; so the
; mini-proveall call completes, but then we get an error because the second
; argument of the outer with-prover-step-limit call took more than 200
; steps.
(with-prover-step-limit
200
(with-prover-step-limit 100000 (mini-proveall)))
; Same as preceding form just above, except that this time there is no error,
; because the inner call of with-prover-step-limit has an extra argument
; of t inserted into the second argument position, which specifies that this
; entire inner call is treated as though it uses no prover steps.
(with-prover-step-limit
200
(with-prover-step-limit 100000 t (mini-proveall)))
; The inner call limits (mini-proveall) to 200 prover steps, which fails
; almost immediately.
(with-prover-step-limit 100000 (with-prover-step-limit 200 (mini-proveall)))
; Do not limit the number of prover steps, regardless of such a limit imposed
; globally or by the surrounding context.
(with-prover-step-limit nil (mini-proveall))
; Same as just above (indeed, nil above is converted to
; *default-step-limit*):
(with-prover-step-limit *default-step-limit* (mini-proveall))
; Advanced example: Limit the indicated theorem to 100 steps, and when the
; proof does not complete, then put down a label instead.
(mv-let (erp val state)
(with-prover-step-limit
100
(thm (equal (append (append x x) x)
(append x x x))))
(if erp
(deflabel foo :doc \"Attempt failed.\")
(value (list :succeeded-with val))))
; Use extra argument of t to avoid ``charging'' steps for the indicated
; form.
(with-prover-step-limit
500
(encapsulate
()
(with-prover-step-limit
500
t ; Don't charge prover steps for this first defthm.
(defthm test1
(equal (append x (append y z))
(append (append x y) z))
:rule-classes nil))
(defthm test2
(equal (append x (append y z))
(append (append x y) z))
:rule-classes nil)))
General Forms:
(with-prover-step-limit expr form)
(with-prover-step-limit expr flg form)
where form is an arbitrary form to evaluate, and expr evaluates to
one of the following: nil; a natural number not exceeding the value
of *default-step-limit*; or the special value, :START. The optional
extra argument in the second position, flg, must be Boolean if
supplied.
If the value of expr is a natural number less than the value of
*default-step-limit*, then that value is the maximum number of
prover steps permitted during evaluation of form before an error
occurs. If however the value of expr is nil or is the value of
*default-step-limit*, then no limit is placed on the number of
prover steps during processing of form. Otherwise, the value of
expr should be the keyword :START, which is intended for use by the
ACL2 implementation and may have semantics that change with new
ACL2 versions.
Finally we describe the optional extra Boolean argument, flg. If flg
is nil or omitted, then a running count of prover steps is
maintained after form is evaluated; otherwise, that count is not
affected by evaluation of form. To see how this works when flg is
nil or omitted, consider an event of shape (progn form1 form2),
where we are tracking prover steps (say, because of a superior call
of with-prover-step-limit). If n is the number of prover steps
available when the [progn] form is entered, and if s prover steps
are executed while evaluating form1, then n-s steps are available
for evaluation of form2 provided s does not exceed n; otherwise, an
error occurs. In particular, this is the case if form1 is an event
(with-prover-step-limit k form1'). However, if form1 is an event
(with-prover-step-limit k t form1'), then because of the extra
argument of t, no steps are ``charged'' to form; that is, all n
steps, rather than n-s steps, are available for evaluation of
form2.
Subtopics
[Last-prover-steps]
The number of prover steps most recently taken")
(WITH-PROVER-TIME-LIMIT
(MISCELLANEOUS)
"Limit the time for proofs
Examples:
; Limit (mini-proveall) to about 1/4 second:
(with-prover-time-limit 1/4 (mini-proveall))
; Limit (mini-proveall) to about 1/4 second, even if surrounding call of
; with-prover-time-limit provides for a more restrictive bound:
(with-prover-time-limit '(1/4) (mini-proveall))
; Limit the indicated theorem to about 1/50 second, and if the proof does not
; complete or it fails, then put down a label instead.
(mv-let (erp val state)
(with-prover-time-limit
1/50
(thm (equal (append (append x x) x)
(append x x x))))
(if erp
(deflabel foo :doc \"Attempt failed.\")
(value (list :succeeded-with val))))
General Form:
(with-prover-time-limit time form)
where time evaluates to a positive rational number or to a list
containing such, and form is arbitrary. Logically,
(with-prover-time-limit time form) is equivalent to form. However,
if the time for evaluation of form exceeds the value specified by
time, and if ACL2 notices this fact during a proof, then that proof
will abort, for example like this:
ACL2 Error in ( DEFTHM PERM-REFLEXIVE ...): Out of time in the rewriter.
If there is already a surrounding call of with-prover-time-limit that
has set up an expiration time, the inner with-prover-time-limit
call is not allowed to push that time further into the future
unless the inner time is specified as a list containing a rational,
rather than as a rational.
Note that by default, the time used is runtime (cpu time); to switch
to realtime (elapsed time), see [get-internal-time].
For a related utility based on prover steps instead of time, see
[with-prover-step-limit]; also see [set-prover-step-limit]. Those
utilities have the advantage of having platform-independent
behavior, unlike time limits, which of course are generally less
restrictive for faster processors. But note that the prover steps
counted need not correspond closely to prover time. For other
utilities that limit time, see [with-timeout] and
[oracle-timelimit].
Although with-prover-time-limit behaves like an ACL2 function in the
sense that it evaluates both its arguments, it is however actually
a macro that behaves as follows. (1) The value of its first (time
limit) argument affects the evaluation of its second argument (by
causing an error during that evaluation if the time for completion
is insufficient). (2) The second argument can return multiple
values (see [mv]), which are then returned by the call of
with-prover-time-limit. (3) Thus, there is not a fixed number of
values returned by with-prover-time-limit.
If you find that the time limit appears to be implemented too
loosely, it may be because the prover only checks the time elapsed
at certain points during the proof process, for example at entry to
the rewriter. For example, if you write your own [clause-processor]
that does an expensive computation, the time is unlikely to be
checked during its execution. If however you find the time limit
seems to be ignored even during ordinary prover operation, you are
encouraged to email an example to the ACL2 implementors with
instructions on how to observe the undesirable behavior. This
information can perhaps be used to improve ACL2 by the insertion of
more checks for expiration of the time limit.
The rest of this documentation topic explains the rather subtle
logical story, and is not necessary for understanding how to use
with-prover-time-limit. The ACL2 [state] object logically contains
a field called the acl2-oracle, which is an arbitrary true list of
objects; see [read-ACL2-oracle]. Our claim is that every ACL2
session makes sense for some value of acl2-oracle in the initial
state for that session. Logically, with-prover-time-limit is a
no-op, just returning its second value. But under the hood, it
provides a ``hint'' for the acl2-oracle, so that (logically
speaking) when its first element ([car]) is consulted by ACL2's
prover to see if the time limit has expired, it gets the ``right''
answer (specifically, either nil if all is well or else a message
to print if the time limit has expired). Logically, the acl2-oracle
is then [cdr]'ed --- that is, its first element is popped off ---
so that future results from read-acl2-oracle are independent of the
one just obtained.")
(WITH-SERIALIZE-CHARACTER
(SERIALIZE ACL2-BUILT-INS)
"Control output mode for print-object$
See [serialize] for a discussion of ``serialization'' routines,
contributed by Jared Davis for saving ACL2 objects in files for
later loading.
The expression (with-serialize-character char form) evaluates to the
value of form, but with the serialize-character of the [state]
assigned to char, which should be one of nil, #\\Y, or #\\Z. We
describe the effect of that assignment below. But note that if you
are doing this because of one or more specific calls of
print-object$, such as (print-object$ x channel state), then you
may wish instead to evaluate (print-object$-ser x
serialize-character channel state), in which case you will not need
to use with-serialize-character.
General forms:
(with-serialize-character nil form)
(with-serialize-character #Y form)
(with-serialize-character #Z form)
where form should evaluate to an [error-triple].
Note that if you prefer to obtain the same behavior (as described
below) globally, rather than only within the scope of
with-serialize-character, then use set-serialize-character in a
corresponding manner:
(set-serialize-character nil state)
(set-serialize-character #\\Y state)
(set-serialize-character #\\Z state)
In each case above, calls of print-object$ (see [io]) in form will
produce a readable object. In the first case, that object is
printed as one might expect at the terminal, as an ordinary Lisp
s-expression. But in the other cases, the object is printed by
first laying down either #Y or #Z (respectively) and then calling
[serialize-write] (or more precisely, the underlying function
called by serialize-write that prints to a stream).
Consider what happens when the ACL2 reader encounters an object
produced as described above (in the #Y or #Z case). When the object
was written, information was recorded on whether that object was a
[hons]. In the case of #Z, the object will be read as a hons if and
only if it was originally written as a hons. But in the case of #Y,
it will never be read as a hons. Thus, #Y and #Z will behave the
same if the original written object was not a hons, creating an
object that is not a hons. For an equivalent explanation and a bit
more discussion, see [serialize-read], in particular the discussion
of the hons-mode. The value :smart described there corresponds to
#Z, while :never corresponds to #Y.")
(WITH-STOLEN-ALIST
(HONS-AND-MEMOIZATION ACL2-BUILT-INS)
"(with-stolen-alist name form) ensures that name is a fast alist at
the start of the execution of form. At the end of execution, it
ensures that name is a fast alist if and only if it was originally.
That is, if name was not a fast alist originally, its hash table
link is freed, and if it was a fast alist originally but its table
was modified during the execution of form, that table is restored.
Note that any extended table created from the original fast alist
during form must be manually freed.
Logically, with-stolen-alist just returns form.
Under the hood, we cause alist to become a fast alist before
executing form, and we check the various conditions outlined above
before returning the final value.
Note that with-stolen-alist will cause logically tail-recursive
functions not to execute tail-recursively if its cleanup phase
happens after the tail-recursive call returns.")
(WITHOUT-EVISC
(IO ACL2-BUILT-INS)
"Print output in full
General Form:
(without-evisc form)
where form is any expression to evaluate. The effect is to evaluate
form as though the without-evisc wrapper were absent, except that
expressions are printed in full for the ensuing output, regardless
of the current evisc-tuples (see [set-evisc-tuple]). See
[set-iprint] for an example.
More precisely, without-evisc binds each of the term-evisc-tuple,
ld-evisc-tuple, abbrev-evisc-tuple and gag-mode-evisc-tuple to nil
(see [set-evisc-tuple]). It does not modify the trace evisc-tuple,
so trace output is not modified by without-evisc. Also note that
calls of printing functions such as [fmt] that include explicit
evisc-tuples will not have those evisc-tuples overridden. The
following example illustrates this point.
ACL2 !>(without-evisc
(fms \"~x0~%\"
(list (cons #0 '((a b ((c d)) e f g) u v w x y)))
*standard-co*
state
(evisc-tuple 2 3 nil nil)))
((A B # ...) U V ...)
<state>
ACL2 !>
We conclude with two remarks. (1) A call of without-evisc on
expression exp actually invokes a specialized call of [ld] on a
one-element list containing exp, which prints the value returned by
evaluation of exp but actually returns the useless value (mv nil
:invisible state). So do not use without-evisc in programs; just
use it at the top level of the ACL2 read-eval-print loop, or at
least the top level of ld. (2) Even when using without-evisc, if
the ACL2 logical [world] is part of the value returned, it will be
printed in abbreviated form because the ACL2 read-eval-print loop
always arranges for this to be the case, regardless of the
ld-evisc-tuple. For example:
ACL2 !>(without-evisc (w state))
<world>
ACL2 !>
An alternative to the use of without-evisc is to explore large
objects using the ACL2 function (walkabout object state). Some
brief documentation is printed when you enter an interactive loop
upon evaluating a call of walkabout. We may add documentation for
walkabout if that is requested.")
(WOF
(IO)
"Direct standard output and proofs output to a file
Example Form:
(wof \"tmp\" (pso)) ; same as (psof \"tmp\")
General Form:
(wof filename form)
where filename is a writable filename and form is any form that
evaluates to an error triple (see [programming-with-state]), that
is, a multiple value of the form (mv erp val state). All output to
channels [standard-co] and [proofs-co] will be directed to the
indicated file. It is acceptable to replace filename with (quote
filename).
Note that so-called comment-window output (see [cw] and see
[observation-cw]) is not redirected by wof to a file, nor is
printing from a [wormhole].")
(WORLD
(STATE)
"ACL2 property lists and the ACL2 logical database
The ACL2 logical world is a data structure that includes all logical
content resulting from the [command]s evaluated, back through and
including initialization, but not including commands that have been
undone (see [ubt]). Thus in particular, the world includes a
represention of the current logical theory, as well as some
extra-logical information such as the values of ACL2 [table]s. The
rest of this topic focuses on the structure of the the ACL2 world
and, more generally, the ``world'' data structure.
A ``world'' is a list of triples, each of the form (sym prop . val),
implementing the ACL2 notion of property lists. ACL2 permits the
simultaneous existence of many property list worlds. ``The world''
is often used as a shorthand for ``the ACL2 logical world'' which
is the particular property list world used within the ACL2 system
to maintain a database that contiains rules, [table]s, and so on.
Common Lisp provides the notion of ``property lists'' by which one
can attach ``properties'' and their corresponding ``values'' to
symbols. For example, one can arrange for the 'color property of
the symbol 'box-14 to be 'purple and the 'color property of the
symbol 'triangle-7 to be 'yellow. Access to property lists is given
via the Common Lisp function get. Thus, (get 'box-14 'color) might
return 'purple. Property lists can be changed via the special form
setf. Thus, (setf (get 'box-14 'color) 'blue) changes the Common
Lisp property list configuration so that (get 'box-14 'color)
returns 'blue. It should be obvious that ACL2 cannot provide this
facility, because Common Lisp's get ``function'' is not a function
of its argument, but instead a function of some implicit state
object representing the property list settings for all symbols.
ACL2 provides the functions getprop and putprop which allow one to
mimic the Common Lisp property list facility. However, ACL2's
getprop takes as one of its arguments a list that is a direct
encoding of what was above called the ``state object representing
the property list settings for all symbols.'' Because ACL2 already
has a notion of ``[state]'' that is quite distinct from that used
here, we call this property list object a ``world.'' A world is
just a true list of triples. Each triple is of the form (sym prop .
val). This world can be thought of as a slightly elaborated form of
association list and getprop is a slightly elaborated form of
[assoc] that takes two keys. When getprop is called on a symbol, s,
property p, and world, w, it scans w for the first triple whose sym
is s and prop is p and returns the corresponding val. Getprop has
two additional arguments: one controls what it returns if no such
sym and prop exist in w, and the other allows an extremely
efficient implementation. To set some property's value for some
symbol, ACL2 provides putprop. (putprop sym prop val w) merely
returns a new world, w', in which (sym prop . val) has been
[cons]ed onto the front of w, thus ``overwriting'' the prop value
of sym in w to val and leaving all other properties in w unchanged.
One aspect of ACL2's property list arrangement is that it is possible
to have many different property list worlds. For example, 'box-14
can have 'color 'purple in one world and can have 'color 'yes in
another, and these two worlds can exist simultaneously because
getprop is explicitly provided the world from which the property
value is to be extracted.
The efficiency alluded to above stems from the fact that Common Lisp
provides property lists. Using Common Lisp's provisions behind the
scenes, ACL2 can ``install'' the properties of a given world into
the Common Lisp property list state so as to make retrieval via
getprop very fast in the special case that the world provided to
getprop has been installed. To permit more than one installed
world, each of which is permitted to be changed via putprop, ACL2
requires that worlds be named and these names are used to
distinquish installed versions of the various worlds. At the moment
we do not further document getprop and putprop.
However, the ACL2 system uses a property list world, named
'current-acl2-world, in which to store the succession of user
[command]s and their effects on the logic. This world is often
referred to in our [documentation] as ``the world'' though it
should be stressed that the user is permitted to have worlds and
ACL2's is in no way distinguished except that the user is not
permitted to modify it except via event [command]s. The ACL2 world
is part of the ACL2 [state] and may be obtained via (w state).
Warning: The ACL2 world is very large. Its length as of this writing
(Version 2.5) is over 40,000 and it grows with each release.
Furthermore, some of the values stored in it are pointers to old
versions of itself. Printing (w state) is something you should
avoid because you likely will not have the patience to await its
completion. For these practical reasons, the only thing you should
do with (w state) is provide it to getprop, as in the form
(getprop sym prop default 'current-acl2-world (w state))
or its convenient abbrevation
(getpropc sym prop default)
to inspect properties within it, or to pass it to ACL2 primitives,
such as theory functions, where it is expected.
Some ACL2 [command] forms, such as theory expressions (see
[theories]) and the values to be stored in tables (see [table]),
are permitted to use the variable symbol world freely with the
understanding that when these forms are evaluated that variable is
bound to (w state). Theoretically, this gives those forms complete
knowledge of the current logical configuration of ACL2. However, at
the moment, few world scanning functions have been documented for
the ACL2 user. Instead, supposedly convenient macro forms have been
created and documented. For example, (current-theory :here), which
is the theory expression which returns the currently [enable]d
theory, actually macroexpands to (current-theory-fn :here world).
When evaluated with world bound to (w state), current-theory-fn
scans the current ACL2 world and computes the set of [rune]s
currently [enable]d in it.
Subtopics
[Formula]
The formula of a name or [rune]
[Getprop]
Access fast property lists
[Getpropc]
Access fast property lists
[Logical-name]
A name created by a logical event
[Props]
Print the ACL2 properties on a symbol
[Putprop]
Update fast property lists
[Redefined-names]
To collect the names that have been redefined")
(WORMHOLE
(STATE LD)
"[ld] without [state] --- a short-cut to a parallel universe
Example Form:
; The following form enters a recursive read-eval-print loop on a
; copy of the current state, allowing you to interact with that loop.
; Note that the form does not mention the ACL2 state variable!
; Evaluate the form below. Inside the resulting loop, define some function,
; e.g., with (defun foo (x) x). Then exit with :q and observe,
; e.g., with :pe foo, that the external state did not change.
(wormhole 'foo
'(lambda (whs) (set-wormhole-entry-code whs :ENTER))
nil
'(list 'hello 'there))
General Form:
(wormhole name entry-lambda input form
:current-package ... ; known package name
:ld-skip-proofsp ... ; nil, t or 'include-book
:ld-redefinition-action ; nil or '(:a . :b)
:ld-prompt ... ; nil, t, or some prompt printer fn
:ld-missing-input-ok ... ; nil, t, :warn, or warning message
:ld-pre-eval-filter ... ; :all, :query, or some new name
:ld-pre-eval-print ... ; nil, t, or :never
:ld-post-eval-print ... ; nil, t, or :command-conventions
:ld-evisc-tuple ... ; nil or '(alist level length hiding-cars)
:ld-error-triples ... ; nil or t
:ld-error-action ... ; :return!, :return, :continue, :error,
; or (:exit N)
:ld-query-control-alist ; alist supplying default responses
:ld-verbose ...) ; nil or t
The keyword arguments above are exactly those of [ld] (see [ld])
except that three of [ld]'s keyword arguments are missing: the
three that specify the channels [standard-oi], [standard-co] and
[proofs-co], which default in wormhole to ACL2's comment window.
There are two ways to create and enter a wormhole: wormhole as
described here and the simpler [wormhole-eval]. We recommend you
read this full account of wormholes before using wormhole-eval.
Ignoring the use of entry-lambda, wormhole manufactures a named
``wormhole [state]'' and calls the general-purpose ACL2
read-eval-print loop [ld] on it. However, when ld exits, the
wormhole evaporates and the function wormhole returns nil. The
manufactured state is like the ``current'' ACL2 [state] except for
two things. First, some information from the last wormhole state of
this name is transferred into the new state; this allows a wormhole
to maintain some state from one call to the next. Second, some
information from the wormhole call itself is transferred into the
new state; this allows the wormhole to be sensitive to context.
These two changes to the current state are reflected in the
settings (@ wormhole-status) and (@ wormhole-input) discussed in
detail below.
Note that wormhole may be called from environments in which [state]
is not bound. It is still applicative because it always returns
nil.
There are some restrictions about what can be done inside a wormhole.
As you may imagine, we really do not ``copy the current state'' but
rather just keep track of how we modified it and undo those
modifications upon exit. An error is signalled if you try to modify
state in an unsupported way. For this same reason, wormholes do not
allow updating of any user-defined single-threaded objects. See
[stobj].
One example wormhole is the implementation of the ACL2
[accumulated-persistence] facility for tracking the frequency with
which rules are tried. To implement this feature directly the
theorem prover would have to take the tracking data as an argument
and pass it around so that updates could be accumulated. This would
greatly clutter the code. Instead, the tracking data is maintained
in a wormhole. The theorem prover enters the wormhole to update the
data as rules are tried. When you request a display of the data,
[show-accumulated-persistence] enters the wormhole and prints the
data. But the data is never available outside that wormhole. The
ACL2 system uses a second wormhole to implement the [brr] facility,
allowing the user to interact with the rewriter as rules are
applied.
We now specify the arguments and behavior of wormhole.
The name argument must be a quoted constant and is typically a
symbol. It will be the ``name'' of the wormhole. A wormhole of that
name will be created the first time either wormhole or
[wormhole-eval] is called.
Every wormhole name has a ``status.'' The status of a wormhole is
stored outside of ACL2; it is inaccessible to the ACL2 user except
when in the named wormhole. But the status of a wormhole may be set
by the user from within the wormhole.
Upon the first call of wormhole or wormhole-eval on a name, the
status of that name is nil. But in general you should arrange for
the status to be a cons. The status is set by the quoted lambda
every time wormhole is called; but it may also be set in the form
argument (the first form evaluated in the interactive loop) by
assigning to the state global variable wormhole-status, as with
(assign wormhole-status ...)
or even by the user interacting with the loop if you do not exit the
loop with the first form. The car of the cons should be either
:ENTER or :SKIP and is called the wormhole's ``entry code.'' The
entry code of nil or an unexpectedly shaped status is :ENTER. The
cdr of the cons is arbitrary data maintained by you.
When wormhole is invoked, the status of the specified name is
incorporated into the manufactured wormhole state. In particular,
inside the wormhole, the status is the value of the state global
variable wormhole-status. That is, inside the wormhole, the status
may be accessed by (@ wormhole-status) and set by (assign
wormhole-status ...), f-get-global and f-put-global. When ld exits
-- typically because the form :q was read by ld -- the then-current
value of wormhole-status is hidden away so that it can be restored
when this wormhole is entered again. The rest of the wormhole state
is lost.
This allows a sequence of entries and exits to a wormhole to maintain
some history in the status and this information can be manipulated
by ACL2 functions executing inside the wormhole.
The second argument to wormhole must be a quoted lambda expression.
We explain it later.
The third argument, input, may be any term. The value of the term is
passed into the manufactured wormhole state, allowing you to pass
in information about the calling context. Inside the wormhole, the
input is available via (@ wormhole-input). It could be reassigned
via (assign wormhole-input ...), but there is no reason to do that.
The fourth argument, form, may be any term; when [ld] is called on
the manufactured wormhole state, the first form evaluated by ld
will be the value of form. Note that form will be translated by ld.
Errors, including guard violations, in the translation or execution
of that first form will leave you in the interactive loop of the
wormhole state.
When used properly, the first form allows you to greet your user
before reading the first interactive command or simply to do
whatever computation you want to do inside the wormhole and exit
silently. We give examples below.
Manufacturing a wormhole state is relatively expensive; in addition,
the forms executed by ld must be read, translated, and interpreted
as with any user type-in. The entry-lambda offers a way to avoid
this or, at least, to decide whether to incur that expense.
Before the wormhole state is manufactured and entered, the
entry-lambda is applied to the current wormhole status with
[wormhole-eval]. That lambda application must produce a new
wormhole status, which is stored as the wormhole's status. The
entry code for the new status determines whether wormhole actually
manufactures a wormhole state and calls ld.
If the entry code for that new status is :ENTER the wormhole state is
manufactured and entered; otherwise, the new status is simply saved
as the most recent status but the wormhole state is not
manufactured or entered. Note therefore that the entry-lambda may
be used to perform two functions: (a) to determine if it is really
necessary to manufacture a state and (b) to update the data in the
wormhole status as a function of the old status without invoking
ld.
The entry-lambda must be a quoted lambda expression of at most one
argument. Thus, the argument must be either
'(lambda (whs) <body>)
or
'(lambda () <body>)
Note the quote. If a formal, e.g., whs, is provided, it must be used
as a variable in the lambda body. The lambda-expression may contain
free variables, that is, the body may mention variables other than
the lambda formal. These free variables are understood in the
caller's environment. These conventions allow us to compile the
entry-lambda application very efficiently when the guard has been
verified.
The guard on a call of wormhole is the conjunction of the guards on
the arguments conjoined with the guard on the body of the
entry-lambda. See [wormhole-eval] for a discussion of the guard on
the lambda-expression.
The functions [wormhole-statusp], [wormhole-entry-code],
[wormhole-data], [set-wormhole-entry-code], [set-wormhole-data],
and [make-wormhole-status] may be useful in manipulating entry
codes and data in the entry-lambda.
Note that you access and manipulate the wormhole's status in two
different ways depending on whether you're ``outside'' of the
wormhole applying the quoted lambda or ``inside'' the
read-eval-print loop of the wormhole.
OUTSIDE (wormhole-eval): access via the value of the lambda formal
and set by returning the new status as the value of the lambda
body.
INSIDE (ld phase of wormhole): access via (@ wormhole-status), and
set via (assign wormhole-status ...).
Pragmatic Advice on Designing a Wormhole: Suppose you are using
wormholes to implement some extra-logical utility. You must
contemplate how you will use your wormhole's status to store hidden
information. You might be tempted to exploit the entry code as part
of the status. For example, you may think of :ENTER as indicating
that your utility is ``turned on'' and :SKIP as indicating that
your utility is ``turned off.'' We advise against such a design. We
recommend you base your decisions on the wormhole data. We
recommend that you set but not read the wormhole entry code to
signal whether you wish to enter a full-fledged wormhole. To use
the entry code as a flag overloads it and invites confusion when
your facility is ``turned off'' but you have to enter the wormhole
for some reason.
For a behind-the-scenes description of how wormholes work, See
[wormhole-implementation].
Here are some sample situations handled by wormhole-eval and
wormhole. Let the wormhole in question be named DEMO. Initially its
status is NIL. The functions below all maintain the convention that
the status is either nil or of the form (:key . lst), where :key is
either :SKIP or :ENTER and lst is a true-list of arbitrary objects.
But since there is no way to prevent the user from entering the
DEMO wormhole interactively and doing something to the status, this
convention cannot be enforced. Thus, the functions below do what we
say they do, e.g., remember all the values of x ever seen, only if
they're the only functions messing with the DEMO status. On the
other hand, the guards of all the functions below can be verified.
We have explicitly declared that the guards on the functions below
are to be verified, to confirm that they can be. Guard verification
is optional but wormholes (and wormhole-eval in particular) are
more efficient when guards have been verified. All of the functions
defined below return nil.
The examples below build on each other. If you really want to
understand wormholes we recommend that you evaluate each of the
forms below, in the order they are discussed.
Q. How do I create a wormhole that prints its status to the comment
window?
(defun demo-status ()
(declare (xargs :verify-guards t))
(wormhole-eval 'demo
'(lambda (whs)
(prog2$ (cw \"DEMO status:~%~x0~%\" whs)
whs))
nil))
Note above that after printing the status to the comment window we
return the new (unchanged) status whs. Had we just written the call
of cw, which returns nil, the function would print the status and
then set it to nil!
Q. How do I use a wormhole to collect every symbol, x, passed to the
function?
(defun demo-collect (x)
(declare (xargs :verify-guards t))
(wormhole-eval 'demo
'(lambda (whs)
(make-wormhole-status whs
(wormhole-entry-code whs)
(if (symbolp x)
(cons x (wormhole-data whs))
(wormhole-data whs))))
nil))
We could have also defined this function this way:
(defun demo-collect (x)
(declare (xargs :verify-guards t))
(if (symbolp x)
(wormhole-eval 'demo
'(lambda (whs)
(set-wormhole-data whs
(cons x (wormhole-data whs))))
nil)
nil))
Both versions always return nil and both versions collect into the
wormhole data field just the symbols x upon which demo-collect is
called.
Q. How do I use demo-collect? Below is a function that maps over a
list and computes its length. But it has been annotated with a call
to demo-collect on every element.
(defun my-len (lst)
(if (endp lst)
0
(+ 1
(prog2$ (demo-collect (car lst))
(my-len (cdr lst))))))
Thus, for example:
ACL2 !>(my-len '(4 temp car \"Hi\" rfix))
5
ACL2 !>(demo-status)
DEMO status:
(:ENTER RFIX CAR TEMP)
NIL
ACL2 !>
Q. How do I set the entry code to :ENTER or :SKIP according to
whether name is a member-equal of the list of things seen so far?
Note that we cannot check this condition outside the wormhole,
because it depends on the list of things collected so far. We make
the decision inside the lambda-expression. Note that we explicitly
check that the guard of member-equal is satisfied by the current
wormhole status, since we cannot rely on the invariant that no
other function interferes with the status of the DEMO wormhole. In
the case that the status is ``unexpected'' we act like the status
is nil and set it to (:SKIP . NIL).
(defun demo-set-entry-code (name)
(declare (xargs :verify-guards t))
(wormhole-eval 'demo
'(lambda (whs)
(if (true-listp (wormhole-data whs))
(set-wormhole-entry-code
whs
(if (member-equal name (wormhole-data whs))
:ENTER
:SKIP))
'(:SKIP . NIL)))
nil))
Thus
ACL2 !>(demo-set-entry-code 'monday)
NIL
ACL2 !>(demo-status)
DEMO status:
(:SKIP RFIX CAR TEMP)
NIL
ACL2 !>(demo-set-entry-code 'rfix)
NIL
ACL2 !>(demo-status)
DEMO status:
(:ENTER RFIX CAR TEMP)
NIL
ACL2 !>
Q. Suppose I want to collect every symbol and then, if the symbol has
an ABSOLUTE-EVENT-NUMBER property in the ACL2 logical world, print
the defining event with :pe and then enter an interactive loop; but
if the symbol does not have an ABSOLUTE-EVENT-NUMBER, don't print
anything and don't enter an interactive loop.
Here it is not important to know what ABSOLUTE-EVENT-NUMBER is; this
example just shows that we can use a wormhole to access the ACL2
logical world, even in a function that does not take the state as
an argument.
In the code below, we use wormhole instead of wormhole-eval, because
we might have to access the logical world and enter an interactive
loop. But for efficiency we do as much as we can inside the entry
lambda, where we can check whether x is symbol and collect it into
the data field of the wormhole status. Note that if we collect x,
we also set the entry code to :ENTER. If we don't collect x, we set
the entry code to :SKIP.
(defun collect-symbols-and-print-events (x)
(declare (xargs :guard t))
(wormhole 'demo
'(lambda (whs)
(if (symbolp x)
(make-wormhole-status whs
:ENTER
(cons x (wormhole-data whs)))
(set-wormhole-entry-code whs :SKIP)))
; The wormhole will not get past here is unless the entry code is
; :ENTER. If we get past here, we manufacture a state, put
; x into (@ wormhole-input) and call ld in such a way that the
; first form executed is the quoted if-expression below.
x
'(if (getpropc (@ wormhole-input) 'absolute-event-number)
(er-progn
(mv-let (col state)
(fmt \"~%Entering a wormhole on the event name ~x0~%\"
(list (cons #\\0 (@ wormhole-input)))
*standard-co* state nil)
(declare (ignore col))
(value nil))
(pe (@ wormhole-input))
(set-ld-prompt 'wormhole-prompt state)
(value :invisible))
(value :q))
:ld-verbose nil
:ld-prompt nil))
The ``first form'' (the if) asks whether the wormhole-input (i.e., x)
has an ABSOLUTE-EVENT-NUMBER property. If so, it enters an
[er-progn] to perform a sequence of commands, each of which returns
an ACL2 error triple (see [programming-with-state]). The first form
uses [fmt] to print a greeting. Since fmt returns (mv col state)
and we must return an error triple, we embed the fmt term in an
(mv-let (col state) ... (value nil)). The macro value takes an
object and returns a ``normal return'' error triple. The second
form in the er-progn uses the ACL2 history macro pe (see [pe]) to
print the defining event for a name. The third form sets the prompt
of this read-eval-print loop to the standard function for printing
the wormhole prompt. We silenced the printing of the prompt when we
called ld, thanks to the :ld-prompt nil keyword option. More on
this below. The fourth form returns the error triple value
:invisible as the value of the first form. This prevents ld from
printing the value of the first form. Since we have not exited ld,
that function just continues by reading the next form from the
comment window. The user perceives this as entering a
read-eval-print loop. We continue in the loop until the user types
:q.
On the other branch of the if, if the symbol has no
ABSOLUTE-EVENT-NUMBER property, we execute the form (value :q),
which is the programming equivalent of typing :q. That causes the
ld to exit.
The ld special variables set in the call to wormhole and further
manipulated inside the first form to ld may require explanation. By
setting :[ld-verbose] to nil, we prevent ld from printing the
familiar ACL2 banner when ld is called. If :ld-verbose nil is
deleted, then you would see something like
ACL2 Version 4.0. Level 2.
...
Type (good-bye) to quit completely out of ACL2.
before the first form is read and evaluated.
By setting :[ld-prompt] to nil we prevent ld from printing the prompt
before reading and evaluating the first form.
As this example shows, to use full-blown wormholes you must
understand the protocol for using wormhole status to control
whether a wormhole state is manufactured for ld and you must also
understand programming with [state] and the effects of the various
[ld] ``special variables.''
From the discussion above we see that wormholes can be used to create
formatted output without passing in the ACL2 [state]. For examples
see [cw], in particular the discussion at the end of that
documentation topic.
Subtopics
[Get-wormhole-status]
Make a wormhole's status visible outside the wormhole
[Make-wormhole-status]
Creates a wormhole status object from given status, entry code, and
data
[Set-wormhole-data]
Sets the wormhole data object in a wormhole status object
[Set-wormhole-entry-code]
Sets the wormhole entry code in a wormhole status object
[Wormhole-data]
Determines the wormhole data object from a wormhole status object
[Wormhole-entry-code]
Determines the wormhole entry code from a wormhole status object
[Wormhole-eval]
State-saving without state --- a short-cut to a parallel universe
[Wormhole-implementation]
Notes on how wormholes are implemented
[Wormhole-p]
Predicate to determine if you are inside a [wormhole]
[Wormhole-statusp]
Predicate recognizing well-formed wormhole status object")
(WORMHOLE-DATA
(WORMHOLE)
"Determines the wormhole data object from a wormhole status object
General Form: (wormhole-data whs)
See [wormhole]. Returns the wormhole data from a well-formed wormhole
status whs. If whs is nil or not well-formed, the data is nil.")
(WORMHOLE-ENTRY-CODE
(WORMHOLE)
"Determines the wormhole entry code from a wormhole status object
General Form: (wormhole-entry-code whs)
See [wormhole]. Returns :ENTER or :SKIP given a well-formed wormhole
status whs. If whs is nil or not well-formed, the entry code is
:ENTER.")
(WORMHOLE-EVAL
(WORMHOLE)
"State-saving without state --- a short-cut to a parallel universe
Example Form:
(wormhole-eval 'demo
'(lambda (whs)
(set-wormhole-data whs
(cons (cons name info)
(wormhole-data whs))))
(prog2$ info name))
General Form:
(wormhole-eval name lambda varterm)
where name must be a quoted wormhole name and lambda must be a quoted
lambda-expression. The lambda-expression must have at most one
formal parameter but the body of the lambda-expression may contain
other variables. Note that in the example form given above, the
lambda has one formal, whs, and uses name and info freely. Note
that the lambda is quoted. The third argument of wormhole-eval,
varterm, is an arbitrary term that should mention all of the free
variables in the lambda-expression. That term establishes your
``right'' to refer to those free variables in the environment in
which the wormhole-eval expression occurs. The value of varterm is
irrelevant and if you provide nil ACL2 will automatically provide a
suitable term, namely a prog2$ form like the one shown in the
example above.
Aside: Exception for ACL2(p) (see [parallelism]) to the irrelevance
of varterm. By default, calls of wormhole-eval employ a lock,
*wormhole-lock*. To avoid such a lock, include the symbol
:NO-WORMHOLE-LOCK in varterm; for example, you might replace a last
argument of nil in wormhole-eval by :NO-WORMHOLE-LOCK. End of
Aside.
See [wormhole] for a full explanation of wormholes. Most relevant
here is that every wormhole has a name and a status. The status is
generally a cons pair whose car is the keyword :ENTER or the
keyword :SKIP and whose cdr is an arbitrary object used to store
information from one wormhole call to the next.
Here is a succinct summary of wormhole-eval. If the lambda-expression
has a local variable, wormhole-eval applies the lambda-expression
to the wormhole status of the named wormhole and remembers the
value as the new wormhole status. If the lambda has no formal
parameter, the lambda is applied to no arguments and the value is
the new status. Wormhole-eval returns nil. Thus, the formal
parameter of the lambda-expression, if provided, denotes the
wormhole's hidden status information; the value of the lambda is
the new status and is hidden away.
The guard of a wormhole-eval call is the guard of the body of the
lambda-expression, with a fresh variable symbol used in place of
the formal so that no assumptions are possible about the hidden
wormhole status. If the guard of a wormhole-eval is verified, the
call is macroexpanded inline to the evaluation of the body in a
suitable environment. Thus, it can be a very fast way to access and
change hidden state information, but the results must remain
hidden. To do arbitrary computations on the hidden state (i.e., to
access the ACL2 [state] or logical [world] or to interact with the
user) see [wormhole].
Functions that are probably useful in the body of the [lambda] or the
guard of a function using wormhole-eval include the following:
[wormhole-statusp], [wormhole-entry-code], [wormhole-data],
[set-wormhole-entry-code], [set-wormhole-data], and
[make-wormhole-status].
See [wormhole] for a series of example uses of wormhole-eval and
wormhole.
For a behind-the-scenes description of how wormholes work, See
[wormhole-implementation].")
(WORMHOLE-IMPLEMENTATION
(WORMHOLE)
"Notes on how wormholes are implemented
What happens when you call [wormhole]? Recall that a typical call of
the function looks like this:
(wormhole 'name
'(lambda (whs) ...)
input
form
:ld-verbose ...
...)
A brief recap of the advertised semantics for wormhole establishes
our terminology: When the above wormhole is evaluated, the
lambda-expression is applied to the wormhole's status and the
result is stored as the new status. Then, if the entry-code of the
new status is :ENTER, [ld] is invoked on a copy of the ``current
state'' with the specified ld- ``special variables;'' output is
directed to the comment window. In that copy of the state, the
state-global variable wormhole-input is set to the value of input
and the state-global variable wormhole-status is set to the (new)
status computed by the lambda-expression. Thus, inside the
wormhole, (@ wormhole-input) returns the list of inputs, (@
wormhole-status) returns the current status, and (assign
wormhole-status ...) sets the wormhole's status. The first form
executed by the ld is the value of form and unless that form
returns (value :q), causing the ld to quit, the ld proceeds to take
subsequent input from the comment window. Upon exiting from ld, the
wormhole state ``evaporates.'' The wormhole's status upon exit is
remembered and restored the next time the wormhole is entered.
Here is what really happens.
Each wormhole's status is recorded in an alist stored in a Common
Lisp global variable named *wormhole-status-alist*. This variable
is not part of the ACL2 state. If you exit the ACL2 loop with :q
you can inspect the value of *wormhole-status-alist*. When the
lambda-expression is evaluated it is applied to the value
associated with name in the alist and the result is stored back
into that alist. This step is performed by [wormhole-eval]. To make
things more efficient, wormhole-eval is just a macro that expands
into a let that binds the lambda formal to the current status and
whose body is the lambda body. Guard clauses are generated from the
body, with one exception: the lambda formal is replaced by a new
variable so that no prior assumptions are available about the value
of the the wormhole status.
If the newly computed status has an entry code of :ENTER [ld] will be
invoked. But we don't really copy state, of course. Instead we will
invoke ld on the live state, which is always available in the von
Neumann world in which ACL2 is implemented. To give the illusion of
copying state, we will undo changes to the state upon exiting. To
support this, we do two things just before invoking ld: we bind a
Common Lisp special variable is to t to record that ACL2 is in a
wormhole, and we initialize an accumulator that will be used to
record state changes made while in the wormhole.
Then ld is invoked, with first argument, standard-oi, being set to
(cons form *standard-oi*). According to the standard semantics of
ld, this reads and evaluates form and then the forms in the
specified channel. The standard channels are directed to and from
the terminal, which is the physical realization of the comment
window.
All state modifying functions of ACL2 are sensitive to the special
variable that indicates that evaluation is in a wormhole. Some ACL2
state-modifying functions (e.g., those that modify the file system
like [write-byte$]) are made to cause an error if invoked inside a
wormhole on a file other than the terminal. Others, like
f-put-global (the function behind such features as assign and
maintenance of the ACL2 logical world by such events as [defun] and
[defthm]) are made to record the old value of the state component
being changed; these records are kept in the accumulator
initialized above.
Upon exit from ld for any reason, the final value of (@
wormhole-status) is stored in *wormhole-status-alist* and then the
accumulator is used to ``undo'' all the state changes.
Wormhole always returns nil.")
(WORMHOLE-P
(WORMHOLE)
"Predicate to determine if you are inside a [wormhole]
See [wormhole] for a discussion of wormholes. (Wormhole-p state)
returns (mv nil t state) when evaluated inside a wormhole, else (mv
nil nil state).")
(WORMHOLE-STATUSP
(WORMHOLE)
"Predicate recognizing well-formed wormhole status object
General Form: (wormhole-statusp whs)
See [wormhole]. This predicate is useful in guards for wormholes. It
checks whether whs is either nil or a cons whose car is :ENTER or
:SKIP.")
(WRITE-BYTE$ (POINTERS) "See [io].")
(XARGS
(DEFUN DECLARE)
"Extra arguments, for example to give [hints] to [defun]
Common Lisp's [defun] function does not easily allow one to pass
extra arguments such as ``[hints]''. ACL2 therefore supports a
peculiar new declaration (see [declare]) designed explicitly for
passing additional arguments to [defun] via a keyword-like syntax.
This declaration can also be used with [defmacro], but only for
xargs keyword :GUARD; so we restrict attention below to use of
xargs in [defun] [events].
The following declaration is nonsensical but does illustrate all of
the xargs keywords for [defun] (which are the members of the list
*xargs-keywords*).
(declare (xargs :guard (symbolp x)
:guard-debug t
:guard-hints ((\"Goal\" :in-theory (theory batch1)))
:hints ((\"Goal\" :in-theory (theory batch1)))
:measure (- i j)
:measure-debug t
:mode :logic
:non-executable t
:normalize nil
:otf-flg t
:ruler-extenders :basic
:split-types t
:stobjs ($s)
:verify-guards t
:well-founded-relation my-wfr))
General Form:
(xargs :key1 val1 ... :keyn valn)
where the keywords and their respective values are as shown below.
Note that once ``inside'' the xargs form, the ``extra arguments''
to [defun] are passed exactly as though they were keyword
arguments.
:GUARD
Value is a term involving only the formals of the function being
defined. The actual [guard] used for the definition is the
conjunction of all the [guard]s and types declared; see [declare].
Note that if no :guard is specified explicitly, then a guard of t is
assumed, as though one had declared (xargs :guard t). (Note that t
is indeed a term involving only the formals; it specifies that the
guard requiremeent is always met.) However, by default, a :[logic]
mode function definition will not attempt to verify guards unless
an expicit xargs :guard declaration is provided. For details on
this point, as well as how to change that default behavior, see
[set-verify-guards-eagerness].
:GUARD-DEBUG
Value: nil by default, else directs ACL2 to decorate each guard
proof obligation with hypotheses indicating its sources. See
[guard-debug].
:GUARD-HINTS
Value: hints (see [hints]), to be used during the [guard]
verification proofs as opposed to the termination proofs of the
[defun].
:[hints]
Value: hints (see [hints]), to be used during the termination proofs
as opposed to the [guard] verification proofs of the [defun].
:MEASURE
Value is a term involving only the formals of the function being
defined. This term indicates what is getting smaller in the
recursion. The well-founded relation with which successive measures
are compared is [o<] by default, but can be changed using the
:well-founded-relation keyword or with the
[set-well-founded-relation] event. Also allowed is a special case,
(:? v1 ... vk), where (v1 ... vk) enumerates a subset of the formal
parameters such that some valid measure involves only those formal
parameters. However, this special case is only allowed for
definitions that are redundant (see [redundant-events]) or are
executed when skipping proofs (see [skip-proofs]). Another special
case is :MEASURE nil, which is treated the same as if :MEASURE is
omitted.
:MEASURE-DEBUG
Value: nil by default, else directs ACL2 to decorate each
termination proof obligation with hypotheses indicating its
sources. See [measure-debug].
:MODE
Value is :[program] or :[logic], indicating the [defun] mode of the
function introduced. See [defun-mode]. If unspecified, the [defun]
mode defaults to the default [defun] mode of the current [world].
To convert a function from :[program] mode to :[logic] mode, see
[verify-termination].
:NON-EXECUTABLE
Value is normally t or nil (the default). Rather than stating
:non-executable t directly, which requires :[logic] mode and that
the definitional body has a certain form, we suggest using the
macro defun-nx or defund-nx; see [defun-nx]. A third value of
:non-executable for advanced users is :program, which is generated
by expansion of defproxy forms; see [defproxy]. For another way to
deal with non-executability, see [non-exec].
:NORMALIZE
Value is a flag telling [defun] whether to propagate [if] tests
upward, as well as potentially performing some simplification with
[type-set] reasoning and expanding calls of a few built-in
functions. Since the default is to do such ``normalization'', the
value supplied is only of interest when it is nil. (See [defun]).
:[otf-flg]
Value is a flag indicating ``onward through the fog'' (see
[otf-flg]). It applies to the [guard] verification, as it is
effectively t during the termination proof.
:RULER-EXTENDERS
For recursive definitions (possibly mutually recursive), value
controls termination analysis and the resulting stored induction
scheme. See [ruler-extenders] for a discussion of legal values and
their effects.
:SPLIT-TYPES
Value is t or nil, indicating whether or not [type]s are to be
proved from the [guard]s. The default is nil, indicating that type
declarations (see [declare]) contribute to the [guard]s. If the
value is t, then instead, the expressions corresponding to the type
declarations (see [type-spec]) are conjoined into a ``split-type
expression,'' and guard verification insists that this term is
implied by the specified :guard. Suppose for example that a
definition has the following [declare] form.
(declare (xargs :guard (p x y) :split-types t)
(type integer x)
(type (satisfies good-bar-p) y))
Then for guard verification, (p x y) is assumed, and in addition to
the usual proof obligations derived from the body of the
definition, guard verification requires a proof that (p x y)
implies both (integerp x) and (good-bar-p y). See community book
demos/split-types-examples.lisp for small examples.
:STOBJS
Value is either a single [stobj] name or a true list of stobj names
(see [stobj] and see [defstobj], and perhaps see [defabsstobj]).
Every stobj name among the formals of the function must be listed,
if the corresponding actual is to be treated as a stobj. That is,
if a function uses a stobj name as a formal parameter but the name
is not declared among the :stobjs then the corresponding argument
is treated as ordinary. The only exception to this rule is [state]:
whether you include it or not, state is always treated as a
single-threaded object. This declaration has two effects. One is to
enforce the syntactic restrictions on single-threaded objects. The
other is to strengthen the [guard] of the function being defined so
that it includes conjuncts specifying that each declared
single-threaded object argument satisfies the recognizer for the
corresponding single-threaded object.
:[verify-guards]
Value is t or nil, indicating whether or not [guard]s are to be
verified upon completion of the termination proof. This flag should
only be t if the :mode is unspecified but the default [defun] mode
is :[logic], or else the :mode is :[logic].
:[well-founded-relation]
Value is a function symbol that is known to be a well-founded
relation in the sense that a rule of class :[well-founded-relation]
has been proved about it. The effect is to replace the default
well-founded relation, which is typically [o<], by the specified
value. See [well-founded-relation] and see
[set-well-founded-relation] for further discussion, including how
to change the default well-founded-relation.
Subtopics
[Guard]
Restricting the domain of a function
[Otf-flg]
Allow more than one initial subgoal to be pushed for induction")
(XOR
(BASICS ACL2-BUILT-INS)
"Logical ``exclusive or''
Xor is the ACL2 exclusive-or function. (xor P Q) means that either P
or Q, but not both, is false (i.e., nil).
Function: <xor>
(defun xor (p q)
(declare (xargs :guard t))
(if p (if q nil t) (if q t nil)))")
(YOU_MUST_THINK_ABOUT_THE_USE_OF_A_FORMULA_AS_A_RULE
(PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
"You Must Think about the Use of a Formula as a Rule
[{IMAGE}]
This is good and bad.
The good news is that you can program ACL2's simplifier.
The bad news is that when you command ACL2 to prove a theorem you
must give some thought to how that theorem is to be used as a rule!
For example, if after proving associativity-of-app as previously
shown, you engaged in the mathematically trivial act of proving it
again but with the equality reversed, you would have programmed
ACL2's rewriter to loop forever.
You can avoid adding any rule by using the command:
(defthm associativity-of-app
(equal (app (app a b) c)
(app a (app b c)))
:rule-classes nil)
[{IMAGE}]")
(ZERO-TEST-IDIOMS
(NUMBERS)
"How to test for 0
Below are six commonly used idioms for testing whether x is 0. [Zip]
and [zp] are the preferred termination tests for recursions down
the integers and naturals, respectively.
idiom logical guard primary
meaning compiled code*
(equal x 0) (equal x 0) t (equal x 0)
(eql x 0) (equal x 0) t (eql x 0)
(zerop x) (equal x 0) x is a number (= x 0)
(= x 0) (equal x 0) x is a number (= x 0)
(zip x) (equal (ifix x) 0) x is an integer (= x 0)
(zp x) (equal (nfix x) 0) x is a natural (int= x 0)
(zpf x) (equal (nfix x) 0) x is a fixnum >= 0 (eql (the-fixnum x) 0)
*See [guards-and-evaluation], especially the subsection titled
``Guards and evaluation V: efficiency issues''. Primary code is
relevant only if [guard]s are verified. The ``compiled code'' shown
is only suggestive.
The first four idioms all have the same logical meaning and differ
only with respect to their executability and efficiency. In the
absence of compiler optimizing, (= x 0) is probably the most
efficient, (equal x 0) is probably the least efficient, and (eql x
0) is in between. However, an optimizing compiler could always
choose to compile (equal x 0) as (eql x 0) and, in situations where
x is known at compile-time to be numeric, (eql x 0) as (= x 0). So
efficiency considerations must, of course, be made in the context
of the host compiler.
Note also that (zerop x) and (= x 0) are indistinguishable. They have
the same meaning and the same [guard], and can reasonably be
expected to generate equally efficient code.
Note that (zip x) and (zp x) do not have the same logical meanings as
the others or each other. They are not simple tests for equality to
0. They each coerce x into a restricted domain, [zip] to the
integers and [zp] to the natural numbers, choosing 0 for x when x
is outside the domain. Thus, 1/2, #c(1 3), and 'abc, for example,
are all ``recognized'' as zero by both [zip] and [zp]. But [zip]
reports that -1 is different from 0 while [zp] reports that -1
``is'' 0. More precisely, (zip -1) is nil while (zp -1) is t.
Note that the last five idioms all have [guard]s that restrict their
Common Lisp executability. If these last five are used in
situations in which [guard]s are to be verified, then proof
obligations are incurred as the price of using them. If guard
verification is not involved in your project, then the first five
can be thought of as synonymous.
[Zip] and [zp] are not provided by Common Lisp but are ACL2-specific
functions. Why does ACL2 provide these functions? The answer has to
do with the admission of recursively defined functions and
efficiency. [Zp] is provided as the zero-test in situations where
the controlling formal parameter is understood to be a natural
number. [Zip] is analogously provided for the integer case. We
illustrate below.
Here is an admissible definition of factorial
(defun fact (n) (if (zp n) 1 (* n (fact (1- n)))))
Observe the classic recursion scheme: a test against 0 and recursion
by [1-]. Note however that the test against 0 is expressed with the
[zp] idiom. Note also the absence of a [guard] making explicit our
intention that n is a natural number.
This definition of factorial is readily admitted because when (zp n)
is false (i.e., nil) then n is a natural number other than 0 and so
(1- n) is less than n. The base case, where (zp n) is true, handles
all the ``unexpected'' inputs, such as arise with (fact -1) and
(fact 'abc). When calls of fact are evaluated, (zp n) checks
(integerp n) and (> n 0). [Guard] verification is unsuccessful for
this definition of fact because [zp] requires its argument to be a
natural number and there is no [guard] on fact, above. Thus the
primary raw lisp for fact is inaccessible and only the :[logic]
definition (which does runtime ``type'' checking) is used in
computation. In summary, this definition of factorial is easily
admitted and easily manipulated by the prover but is not executed
as efficiently as it could be.
Runtime efficiency can be improved by adding a [guard] to the
definition.
(defun fact (n)
(declare (xargs :guard (and (integerp n) (>= n 0))))
(if (zp n) 1 (* n (fact (1- n)))))
This [guard]ed definition has the same termination conditions as
before -- termination is not sensitive to the [guard]. But the
[guard]s can be verified. This makes the primary raw lisp
definition accessible during execution. In that definition, the (zp
n) above is compiled as (= n 0), because n will always be a natural
number when the primary code is executed. Thus, by adding a [guard]
and verifying it, the elegant and easily used definition of
factorial is also efficiently executed on natural numbers.
Now let us consider an alternative definition of factorial in which
(= n 0) is used in place of (zp n).
(defun fact (n) (if (= n 0) 1 (* n (fact (1- n)))))
This definition does not terminate. For example (fact -1) gives rise
to a call of (fact -2), etc. Hence, this alternative is
inadmissible. A plausible response is the addition of a [guard]
restricting n to the naturals:
(defun fact (n)
(declare (xargs :guard (and (integerp n) (>= n 0))))
(if (= n 0) 1 (* n (fact (1- n)))))
But because the termination argument is not sensitive to the [guard],
it is still impossible to admit this definition. To influence the
termination argument one must change the conditions tested. Adding
a runtime test that n is a natural number would suffice and allow
both admission and [guard] verification. But such a test would slow
down the execution of the compiled function.
The use of (zp n) as the test avoids this dilemma. [Zp] provides the
logical equivalent of a runtime test that n is a natural number but
the execution efficiency of a direct [=] comparison with 0, at the
expense of a [guard] conjecture to prove. In addition, if [guard]
verification and most-efficient execution are not needed, then the
use of (zp n) allows the admission of the function without a
[guard] or other extraneous verbiage.
While general rules are made to be broken, it is probably a good idea
to get into the habit of using (zp n) as your terminating ``0
test'' idiom when recursing down the natural numbers. It provides
the logical power of testing that n is a non-0 natural number and
allows efficient execution.
We now turn to the analogous function, [zip]. [Zip] is the preferred
0-test idiom when recursing through the integers toward 0. [Zip]
considers any non-integer to be 0 and otherwise just recognizes 0.
A typical use of [zip] is in the definition of [integer-length],
shown below. (ACL2 can actually accept this definition, but only
after appropriate lemmas have been proved.)
(defun integer-length (i)
(declare (xargs :guard (integerp i)))
(if (zip i)
0
(if (= i -1)
0
(+ 1 (integer-length (floor i 2))))))
Observe that the function recurses by (floor i 2). Hence, calling the
function on 25 causes calls on 12, 6, 3, 1, and 0, while calling it
on -25 generates calls on -13, -7, -4, -2, and -1. By making (zip
i) the first test, we terminate the recursion immediately on
non-integers. The [guard], if present, can be verified and allows
the primary raw lisp definition to check (= i 0) as the first
terminating condition (because the primary code is executed only on
integers).")
(ZEROP
(NUMBERS ACL2-BUILT-INS)
"Test an acl2-number against 0
(zerop x) is t if x is 0 and is nil otherwise. Thus, it is logically
equivalent to (equal x 0).
(Zerop x) has a [guard] requiring x to be numeric and can be expected
to execute more efficiently than (equal x 0) in properly [guard]ed
compiled code.
In recursions down the natural numbers, (zp x) is preferred over
(zerop x) because the former coerces x to a natural and allows the
termination proof. In recursions through the integers, (zip x) is
preferred. See [zero-test-idioms].
Zerop is a Common Lisp function. See any Common Lisp documentation
for more information.
Function: <zerop>
(defun zerop (x)
(declare (xargs :guard (acl2-numberp x)))
(eql x 0))")
(ZIP
(NUMBERS ACL2-BUILT-INS)
"Testing an ``integer'' against 0
(Zip i) is logically equivalent to (equal (ifix i) 0) and is the
preferred termination test for recursion through the integers. (Zip
i) returns t if i is 0 or not an integer; it returns nil otherwise.
Thus,
i (zip i)
3 nil
0 t
-2 nil
5/2 t
#c(1 3) t
'abc t
(Zip i) has a [guard] requiring i to be an integer.
For a discussion of the various idioms for testing against 0, see
[zero-test-idioms].
Zip is typically used as the termination test in recursions through
the integers. It has the advantage of ``coercing'' its argument to
an integer and hence allows the definition to be admitted without
an explicit type check in the body. [Guard] verification allows zip
to be compiled as a direct [=]-comparision with 0.
Function: <zip>
(defun zip (x)
(declare (xargs :guard (integerp x)))
(if (integerp x) (= x 0) t))")
(ZP
(NUMBERS ACL2-BUILT-INS)
"Testing a ``natural'' against 0
(Zp n) is logically equivalent to (equal (nfix n) 0) and is the
preferred termination test for recursion down the natural numbers.
(Zp n) returns t if n is 0 or not a natural number; it returns nil
otherwise. Thus, in the ACL2 logic (ignoring the issue of
[guard]s):
n (zp n)
3 nil
0 t
-1 t
5/2 t
#c(1 3) t
'abc t
(Zp n) has a [guard] requiring n to be a natural number.
For a discussion of the various idioms for testing against 0, see
[zero-test-idioms].
Zp is typically used as the termination test in recursions down the
natural numbers. It has the advantage of ``coercing'' its argument
to a natural and hence allows the definition to be admitted without
an explicit type check in the body. [Guard] verification allows zp
to be compiled as a direct [=]-comparision with 0.
Function: <zp>
(defun zp (x)
(declare (xargs :guard (and (integerp x) (<= 0 x))))
(if (integerp x) (<= x 0) t))")
(ZPF
(NUMBERS ACL2-BUILT-INS)
"Testing a nonnegative fixnum against 0
Zpf is exactly the same as [zp], except that zpf is intended for, and
faster for, fixnum arguments. Its guard is specified with a type
declaration, (type (unsigned-byte 29) x). (See [declare] and see
[type-spec].) Also see [zp].
Function: <zpf>
(defun zpf (x)
(declare (type (unsigned-byte 29) x))
(if (integerp x) (<= x 0) t))")
(ACL2-PC::=
(PROOF-CHECKER-COMMANDS)
"(atomic macro) attempt an equality (or equivalence) substitution
Examples:
= -- replace the current subterm by a term equated to it in
one of the hypotheses (if such a term exists)
(= x) -- replace the current subterm by x, assuming that the prover
can show that they are equal
(= (+ x y) z)
-- replace the term (+ x y) by the term z inside the current
subterm, assuming that the prover can prove
(equal (+ x y) z) from the current top-level hypotheses
or that this term or (equal z (+ x y)) is among the
current top-level hypotheses or the current governors
(= & z)
-- exactly the same as above, if (+ x y) is the current
subterm
(= (+ x y) z :hints :none)
-- same as (= (+ x y) z), except that a new subgoal is
created with the current goal's hypotheses and governors
as its top-level hypotheses and (equal (+ x y) z) as its
conclusion
(= (+ x y) z 0)
-- exactly the same as immediately above
(= (p x)
(p y)
:equiv iff
:otf-flg t
:hints ((\"Subgoal 2\" :BY FOO) (\"Subgoal 1\" :use bar)))
-- same as (= (+ x y) z), except that the prover uses
the indicated values for otf-flg and hints, and only
propositional (iff) equivalence is used (however, it
must be that only propositional equivalence matters at
the current subterm)
General Form:
(= &optional x y &rest keyword-args)
If terms x and y are supplied, then replace x by y inside the current
subterm if they are ``known'' to be ``equal''. Here ``known'' means
the following: the prover is called as in the prove command (using
keyword-args) to prove (equal x y), except that a keyword argument
:equiv is allowed, in which case (equiv x y) is proved instead,
where equiv is that argument. (See below for how governors are
handled.)
Actually, keyword-args is either a single non-keyword or is a list of
the form ((kw-1 x-1) ... (kw-n x-n)), where each kw-i is one of the
keywords :equiv, :otf-flg, :hints. Here :equiv defaults to equal if
the argument is not supplied or is nil, and otherwise should be the
name of an ACL2 equivalence relation. :Otf-flg and :hints give
directives to the prover, as explained above; also see
[ACL2-pc::prove]. However, no prover call is made if :hints is a
non-nil atom or if keyword-args is a single non-keyword (more on
this below).
Remarks on defaults
(1) If there is only one argument, say a, then x defaults to the
current subterm, in the sense that x is taken to be the current
subterm and y is taken to be a.
(2) If there are at least two arguments, then x may be the symbol &,
which then represents the current subterm. Thus, (= a) is
equivalent to (= & a). (Obscure point: actually, & can be in any
package, except the keyword package.)
(3) If there are no arguments, then we look for a top-level
hypothesis or a governor of the form (equal c u) or (equal u c),
where c is the current subterm. In that case we replace the current
subterm by u.
As with the prove command, we allow goals to be given ``bye''s in the
proof, which may be generated by a :hints keyword argument in
keyword-args. These result in the creation of new subgoals.
A proof is attempted unless the :hints argument is a non-nil atom
other than :none, or unless there is one element of keyword-args
and it is not a keyword. In that case, if there are any hypotheses
in the current goal, then what is attempted is a proof of the
implication whose antecedent is the conjunction of the current
hypotheses and governors and whose conclusion is the appropriate
equal term.
Remarks: (1) It is allowed to use abbreviations in the hints. (2) The
keyword :none has the special role as a value of :hints that is
shown clearly in an example above. (3) If there are governors, then
the new subgoal has as additional hypotheses the current governors.")
(ACL2-PC::ACL2-WRAP
(PROOF-CHECKER-COMMANDS)
"(macro) same as (lisp x)
Example:
(acl2-wrap (pe :here))
General Form:
(acl2-wrap form)
Same as (lisp form). This is provided for interface tools that want
to be able to execute the same form in raw Lisp, in the
proof-checker, or in the ACL2 top-level loop (lp).")
(ACL2-PC::ADD-ABBREVIATION
(PROOF-CHECKER-COMMANDS)
"(primitive) add an abbreviation
Example: (add-abbreviation v (* x y)) causes future occurrences of (*
x y) to be printed as (? v), until (unless) a corresponding
invocation of remove-abbreviations occurs. In this case we say that
v ``abbreviates'' (* x y).
General Form:
(add-abbreviation var &optional raw-term)
Let var be an abbreviation for raw-term, if raw-term is supplied,
else for the current subterm. Note that var must be a variable that
does not already abbreviate some term.
A way to think of abbreviations is as follows. Imagine that whenever
an abbreviation is added, say v abbreviates expr, an entry
associating v to expr is made in an association list, which we will
call ``*abbreviations-alist*''. Then simply imagine that ? is a
function defined by something like:
(defun ? (v)
(let ((pair (assoc v *abbreviations-alist*)))
(if pair (cdr pair)
(error ...))))
Of course the implementation isn't exactly like that, since the
``constant'' *abbreviations-alist* actually changes each time an
add-abbreviation instruction is successfully invoked. Nevertheless,
if one imagines an appropriate redefinition of the ``constant''
*abbreviations-alist* each time an add-abbreviation is invoked,
then one will have a clear model of the meaning of such an
instruction.
The effect of abbreviations on output is that before printing a term,
each subterm that is abbreviated by a variable v is first replaced
by (? v).
The effect of abbreviations on input is that every built-in
proof-checker command accepts abbreviations wherever a term is
expected as an argument, i.e., accepts the syntax (? v) whenever v
abbreviates a term. For example, the second argument of
add-abbreviation may itself use abbreviations that have been
defined by previous add-abbreviation instructions.
See also [ACL2-pc::remove-abbreviations] and see
[ACL2-pc::show-abbreviations].")
(ACL2-PC::AL
(PROOF-CHECKER-COMMANDS)
"(macro) same as apply-linear
Example:
(al 3)
See [ACL2-pc::apply-linear], as al and apply-linear are identical.")
(ACL2-PC::APPLY-LINEAR
(PROOF-CHECKER-COMMANDS)
"(primitive) apply a linear rule
Examples:
(apply-linear foo)
-- apply the linear rule `foo'
(apply-linear (:linear foo))
-- same as above
(apply-linear 2)
-- apply the second linear rule, as displayed by show-linears
rewrite
-- apply the first rewrite rule, as displayed by show-rewrites
(apply-linear foo ((y 7)))
-- apply the linear rule foo with the substitution
that associates 7 to the ``free variable'' y
(apply-linear foo ((x 2) (y 3)) t)
-- apply the linear rule foo by substituting 2 and 3 for free
variables x and y, respectively, and also binding all other
free variables possible by using the current context
(hypotheses and governors)
General Form:
(apply-linear &optional rule-id substitution instantiate-free)
Add a new top-level hypothesis by applying a [linear] rule to the
current subterm. The new hypothesis will be created according to
the information provided by the show-linears (sls) command.
A short name for this command is al.
We assume familiarity with the [proof-checker]'s rewrite (r) command
(see [ACL2-pc::rewrite]). In brief, the apply-linear command is an
analogue of the rewrite command, but for [linear] rules in place of
[rewrite] rules. There is a significant difference: for the
apply-linear command, instead of rewriting the current subterm as
is done by the rewrite command, the conclusion of the applicable
linear rule, suitably instantiated, is added as a new (and last)
top-level hypothesis of the goal. There is another significant
difference: the automatic application of [linear] rules in the
theorem prover is somewhat more complex than the automatic
application of [rewrite] rules, so the apply-linear command may not
correspond as closely to the prover's automatic use of a linear
rule as the rewrite command corresponds to the prover's automatic
use of a rewrite rule.
Below, we refer freely to the [documentation] for the proof-checker's
rewrite command (see [ACL2-pc::rewrite]).
The rule-id is treated just as it is by the rewrite command. If
rule-id is a positive integer n, then the nth rule as displayed by
show-linears is the one that is applied. If rule-id is nil or is
not supplied, then it is treated as the number 1. Otherwise,
rule-id should be either a symbol or else a :linear [rune]. If a
symbol is supplied, then any [linear] rule of that name may be
used.
Consider the following example. Suppose that the current subterm is
(< (g (h y)) y) and that foo is the name of the following linear
rule.
(implies (true-listp x)
(< (g x) 15))
Then the instruction (apply-linear foo) applies foo by adding a new
hypothesis (< (g (h y)) 15). In addition, a new goal with
conclusion (true-listp y) is created unless the current context
(top-level hypotheses and governors) implies (true-listp y) using
only ``trivial reasoning'', just as for the rewrite command.
If the rule-id argument is a number or is not supplied, then the
system will store an instruction of the form (apply-linear name
...), where name is the name of a [linear] rule; this is in order
to make it easier to replay instructions when there have been
changes to the history. Except: instead of the name (whether the
name is supplied or calculated), the system stores the [rune] if
there is any chance of ambiguity. (Formally, ``ambiguity'' here
means that the rune being applied is of the form (:rewrite name .
index), where index is not nil.)
Speaking in general, then, an apply-linear instruction works as
follows.
First, a [linear] rule is selected according to the arguments of the
instruction. The selection is made as explained under ``General
Form'' above.
Next, a trigger term of the rule (see [linear]) is matched with the
current subterm, i.e., a substitution unify-subst is found such
that if one instantiates that trigger term of the rule with
unify-subst, then one obtains the current subterm. If this match
fails, then the instruction fails.
Next, an attempt is made to relieve (discharge) the hypotheses,
possibly handling free variables (see [free-variables]), exactly as
is done with hypotheses when applying the [proof-checker] command,
rewrite (r).
Finally, the instruction is applied exactly as the rewrite
instruction is applied, except instead of replacing the current
subterm, the rule's instantiated conclusion is added to the end of
the list of top-level hypotheses of the goal.
Note that as for the rewrite command, the substitution argument
should be a list whose elements have the form (variable term),
where term may contain abbreviations.")
(ACL2-PC::BASH
(PROOF-CHECKER-COMMANDS)
"(atomic macro) call the ACL2 theorem prover's simplifier
Examples:
bash -- attempt to prove the current goal by simplification alone
(bash (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
-- attempt to prove the current goal by simplification alone,
with the indicated hints
General Form:
(bash &rest hints)
Call the theorem prover's simplifier, creating a subgoal for each
resulting goal.
Notice that unlike prove, the arguments to bash are spread out, and
are all hints.
Bash is similar to reduce in that neither of these allows induction.
But bash only allows simplification, while reduce allows processes
eliminate-destructors, fertilize, generalize, and
eliminate-irrelevance.
Remark: All forcing rounds will be skipped (unless there are more
than 15 subgoals generated in the first forcing round, an injustice
that should be rectified, but might remain unless there is pressure
to fix it).")
(ACL2-PC::BDD
(PROOF-CHECKER-COMMANDS)
"(atomic macro) prove the current goal using bdds
Examples:
bdd
(bdd :vars nil :bdd-constructors (cons) :prove t :literal :all)
The general form is as shown in the latter example above, but with
any keyword-value pairs omitted and with values as described for
the :[bdd] hint; see [hints].
This command simply calls the theorem prover with the indicated bdd
hint for the top-level goal. Note that if :prove is t (the
default), then the proof will succeed entirely using bdds or else
it will fail immediately. See [bdd].")
(ACL2-PC::BK
(PROOF-CHECKER-COMMANDS)
"(atomic macro) move backward one argument in the enclosing term
Example and General Form:
bk
For example, if the conclusion is (= x (* (- y) z)) and the current
subterm is (* (- y) z), then after executing bk, the current
subterm will be x.
Move to the previous argument of the enclosing term.
This is the same as up followed by (dive n-1), where n is the
position of the current subterm in its parent term in the
conclusion. Thus in particular, the nx command fails if one is
already at the top of the conclusion.
Also see [ACL2-pc::up], [ACL2-pc::dive], [ACL2-pc::top], and
[ACL2-pc::nx].")
(ACL2-PC::BOOKMARK
(PROOF-CHECKER-COMMANDS)
"(macro) insert matching ``bookends'' comments
Example:
(bookmark final-goal)
General Form:
(bookmark name &rest instruction-list)
Run the instructions in instruction-list (as though this were a call
of do-all; see [ACL2-pc::do-all]), but first insert a begin bookend
with the given name and then, when the instructions have been
completed, insert an end bookend with that same name. See
[ACL2-pc::comm] for an explanation of bookends and how they can
affect the display of instructions.")
(ACL2-PC::CASESPLIT
(PROOF-CHECKER-COMMANDS)
"(primitive) split into two cases
Example:
(casesplit (< x y)) -- assuming that we are at the top of the
conclusion, add (< x y) as a new top-level
hypothesis in the current goal, and create a
subgoal identical to the current goal except
that it has (not (< x y)) as a new top-level
hypothesis
General Form:
(casesplit expr &optional use-hyps-flag do-not-flatten-flag)
When the current subterm is the entire conclusion, this instruction
adds expr as a new top-level hypothesis, and create a subgoal
identical to the existing current goal except that it has the
negation of expr as a new top-level hypothesis. Also see
[ACL2-pc::claim]. The optional arguments control the use of
governors and the ``flattening'' of new hypotheses, as we now
explain.
The argument use-hyps-flag is only of interest when there are
governors. (To read about governors, see [ACL2-pc::hyps]). In that
case, if use-hyps-flag is not supplied or is nil, then the
description above is correct; but otherwise, it is not expr but
rather it is (implies govs expr) that is added as a new top-level
hypothesis (and whose negation is added as a top-level hypothesis
for the new goal), where govs is the conjunction of the governors.
If do-not-flatten-flag is supplied and not nil, then that is all
there is to this command. Otherwise (thus this is the default),
when the claimed term (first argument) is a conjunction (and) of
terms and the claim instruction succeeds, then each (nested)
conjunct of the claimed term is added as a separate new top-level
hypothesis. Consider the following example, assuming there are no
governors.
(casesplit (and (and (< x y) (integerp a)) (equal r s)) t)
Three new top-level hypotheses are added to the current goal, namely
(< x y), (integerp a), and (equal r s). In that case, only one
hypothesis is added to create the new goal, namely the negation of
(and (< x y) (integerp a) (equal r s)). If the negation of this
term had been claimed, then it would be the other way around: the
current goal would get a single new hypothesis while the new goal
would be created by adding three hypotheses.
Remark: It is allowed to use abbreviations in the hints.")
(ACL2-PC::CG
(PROOF-CHECKER-COMMANDS)
"(macro) change to another goal.
Examples:
(cg (main . 1)) -- change to the goal (main . 1)
cg -- change to the next-to-top goal
General Form:
(CG &OPTIONAL goal-name)
Same as (change-goal goal-name t), i.e. change to the indicated and
move the current goal to the end of the goal stack.")
(ACL2-PC::CHANGE-GOAL
(PROOF-CHECKER-COMMANDS)
"(primitive) change to another goal.
Examples:
(change-goal (main . 1)) -- change to the goal (main . 1)
change-goal -- change to the next-to-top goal
General Form:
(change-goal &optional goal-name end-flg)
Change to the goal with the name goal-name, i.e. make it the current
goal. However, if goal-name is nil or is not supplied, then it
defaults to the next-to-top goal, i.e., the second goal in the
stack of goals. If end-flg is supplied and not nil, then move the
current goal to the end of the goal stack; else merely swap it with
the next-to-top goal. Also see [ACL2-pc::cg].")
(ACL2-PC::CL-PROC
(PROOF-CHECKER-COMMANDS)
"(macro) same as clause-processor
This is simply an abbreviation for [ACL2-pc::clause-processor].")
(ACL2-PC::CLAIM
(PROOF-CHECKER-COMMANDS)
"(atomic macro) add a new hypothesis
Examples:
(claim (< x y)) -- attempt to prove (< x y) from the current
top-level hypotheses and if successful, then
add (< x y) as a new top-level hypothesis in
the current goal
(claim (< x y)
:otf-flg t
:hints ((\"Goal\" :induct t)))
-- as above, but call the prover using the
indicated values for the otf-flg and hints
(claim (< x y) 0) -- as above, except instead of attempting to
prove (< x y), create a new subgoal with the
same top-level hypotheses as the current goal
that has (< x y) as its conclusion
(claim (< x y) :hints :none)
-- same as immediately above
General Form:
(claim expr &rest rest-args)
This command creates a new subgoal with the same top-level hypotheses
as the current goal but with a conclusion of expr. If rest-args is
a non-empty list headed by a non-keyword, then there will be no
proof attempted for the new subgoal. With that possible exception,
rest-args should consist of keyword arguments. The keyword argument
:do-not-flatten controls the ``flattening'' of new hypotheses, just
as with the casesplit command (see [ACL2-pc::casesplit]). The
remaining rest-args are used with a call the prove command on the
new subgoal, except that if :hints is a non-nil atom, then the
prover is not called --- rather, this is the same as the situation
described above, where rest-args is a non-empty list headed by a
non-keyword.
Remarks: (1) Unlike the casesplit command, the claim command is
completely insensitive to governors. (2) It is allowed to use
abbreviations in the hints. (3) The keyword :none has the special
role as a value of :hints that is shown clearly in an example
above.")
(ACL2-PC::CLAUSE-PROCESSOR
(PROOF-CHECKER-COMMANDS)
"(atomic macro) use a clause-processor
Example:
(cl-proc :function
note-fact-clause-processor
:hint '(equal a a)) -- Invoke the indicated clause processor function
with the indicated hint argument (see the beginning of community book
books/clause-processors/basic-examples.lisp.
General Form:
(cl-proc &rest cl-proc-args)
Invoke a clause-processor as indicated by cl-proc-args, which is a
list of arguments that can serve as the value of a
:[clause-processor] hint; see [hints].
This command calls the prove command, and hence should only be used
at the top of the conclusion.")
(ACL2-PC::COMM
(PROOF-CHECKER-COMMANDS)
"(macro) display instructions from the current interactive session
Examples:
comm
(comm 10)
General Form:
(comm &optional n)
Prints out instructions in reverse order. This is actually the same
as (commands n t) --- or, (commands nil t) if n is not supplied. As
for commands (see [ACL2-pc::commands]), the final argument of t
causes suppression of instructions occurring between so-called
``matching bookends,'' which we now explain.
A ``begin bookend'' is an instruction of the form
(COMMENT :BEGIN x . y).
Similarly, an ``end bookend'' is an instruction of the form
(COMMENT :END x' . y').
The ``name'' of the first bookend is x and the ``name'' of the second
bookend is x'. When such a pair of instructions occurs in the
current state-stack, we call them ``matching bookends'' provided
that they have the same name (i.e. x equals x') and if no other
begin or end bookend with name x occurs between them. The idea now
is that comm hides matching bookends together with the instructions
they enclose. Here is a more precise explanation of this
``hiding''; probably there is no value in reading on!
A comm instruction hides bookends in the following manner. (So does a
comment instruction when its second optional argument is supplied
and non-nil.) First, if the first argument n is supplied and not
nil, then we consider only the last n instructions from the
state-stack; otherwise, we consider them all. Now the resulting
list of instructions is replaced by the result of applying the
following process to each pair of matching bookends: the pair is
removed, together with everything in between the begin and end
bookend of the pair, and all this is replaced by the
``instruction''
(\"***HIDING***\" :COMMENT :BEGIN name ...)
where (comment begin name ...) is the begin bookend of the pair.
Finally, after applying this process to each pair of matching
bookends, each begin bookend of the form (comment begin name ...)
that remains is replaced by
(\"***UNFINISHED***\" :COMMENT :BEGIN name ...) .")
(ACL2-PC::COMMANDS
(PROOF-CHECKER-COMMANDS)
"(macro) display instructions from the current interactive session
Examples:
commands
(commands 10 t)
General Forms:
commands or (commands nil)
Print out all the instructions (in the current state-stack) in
reverse order, i.e. from the most recent instruction to the starting
instruction.
(commands n) [n a positive integer]
Print out the most recent n instructions (in the current
state-stack), in reverse order.
(commands x abbreviate-flag)
Same as above, but if abbreviate-flag is non-NIL, then do not
display commands between ``matching bookends''. See documentation
for comm for an explanation of matching bookends.
Remark: If there are more than n instructions in the state-stack,
then (commands n) is the same as commands (and also, (commands n
abb) is the same as (commands nil abb)).")
(ACL2-PC::COMMENT
(PROOF-CHECKER-COMMANDS)
"(primitive) insert a comment
Example:
(comment now begin difficult final goal)
General Form:
(comment &rest x)
This instruction makes no change in the state except to insert the
comment instruction.
Some comments can be used to improve the display of commands; see
[ACL2-pc::comm].")
(ACL2-PC::CONTRADICT
(PROOF-CHECKER-COMMANDS)
"(macro) same as contrapose
See [ACL2-pc::contrapose].")
(ACL2-PC::CONTRAPOSE
(PROOF-CHECKER-COMMANDS)
"(primitive) switch a hypothesis with the conclusion, negating both
Example:
(contrapose 3)
General Form:
(contrapose &optional n)
The (optional) argument n should be a positive integer that does not
exceed the number of hypotheses. Negate the current conclusion and
make it the nth hypothesis, while negating the current nth
hypothesis and making it the current conclusion. If no argument is
supplied then the effect is the same as for (contrapose 1).
Remark: By ``negate'' we mean an operation that replaces nil by t, x
by nil for any other explicit value x, (not x) by x, and any other
x by (not x).")
(ACL2-PC::DEMOTE
(PROOF-CHECKER-COMMANDS)
"(primitive) move top-level hypotheses to the conclusion
Examples:
demote -- demote all top-level hypotheses
(demote 3 5) -- demote hypotheses 3 and 5
For example, if the top-level hypotheses are x and y and the
conclusion is z, then after execution of demote, the conclusion
will be (implies (and x y) z) and there will be no (top-level)
hypotheses.
General Form:
(demote &rest hyps-indices)
Eliminate the indicated (top-level) hypotheses, but replace the
conclusion conc with (implies hyps conc) where hyps is the
conjunction of the hypotheses that were eliminated. If no arguments
are supplied, then all hypotheses are demoted, i.e. demote is the
same as (demote 1 2 ... n) where n is the number of top-level
hypotheses.
Remark: You must be at the top of the conclusion in order to use this
command. Otherwise, first invoke top. Also, demote fails if there
are no top-level hypotheses or if indices are supplied that are out
of range.")
(ACL2-PC::DIVE
(PROOF-CHECKER-COMMANDS)
"(primitive) move to the indicated subterm
Examples:
(DIVE 1) -- assign the new current subterm to be the first
argument of the existing current subterm
(DIVE 1 2) -- assign the new current subterm to be the result of
first taking the 1st argument of the existing
current subterm, and then the 2nd argument of that
For example, if the current subterm is
(* (+ a b) c),
then after (dive 1) it is
(+ a b).
If after that, then (dive 2) is invoked, the new current subterm will
be
b.
Instead of (dive 1) followed by (dive 2), the same current subterm
could be obtained by instead submitting the single instruction
(dive 1 2).
General Form:
(dive &rest naturals-list)
If naturals-list is a non-empty list (n_1 ... n_k) of natural
numbers, let the new current subterm be the result of selecting the
n_1-st argument of the current subterm, and then the n_2-th subterm
of that, ..., finally the n_k-th subterm.
Remark: Dive is related to the command pp, in that the diving is done
according to raw (translated, internal form) syntax. Use the
command dv if you want to dive according to the syntax displayed by
the command p. Note that (dv n) can be abbreviated by simply n.
Remark: Emacs users who load (into Emacs) the file emacs/acl2-doc.el
will have defined a command, Control-t Control-d, that avoids the
need to type dive commands. After you print the current term using
the pp command, you may position the cursor on a subterm and type
Control-t Control-d. Emacs will respond by pasting the appropriate
dive command immediately after the proof-checker's prompt. You can
then simply type <RETURN> in order to dive to the desired subterm.")
(ACL2-PC::DO-ALL
(PROOF-CHECKER-COMMANDS)
"(macro) run the given instructions
Example:
(do-all induct p prove)
General Form:
(do-all &rest instruction-list)
Run the indicated instructions until there is a hard ``failure''. The
instruction ``succeeds'' if and only if each instruction in
instruction-list does. (See [ACL2-pc::sequence] for an explanation
of ``success'' and ``failure.'') As each instruction is executed,
the system will print the usual prompt followed by that
instruction, unless the global state variable
pc-print-prompt-and-instr-flg is nil.
Remark: If do-all ``fails'', then the failure is hard if and only if
the last instruction it runs has a hard ``failure''.
Obscure point: For the record, (do-all ins_1 ins_2 ... ins_k) is the
same as (sequence (ins_1 ins_2 ... ins_k)).")
(ACL2-PC::DO-ALL-NO-PROMPT
(PROOF-CHECKER-COMMANDS)
"(macro) run the given instructions, halting once there is a
``failure''
Example:
(do-all-no-prompt induct p prove)
General Form:
(do-all-no-prompt &rest instruction-list)
Do-all-no-prompt is the same as do-all, except that the prompt and
instruction are not printed each time, regardless of the value of
pc-print-prompt-and-instr-flg. Also, restoring is disabled. See
[ACL2-pc::do-all].")
(ACL2-PC::DO-STRICT
(PROOF-CHECKER-COMMANDS)
"(macro) run the given instructions, halting once there is a
``failure''
Example:
(do-strict induct p prove)
General Form:
(do-strict &rest instruction-list)
Run the indicated instructions until there is a (hard or soft)
``failure''. In fact do-strict is identical in effect to do-all,
except that do-all only halts once there is a hard ``failure''. See
[ACL2-pc::do-all].")
(ACL2-PC::DOC
(PROOF-CHECKER-COMMANDS)
"(macro) access documentation inside the proof-checker
Examples:
(doc rewrite) -- documentation on rewriting in ACL2
(doc acl2-pc::rewrite) -- documentation on the proof-checker rewrite command
(doc) -- same as (help doc) or (doc acl2-pc::doc)
doc -- same as above
General Forms:
(doc) ; or, just: help
(doc topic-name)
For any [documentation] topic, A, (doc A) prints documentation on A
to the terminal. You can read that documentation online or in the
Emacs [ACL2-Doc] browser; see [documentation]. This [proof-checker]
command provides a direct interface to the ACL2 :[doc] command at
the terminal.
Also see [ACL2-pc::help], which provides help for proof-checker
commands. For example, submitting (help rewrite) to the
proof-checker is equivalent to submitting (doc acl2-pc::rewrite) to
the proof-checker, which corresponds to submitting :doc
acl2-pc::rewrite directly to the ACL2 loop.")
(ACL2-PC::DROP
(PROOF-CHECKER-COMMANDS)
"(primitive) drop top-level hypotheses
Examples:
(drop 2 3) -- drop the second and third hypotheses
drop -- drop all top-level hypotheses
General Forms:
(drop n1 n2 ...) -- Drop the hypotheses with the indicated indices.
drop -- Drop all the top-level hypotheses.
Remark: If there are no top-level hypotheses, then the instruction
drop will fail. If any of the indices is out of range, i.e. is not
an integer between one and the number of top-level hypotheses
(inclusive), then (drop n1 n2 ...) will fail.")
(ACL2-PC::DV
(PROOF-CHECKER-COMMANDS)
"(atomic macro) move to the indicated subterm
Examples:
(dv 1) -- assign the new current subterm to be the first argument
of the existing current subterm
(dv 1 2) -- assign the new current subterm to be the result of
first taking the 1st argument of the existing
current subterm, and then the 2nd argument of that
For example, if the current subterm is
(* (+ a b) c),
then after (dv 1) it is
(+ a b).
If after that, then (dv 2) is invoked, the new current subterm will
be
b.
Instead of (dv 1) followed by (dv 2), the same current subterm could
be obtained by instead submitting the single instruction (dv 1 2).
General Form:
(dv &rest naturals-list)
If naturals-list is a non-empty list (n_1 ... n_k) of natural
numbers, let the new current subterm be the result of selecting the
n_1-st argument of the current subterm, and then the n_2-th subterm
of that, ..., finally the n_k-th subterm.
Remark: (dv n) may be abbreviated by simply n, so we could have typed
1 instead of (dv 1) in the first example above.
Remark: Emacs users who load (into Emacs) the file emacs/acl2-doc.el
will have defined a command, Control-t d, that avoids the need to
type dv commands. After you print the current term using the p or
th command, you may position the cursor on a subterm and type
Control-t d. Emacs will respond by pasting the appropriate dv
command immediately after the proof-checker's prompt. You can then
simply type <RETURN> in order to dive to the desired subterm.
Remark: A similar command is dive, which is related to the command
pp, in that the diving is done according to raw (translated,
internal form) syntax. (See [ACL2-pc::dive].) Use the command dv if
you want to dive according to the syntax displayed by the command
p. Thus, the command ``up'' is the inverse of dive, not of dv. The
following example illustrates this point.
ACL2 !>(verify (equal (* a b c) x))
->: p ; print user-level term
(EQUAL (* A B C) X)
->: pp ; print internal-form (translated) term
(EQUAL (BINARY-* A (BINARY-* B C)) X)
->: exit
Exiting....
NIL
ACL2 !>(verify (equal (* a b c) x))
->: p
(EQUAL (* A B C) X)
->: 1 ; same as (dv 1)
->: p ; print user-level term
(* A B C)
->: pp ; print internal-form (translated) term
(BINARY-* A (BINARY-* B C))
->: 3 ; dive to third argument of (* A B C)
->: p
C
->: up ; go up one level in (BINARY-* A (BINARY-* B C))
->: p
(* B C)
->: pp
(BINARY-* B C)
->:
Subtopics
[Dive-into-macros-table]
Right-associated function information for the [proof-checker]")
(ACL2-PC::ELIM
(PROOF-CHECKER-COMMANDS)
"(atomic macro) call the ACL2 theorem prover's elimination process
Example and General Form:
elim
Upon running the elim command, the system will create a subgoal will
be created for each goal that would have been pushed for proof by
induction in an ordinary proof, where only elimination is used; not
even simplification is used!")
(ACL2-PC::EQUIV
(PROOF-CHECKER-COMMANDS)
"(primitive) attempt an equality (or congruence-based) substitution
Examples:
(equiv (* x y) 3) -- replace (* x y) by 3 everywhere inside the
current subterm, if their equality is among the
top-level hypotheses or the governors
(equiv x t iff) -- replace x by t everywhere inside the current
subterm, where only propositional equivalence
needs to be maintained at each occurrence of x
General form:
(equiv old new &optional relation)
Substitute new for old everywhere inside the current subterm,
provided that either (relation old new) or (relation new old) is
among the top-level hypotheses or the governors (possibly by way of
backchaining and/or refinement; see below). If relation is nil or
is not supplied, then it defaults to equal. Also see acl2-pc::= for
a much more flexible command. Note that the equiv command fails if
no substitution is actually made.
Remark: No substitution takes place inside explicit values. So for
example, the instruction (equiv 3 x) will cause 3 to be replaced by
x if the current subterm is, say, (* 3 y), but not if the current
subterm is (* 4 y) even though 4 = (1+ 3).
The following remarks are quite technical and mostly describe a
certain weak form of ``backchaining'' that has been implemented for
equiv in order to support the = command. In fact neither the term
(relation old new) nor the term (relation new old) needs to be
explicitly among the current ``assumptions'', i.e., the top-level
hypothesis or the governors. Rather, there need only be such an
assumption that ``tells us'' (r old new) or (r new old), for some
equivalence relation r that refines relation. Here, ``tells us''
means that either one of the indicated terms is among those
assumptions, or else there is an assumption that is an implication
whose conclusion is one of the indicated terms and whose hypotheses
(gathered up by appropriately flattening the first argument of the
implies term) are all among the current assumptions.")
(ACL2-PC::EX
(PROOF-CHECKER-COMMANDS)
"(macro) exit after possibly saving the state
Example and General Form:
ex
Same as exit, except that first the instruction save is executed.
If save queries the user and is answered negatively, then the exit is
aborted.")
(ACL2-PC::EXIT
(PROOF-CHECKER-COMMANDS)
"(meta) exit the interactive proof-checker
Examples:
exit -- exit the interactive proof-checker
(exit t) -- exit after printing a bogus defthm event
(exit append-associativity) -- exit and create a defthm
event named append-associativity
General Forms:
exit -- Exit without storing an event.
(exit t) -- Exit after printing a bogus defthm event, showing :INSTRUCTIONS.
(exit event-name &optional rule-classes do-it-flg) --
Exit, and perhaps store an event
The command exit returns you to the ACL2 loop. At a later time,
(acl2::verify) may be executed to get back into the same
proof-checker state, as long as there hasn't been an intervening
use of the proof-checker (otherwise see [ACL2-pc::save]).
When given one or more arguments as shown above, exit still returns
you to the ACL2 loop, but first, if the interactive proof is
complete, then it attempts create a defthm event with the specified
event-name and rule-classes (which defaults to (:rewrite) if not
supplied). The event will be printed to the terminal, and then
normally the user will be queried whether an event should really be
created. However, if the final optional argument do-it-flg is
supplied and not nil, then an event will be made without a query.
For example, the form
(exit top-pop-elim (:elim :rewrite) t)
causes a defthm event named top-pop-elim to be created with
rule-classes (:elim :rewrite), without a query to the user (because
of the argument t).
Remark: it is permitted for event-name to be nil. In that case, the
name of the event will be the name supplied during the original
call of verify. (See [verify] and [ACL2-pc::commands].) Also in
that case, if rule-classes is not supplied then it defaults to the
rule-classes supplied in the original call of verify.
Comments on ``success'' and ``failure''. An exit instruction will
always ``fail'', so for example, if it appears as an argument of a
do-strict instruction then none of the later (instruction)
arguments will be executed. Moreover, the ``failure'' will be
``hard'' if an event is successfully created or if the instruction
is simply exit; otherwise it will be ``soft''. See
[ACL2-pc::sequence] for an explanation of hard and soft
``failures''. An obscure but potentially important fact is that if
the ``failure'' is hard, then the error signal is a special signal
that the top-level interactive loop can interpret as a request to
exit. Thus for example, a sequencing command that turns an error
triple (mv erp val state) into (mv t val state) would never cause
an exit from the interactive loop.
If the proof is not complete, then (exit event-name ...) will not
cause an exit from the interactive loop. However, in that case it
will print out the original user-supplied goal (the one that was
supplied with the call to verify) and the current list of
instructions.")
(ACL2-PC::EXPAND
(PROOF-CHECKER-COMMANDS)
"(primitive) expand the current function call without simplification
Examples:
expand -- expand and do not simplify.
Also see [ACL2-pc::x], which performs simplification, and see
[ACL2-pc::x-dumb], which provides a simple interface to
acl2-pc::expand.
For example, if the current subterm is (append a b), then after
expand the current subterm will be the term:
(if (consp a)
(cons (car a) (append (cdr a) b))
b)
regardless of the top-level hypotheses and the governors.
General Form:
(expand &optional do-not-expand-lambda-flg)
Expand the function call at the current subterm, and do not simplify.
The options have the following meanings:
do-not-expand-lambda-flg: default is nil; otherwise, the result
should be a lambda expression")
(ACL2-PC::FAIL
(PROOF-CHECKER-COMMANDS)
"(macro) cause a failure
Examples:
fail
(fail t)
General Form:
(fail &optional hard)
This is probably only of interest to writers of macro commands. The
only function of fail is to fail to ``succeed''.
The full story is that fail and (fail nil) simply return (mv nil nil
state), while (fail hard) returns (mv hard nil state) if hard is
not nil. Also see [ACL2-pc::do-strict], [ACL2-pc::do-all], and
[ACL2-pc::sequence].")
(ACL2-PC::FINISH
(PROOF-CHECKER-COMMANDS)
"(macro) require completion of instructions; save error if inside
:[hints]
Example:
(finish induct prove bash)
General Form:
(finish &rest instructions)
Run the indicated instructions, stopping at the first failure. If
there is any failure, or if any new goals are created and remain at
the end of the indicated instructions, then consider the call of
finish to be a failure. See [proof-checker-commands] and see
[ACL2-pc::sequence] for a discussion of the notion of ``failure''
for [proof-checker] commands.")
(ACL2-PC::FORWARDCHAIN
(PROOF-CHECKER-COMMANDS)
"(atomic macro) forward chain from an implication in the hyps
Example:
(forwardchain 2) ; Second hypothesis should be of the form
; (IMPLIES hyp concl), and the result is to replace
; that hypothesis with concl.
General Forms:
(forwardchain hypothesis-number)
(forwardchain hypothesis-number hints)
(forwardchain hypothesis-number hints quiet-flg)
This command replaces the hypothesis corresponding to given index,
which should be of the form (IMPLIES hyp concl), with its
consequent concl. In fact, the given hypothesis is dropped, and the
replacement hypothesis will appear as the final hypothesis after
this command is executed.
The prover must be able to prove the indicated hypothesis from the
other hypotheses, or else the command will fail. The :hints
argument is used in this prover call, and should have the usual
syntax of hints to the prover.
Output is suppressed if quiet-flg is supplied and not nil.")
(ACL2-PC::FREE
(PROOF-CHECKER-COMMANDS)
"(atomic macro) create a ``free variable''
Example:
(free x)
General Form:
(free var)
Mark var as a ``free variable''. Free variables are only of interest
for the put command; see [ACL2-pc::put].")
(ACL2-PC::GENEQV
(PROOF-CHECKER-COMMANDS)
"(macro) show the generated equivalence relation maintained at the
current subterm
General Forms:
geneqv ; show list of equivalence relations being maintained
(geneqv t) ; as above, but pair each relation with a justifying rune
This is an advanced command, whose effect is to print the so-called
``generated equivalence relation'' (or ``geneqv'') that is
maintained at the current subterm of the conclusion. That structure
is a list of equivalence relations, representing the transitive
closure E of the union of those relations, such that it suffices to
maintain E at the current subterm: if that subterm, u, is replaced
in the goal's conclusion, G, by another term equivalent to u with
respect to E, then the resulting conclusion is Boolean equivalent
to G. Also see [defcong].
The command `geneqv' prints the above list of equivalence relations,
or more precisely, the list of function symbols for those
relations. If however geneqv is given a non-nil argument, then a
list is printed whose elements are each of the form (s r), where s
is the symbol for an equivalence relation and r is a :[congruence]
[rune] justifying the inclusion of s in the list of equivalence
relations being maintained at the current subterm.")
(ACL2-PC::GENERALIZE
(PROOF-CHECKER-COMMANDS)
"(primitive) perform a generalization
Example:
(generalize
((and (true-listp x) (true-listp y)) 0)
((append x y) w))
General Form:
(generalize &rest substitution)
Generalize using the indicated substitution, which should be a
non-empty list. Each element of that list should be a two-element
list of the form (term variable), where term may use abbreviations.
The effect of the instruction is to replace each such term in the
current goal by the corresponding variable. This replacement is
carried out by a parallel substitution, outside-in in each
hypothesis and in the conclusion. More generally, actually, the
``variable'' (second) component of each pair may be nil or a
number, which causes the system to generate a new name of the form
_ or _n, with n a natural number; more on this below. However, when
a variable is supplied, it must not occur in any goal of the
current proof-checker state.
When the ``variable'' above is nil, the system will treat it as the
variable |_| if that variable does not occur in any goal of the
current proof-checker state. Otherwise it treats it as |_0|, or
|_1|, or |_2|, and so on, until one of these is not among the
variables of the current proof-checker state. If the ``variable''
is a non-negative integer n, then the system treats it as |_n|
unless that variable already occurs among the current goals, in
which case it increments n just as above until it obtains a new
variable.
Remark: The same variable may not occur as the variable component of
two different arguments (though nil may occur arbitrarily many
times, as may a positive integer).")
(ACL2-PC::GOALS
(PROOF-CHECKER-COMMANDS)
"(macro) list the names of goals on the stack
Example and General Form:
goals
Goals lists the names of all goals that remain to be proved. They are
listed in the order in which they appear on the stack of remaining
goals, which is relevant for example to the effect of a change-goal
instruction.")
(ACL2-PC::HELP
(PROOF-CHECKER-COMMANDS)
"(macro) proof-checker help facility
Examples:
(help rewrite) -- documentation on the proof-checker rewrite command
(help) -- this help
(help help) -- same as (help) or simply, help
(help all) -- same as (doc proof-checker-commands)
General Forms:
(help) ; or, just: help
(help command)
(help all)
For any proof-checker command, C, (help C) prints documentation on C
to the terminal. You can read that documentation online or in the
Emacs [ACL2-Doc] browser by viewing topic acl2-pc::C; see
[documentation].
To see a list of all proof-checker commands, you can submit (help
all). This is actually equivalent to (doc proof-checker-commands),
which prints the documentation for topic [proof-checker-commands]
(which, as discussed above, you can view online or with
[ACL2-Doc]).
Also see [ACL2-pc::doc], which provides a direct interface to the
ACL2 :[doc] command. For example, submitting (help rewrite) to the
proof-checker is equivalent to submitting (doc acl2-pc::rewrite) to
the proof-checker or submitting :doc acl2-pc::rewrite directly to
the ACL2 loop.")
(ACL2-PC::HYPS
(PROOF-CHECKER-COMMANDS)
"(macro) print the hypotheses
Examples:
hyps -- print all (top-level) hypotheses
(hyps (1 3) (2 4)) -- print hypotheses 1 and 3 and governors 2 and 4
(hyps (1 3) t) -- print hypotheses 1 and 3 and all governors
General Form:
(hyps &optional hyps-indices govs-indices)
Print the indicated top-level hypotheses and governors. (The notion
of ``governors'' is defined below.) Here, hyps-indices and
govs-indices should be lists of indices of hypotheses and governors
(respectively), except that the atom t may be used to indicate that
one wants all hypotheses or governors (respectively).
The list of ``governors'' is defined as follows. Actually, we define
here the notion of the governors for a pair of the form <term,
address>]; we're interested in the special case where the term is
the conclusion and the address is the current address. If the
address is nil, then there are no governors, i.e., the list of
governors is nil. If the term is of the form (if x y z) and the
address is of the form (2 . rest) or (3 . rest), then the list of
governors is the result of consing x or its negation (respectively)
onto the list of governors for the pair <y, rest> or the pair <z,
rest> (respectively). If the term is of the form (implies x y) and
the address is of the form (2 . rest), then the list of governors
is the result of consing x onto the list of governors for the pair
<y, rest>. Otherwise, the list of governors for the pair <term, (n
. rest)> is exactly the list of governors for the pair <argn, rest>
where argn is the nth argument of term.
If all goals have been proved, a message saying so will be printed.
(as there will be no current hypotheses or governors!).
The hyps command never causes an error. It ``succeeds'' (in fact its
value is t) if the arguments (when supplied) are appropriate, i.e.
either t or lists of indices of hypotheses or governors,
respectively. Otherwise it ``fails'' (its value is nil).")
(ACL2-PC::ILLEGAL
(PROOF-CHECKER-COMMANDS)
"(macro) illegal instruction
Example:
(illegal -3)
General Form:
(illegal instruction)
Probably not of interest to most users; always ``fails'' since it
expands to the fail command.
The illegal command is used mainly in the implementation. For
example, the instruction 0 is ``read'' as (illegal 0), since dive
expects positive integers.")
(ACL2-PC::IN-THEORY
(PROOF-CHECKER-COMMANDS)
"(primitive) set the current proof-checker theory
Example:
(in-theory
(union-theories (theory 'minimal-theory) '(true-listp binary-append)))
General Form:
(in-theory &optional atom-or-theory-expression)
If the argument is not supplied, then this command sets the current
proof-checker theory (see below for explanation) to agree with the
current ACL2 theory. Otherwise, the argument should be a theory
expression, and in that case the proof-checker theory is set to the
value of that theory expression.
The current proof-checker theory is used in all calls to the ACL2
theorem prover and rewriter from inside the proof-checker. Thus,
the most recent in-theory instruction in the current state-stack
has an effect in the proof-checker totally analogous to the effect
caused by an in-theory hint or event in ACL2. All in-theory
instructions before the last are ignored, because they refer to the
current theory in the ACL2 [state], not to the existing
proof-checker theory. For example:
ACL2 !>:trans1 (enable bar)
(UNION-THEORIES (CURRENT-THEORY :HERE)
'(BAR))
ACL2 !>:trans1 (CURRENT-THEORY :HERE)
(CURRENT-THEORY-FN :HERE WORLD)
ACL2 !>
Thus (in-theory (enable bar)) modifies the current theory of the
current ACL2 world. So for example, suppose that foo is disabled
outside the proof checker and you execute the following
instructions, in this order.
(in-theory (enable foo))
(in-theory (enable bar))
Then after the second of these, bar will be enabled in the
proof-checker, but foo will be disabled. The reason is that
(in-theory (enable bar)) instructs the proof-checker to modify the
current theory (from outside the proof-checker, not from inside the
proof-checker) by enabling bar.
Note that in-theory instructions in the proof-checker have no effect
outside the proof-checker's interactive loop.
If the most recent in-theory instruction in the current state of the
proof-checker has no arguments, or if there is no in-theory
instruction in the current state of the proof-checker, then the
proof-checker will use the current ACL2 theory. This is true even
if the user has interrupted the interactive loop by exiting and
changing the global ACL2 theory. However, if the most recent
in-theory instruction in the current state of the proof-checker had
an argument, then global changes to the current theory will have no
effect on the proof-checker state.")
(ACL2-PC::INDUCT
(PROOF-CHECKER-COMMANDS)
"(atomic macro) generate subgoals using induction
Examples:
induct, (induct t)
-- induct according to a heuristically-chosen scheme, creating
a new subgoal for each base and induction step
(induct (append (reverse x) y))
-- as above, but choose an induction scheme based on the term
(append (reverse x) y) rather than on the current goal
General Form:
(induct &optional term)
Induct as in the corresponding :induct hint given to the theorem
prover, creating new subgoals for the base and induction steps. If
term is t or is not supplied, then use the current goal to
determine the induction scheme; otherwise, use that term.
Remark: As usual, abbreviations are allowed in the term.
Remark: Induct actually calls the prove command with all processes
turned off. Thus, you must be at top of the goal for an induct
instruction.")
(ACL2-PC::LEMMAS-USED
(PROOF-CHECKER-COMMANDS)
"(macro) print the runes (definitions, lemmas, ...) used
This is just an alias for runes.")
(ACL2-PC::LISP
(PROOF-CHECKER-COMMANDS)
"(meta) evaluate the given form in Lisp
Example:
(lisp (assign xxx 3))
General Form:
(lisp form)
Evaluate form. The lisp command is mainly of interest for side
effects. Also see [ACL2-pc::print], [ACL2-pc::skip], and
[ACL2-pc::fail].
The rest of the documentation for lisp is of interest only to those
who use it in macro commands. If the Lisp evaluation (by
trans-eval) of form returns an [error-triple] of the form (mv erp
((NIL NIL STATE) . (erp-1 val-1 &)) state), then the lisp command
returns the appropriate error triple
(mv (or erp erp-1)
val-1
state) .
Otherwise, the trans-eval of form must return an error triple of the
form (mv erp (cons stobjs-out val) &), and the lisp command returns
the appropriate error triple
(mv erp
val
state).
Note that the output signature of the form has been lost. The user
must know the signature in order to use the output of the lisp
command. Trans-eval, which is undocumented except by comments in
the ACL2 source code, has replaced, in val, any occurrence of the
current state or the current values of stobjs by simple symbols
such as REPLACED-STATE. The actual values of these objects may be
recovered, in principle, from the state returned and the
user-stobj-alist within that state. However, in practice, the
stobjs cannot be recovered because the user is denied access to
user-stobj-alist. The moral is: do not try to write macro commands
that manipulate stobjs. Should the returned val contain
REPLACED-STATE the value may simply be ignored and state used,
since that is what REPLACED-STATE denotes.")
(ACL2-PC::NEGATE
(PROOF-CHECKER-COMMANDS)
"(macro) run the given instructions, and ``succeed'' if and only if
they ``fail''
Example: (negate prove)
General form:
(negate &rest instruction-list)
Run the indicated instructions exactly in the sense of do-all, and
``succeed'' if and only if they ``fail''.
Remark: Negate instructions will never produce hard ``failures''.")
(ACL2-PC::NIL
(PROOF-CHECKER-COMMANDS)
"(macro) used for interpreting control-d
Example and General form:
nil
(or, control-d).
The whole point of this command is that in some Lisps (including
akcl), if you type control-d then it seems, on occasion, to get
interpreted as nil. Without this command, one seems to get into an
infinite loop.")
(ACL2-PC::NOISE
(PROOF-CHECKER-COMMANDS)
"(meta) run instructions with output
Example:
(noise induct prove)
General Form:
(noise &rest instruction-list)
Run the instruction-list through the top-level loop with output.
In fact, having output is the default. Noise is useful inside a
surrounding call of quiet, when one temporarily wants output. For
example, if one wants to see output for a prove command immediately
following an induct command but before an s command, one may want
to submit an instruction like (quiet induct (noise prove) s). Also
see [ACL2-pc::quiet].")
(ACL2-PC::NX
(PROOF-CHECKER-COMMANDS)
"(atomic macro) move forward one argument in the enclosing term
Example and General Form:
nx
For example, if the conclusion is (= x (* (- y) z)) and the current
subterm is x, then after executing nx, the current subterm will be
(* (- y) z).
This is the same as up followed by (dive n+1), where n is the
position of the current subterm in its parent term in the
conclusion. Thus in particular, the nx command fails if one is
already at the top of the conclusion.
Also see [ACL2-pc::up], [ACL2-pc::dive], [ACL2-pc::top], and
[ACL2-pc::bk].")
(ACL2-PC::ORELSE
(PROOF-CHECKER-COMMANDS)
"(macro) run the first instruction; if (and only if) it ``fails'', run
the second
Example:
(orelse top (print \"Couldn't move to the top\"))
General form:
(orelse instr1 instr2)
Run the first instruction. Then if it ``fails'', run the second
instruction also; otherwise, stop after the first.
This instruction ``succeeds'' if and only if either instr1
``succeeds'', or else instr2 ``succeeds''. If it ``fails'', then
the failure is soft.")
(ACL2-PC::P
(PROOF-CHECKER-COMMANDS)
"(macro) prettyprint the current term
Example and General Form:
p
Prettyprint the current term. The usual user syntax is used, so that
for example one would see (and x y) rather than (if x y 'nil). (See
also pp.) Also, abbreviations are inserted where appropriate; see
[ACL2-pc::add-abbreviation].
The ``current term'' is the entire conclusion unless dive commands
have been given, in which case it may be a subterm of the
conclusion.
If all goals have been proved, a message saying so will be printed
(as there will be no current term!).")
(ACL2-PC::P-TOP
(PROOF-CHECKER-COMMANDS)
"(macro) prettyprint the conclusion, highlighting the current term
Example and General Form:
p-top
For example, if the conclusion is (equal (and x (p y)) (foo z)) and
the current subterm is (p y), then p-top will print (equal (and x
(*** (p y) ***)) (foo z)).
Prettyprint the the conclusion, highlighting the current term. The
usual user syntax is used, as with the command p (as opposed to
pp). This is illustrated in the example above, where one would*not*see (equal (if x (*** (p y) ***) 'nil) (foo z)).
Remark (obscure): In some situations, a term of the form (if x t y)
occurring inside the current subterm will not print as (or x y),
when x isn't a call of a boolean primitive. There's nothing
incorrect about this, however.")
(ACL2-PC::PL
(PROOF-CHECKER-COMMANDS)
"(macro) print the rules for a given name
Examples:
pl
(pl foo)
General Form:
(pl &optional x)
This command simply invokes the corresponding command of the
top-level ACL2 loop; see [pl]. If no argument is given, or if the
argument is nil, then the current subterm should be a call of a
function symbol, and the argument is taken to be that symbol.
If you want information about applying rewrite rules to the current
subterm, consider the show-rewrites (or equivalently, sr) command.")
(ACL2-PC::PP
(PROOF-CHECKER-COMMANDS)
"(macro) prettyprint the current term
Example and General Form:
pp
This is the same as p (see its documentation), except that raw syntax
(internal form) is used. So for example, one would see (if x y
'nil) rather than (and x y). Abbreviations are however still
inserted, as with p.")
(ACL2-PC::PR
(PROOF-CHECKER-COMMANDS)
"(macro) print the rules for a given name
Examples:
pr
(pr foo)
General Form:
(pr &optional x)
This command simply invokes the corresponding command of the
top-level ACL2 loop; see [pr]. If no argument is given, or if the
argument is nil, then the current subterm should be a call of a
function symbol, and the argument is taken to be that symbol.
If you want information about applying rewrite rules to the current
subterm, consider the show-rewrites (or equivalently, sr) command.")
(ACL2-PC::PRINT
(PROOF-CHECKER-COMMANDS)
"(macro) print the result of evaluating the given form
Example:
(print (append '(a b) '(c d)))
Print the list (a b c d) to the terminal
General Forms:
(print form)
(print form t)
Prettyprints the result of evaluating form. The evaluation of form
should return a single value that is not [state] or a
single-threaded object (see [stobj]). The optional second argument
causes printing to be done without elision (so-called
``evisceration''; see [evisc-tuple]).
If the form you want to evaluate does not satisfy the criterion
above, you should create an appropriate call of the lisp command
instead. Notice that this command always returns (mv nil nil state)
where the second result will always be REPLACED-STATE.")
(ACL2-PC::PRINT-ALL-CONCS
(PROOF-CHECKER-COMMANDS)
"(macro) print all the conclusions of (as yet unproved) goals
Example and General Form: print-all-concs
Prints all the conclusions of goals that remain to be proved, in a
pleasant format. Also see [ACL2-pc::print-all-goals].")
(ACL2-PC::PRINT-ALL-GOALS
(PROOF-CHECKER-COMMANDS)
"(macro) print all the (as yet unproved) goals
Example and General Form: print-all-goals
Prints all the goals that remain to be proved, in a pleasant format.
Also see [ACL2-pc::print-all-concs].")
(ACL2-PC::PRINT-MAIN
(PROOF-CHECKER-COMMANDS)
"(macro) print the original goal
Example and General Form:
print-main
Print the goal as originally entered.")
(ACL2-PC::PRO
(PROOF-CHECKER-COMMANDS)
"(atomic macro) repeatedly apply promote
Example and General Form:
pro
Apply the promote command until there is no change. This command
``succeeds'' exactly when at least one call of promote
``succeeds''. In that case, only a single new proof-checker state
will be created.")
(ACL2-PC::PROMOTE
(PROOF-CHECKER-COMMANDS)
"(primitive) move antecedents of conclusion's implies term to
top-level hypotheses
Examples:
promote
(promote t)
For example, if the conclusion is (implies (and x y) z), then after
execution of promote, the conclusion will be z and the terms x and
y will be new top-level hypotheses.
General Form:
(promote &optional do-not-flatten-flag)
Replace conclusion of (implies hyps exp) or (if hyps exp t) with
simply exp, adding hyps to the list of top-level hypotheses.
Moreover, if hyps is viewed as a conjunction then each conjunct
will be added as a separate top-level hypothesis. An exception is
that if do-not-flatten-flag is supplied and not nil, then only one
top-level hypothesis will be added, namely hyps.
Remark: You must be at the top of the conclusion in order to use this
command. Otherwise, first invoke top.")
(ACL2-PC::PROTECT
(PROOF-CHECKER-COMMANDS)
"(macro) run the given instructions, reverting to existing state upon
failure
Example:
(protect induct p prove)
General Form:
(protect &rest instruction-list)
Protect is the same as do-strict, except that as soon as an
instruction ``fails'', the state-stack reverts to what it was
before the protect instruction began, and restore is given the same
meaning that it had before the protect instruction began. See
[ACL2-pc::do-strict].")
(ACL2-PC::PROVE
(PROOF-CHECKER-COMMANDS)
"(primitive) call the ACL2 theorem prover to prove the current goal
Examples:
prove -- attempt to prove the current goal
(prove :otf-flg t
:hints ((\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar)))
-- attempt to prove the current goal, with the indicated hints
and with OTF-FLG set
General Form:
(prove &rest rest-args)
Attempt to prove the current goal, where rest-args is as in the
keyword arguments to defthm except that only :hints and :otf-flg
are allowed. The command succeeds exactly when the corresponding
defthm would succeed, except that it is all right for some goals to
be given ``bye''s. Each goal given a ``bye'' will be turned into a
new subgoal. (See [hints] for an explanation of :by hints.)
Remark: Use (= t) instead if you are not at the top of the
conclusion. Also note that if there are any hypotheses in the
current goal, then what is actually attempted is a proof of
(implies hyps conc), where hyps is the conjunction of the top-level
hypotheses and conc is the goal's conclusion.
Remark: It is allowed to use abbreviations in the hints.")
(ACL2-PC::PSO
(PROOF-CHECKER-COMMANDS)
"(macro) print the most recent proof attempt from inside the
proof-checker
Example and General Form:
pso
Print the most recent proof attempt from inside the proof-checker
assuming you are in [gag-mode] or have saved output (see
[set-saved-output]). This includes all calls to the prover,
including for example [proof-checker] commands induct, split, and
bash, in addition to prove. So for example, you can follow (quiet
prove) with pso to see the proof, including [proof-tree] output, if
it failed.
Related [proof-checker] commands are psog and pso!; see
[ACL2-pc::psog] and [ACL2-pc::pso!].")
(ACL2-PC::PSO!
(PROOF-CHECKER-COMMANDS)
"(macro) print the most recent proof attempt from inside the
proof-checker
Example and General Form:
pso!
Print the most recent proof attempt from inside the proof-checker,
including [proof-tree] output, assuming you are in [gag-mode] or
have saved output (see [set-saved-output]). This includes all calls
to the prover, including for example [proof-checker] commands
induct, split, and bash, in addition to prove. So for example, you
can follow (quiet prove) with pso! to see the proof, including
[proof-tree] output, if it failed.
Related [proof-checker] commands are pso and psog; see [ACL2-pc::pso]
and [ACL2-pc::psog].")
(ACL2-PC::PSOG
(PROOF-CHECKER-COMMANDS)
"(macro) print the most recent proof attempt from inside the
proof-checker
Example and General Form:
psog
Print the most recent proof attempt from inside the proof-checker,
including goal names, assuming you are in [gag-mode] or have saved
output (see [set-saved-output]). This includes all calls to the
prover, including for example [proof-checker] commands induct,
split, and bash, in addition to prove. So for example, you can
follow (quiet prove) with psog to see the proof, including
[proof-tree] output, if it failed.
Related [proof-checker] commands are pso and pso!; see [ACL2-pc::pso]
and [ACL2-pc::pso!].")
(ACL2-PC::PUT
(PROOF-CHECKER-COMMANDS)
"(macro) substitute for a ``free variable''
Example:
(put x 17)
General Form:
(put var expr)
Substitute expr for the ``free variable'' var, as explained below.
A ``free variable'' is, for our purposes, a variable var such that
the instruction (free var) has been executed earlier in the
state-stack. What (free var) really does is to let var be an
abbreviation for the term (hide var) (see
[ACL2-pc::add-abbreviation]). What (put var expr) really does is to
unwind the state-stack, replacing that free instruction with the
instruction (add-abbreviation var expr), so that future references
to (? var) become reference to expr rather than to (hide var), and
then to replay all the other instructions that were unwound.
Because hide was used, the expectation is that in most cases, the
instructions will replay successfully and put will ``succeed''.
However, if any replayed instruction ``fails'', then the entire
replay will abort and ``fail'', and the state-stack will revert to
its value before the put instruction was executed.
If (put var expr) ``succeeds'', then (remove-abbreviation var) will
be executed at the end.
Remark: The restore command will revert the state-stack to its value
present before the put instruction was executed.")
(ACL2-PC::QUIET
(PROOF-CHECKER-COMMANDS)
"(meta) run instructions without output
Example:
(quiet induct prove)
General Form:
(quiet &rest instruction-list)
Run the instruction-list through the top-level loop with no output.
Also see [ACL2-pc::noise].")
(ACL2-PC::R
(PROOF-CHECKER-COMMANDS)
"(macro) same as rewrite
Example:
(r 3)
See [ACL2-pc::rewrite].")
(ACL2-PC::REDUCE
(PROOF-CHECKER-COMMANDS)
"(atomic macro) call the ACL2 theorem prover's simplifier
Examples:
reduce -- attempt to prove the current goal without using induction
(reduce (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
-- attempt to prove the current goal without using
induction, with the indicated hints
General Form:
(reduce &rest hints)
Attempt to prove the current goal without using induction, using the
indicated hints (if any). A subgoal will be created for each goal
that would have been pushed for proof by induction in an ordinary
proof.
Notice that unlike prove, the arguments to reduce are spread out, and
are all hints.
Reduce is similar to bash in that neither of these allows induction.
But bash only allows simplification, while reduce allows processes
eliminate-destructors, fertilize, generalize, and
eliminate-irrelevance.
Remark: Induction will be used to the extent that it is ordered
explicitly in the hints.")
(ACL2-PC::REDUCE-BY-INDUCTION
(PROOF-CHECKER-COMMANDS)
"(macro) call the ACL2 prover without induction, after going into
induction
Examples:
reduce-by-induction
-- attempt to prove the current goal after going into induction,
with no further inductions
(reduce-by-induction (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
-- attempt to prove the current goal after going into induction,
with no further inductions, using the indicated hints
General Form:
(reduce-by-induction &rest hints)
A subgoal will be created for each goal that would have been pushed
for proof by induction in an ordinary proof, except that the proof
begins with a top-level induction.
Notice that unlike prove, the arguments to reduce-by-induction are
spread out, and are all hints. Also see [ACL2-pc::prove],
[ACL2-pc::reduce], and [ACL2-pc::bash].
Remark: Induction and the various processes will be used to the
extent that they are specified explicitly in the :induct and
:do-not [hints].")
(ACL2-PC::REMOVE-ABBREVIATIONS
(PROOF-CHECKER-COMMANDS)
"(primitive) remove one or more abbreviations
Examples:
remove-abbreviations -- remove all abbreviations
(remove-abbreviations v w)
-- assuming that V and W currently abbreviate
terms, then they are ``removed'' in the
sense that they are no longer considered to
abbreviate those terms
General Forms:
(remove-abbreviations &rest vars)
If vars is not empty (i.e., not nil), remove the variables in vars
from the current list of abbreviations, in the sense that each
variable in vars will no longer abbreviate a term.
Remark: The instruction fails if at least one of the arguments fails
to be a variable that abbreviates a term.
Also see [ACL2-pc::add-abbreviation] for a discussion of
abbreviations in general, and see [ACL2-pc::show-abbreviations].")
(ACL2-PC::REPEAT
(PROOF-CHECKER-COMMANDS)
"(macro) repeat the given instruction until it ``fails''
Example:
(repeat promote)
General Form:
(repeat instruction)
The given instruction is run repeatedly until it ``fails''.
Remark: There is nothing here in general to prevent the instruction
from being run after all goals have been proved, though this is
indeed the case for primitive instructions.")
(ACL2-PC::REPEAT-REC
(PROOF-CHECKER-COMMANDS)
"(macro) auxiliary to repeat
See [ACL2-pc::repeat].")
(ACL2-PC::REPLAY
(PROOF-CHECKER-COMMANDS)
"(macro) replay one or more instructions
Examples:
REPLAY -- replay all instructions in the current session
(i.e., state-stack)
(REPLAY 5) -- replay the most recent 5 instructions
(REPLAY 5
(COMMENT deleted dive command here))
-- replace the 5th most recent instruction with the
indicated comment instruction, and then replay it
followed by the remaining 4 instructions
General Form:
(REPLAY &OPTIONAL n replacement-instruction)
Replay the last n instructions if n is a positive integer; else n
should be nil or not supplied, and replay all instructions.
However, if replacement-instruction is supplied and not nil, then
before the replay, replace the nth instruction (from the most
recent, as shown by commands) with replacement-instruction.
If this command ``fails'', then the restore command will revert the
state-stack to its value present before the replay instruction was
executed.")
(ACL2-PC::RESTORE
(PROOF-CHECKER-COMMANDS)
"(meta) remove the effect of an UNDO command
Example and General Form:
restore
Restore removes the effect of an undo command. This always works as
expected if restore is invoked immediately after undo, without
intervening instructions. However, other commands may also interact
with restore, notably ``sequencing'' commands such as do-all,
do-strict, protect, and more generally, sequence.
Remark: Another way to control the saving of proof-checker state is
with the save command; see [ACL2-pc::save].
The restore command always ``succeeds''; it returns (mv nil t state).")
(ACL2-PC::RETAIN
(PROOF-CHECKER-COMMANDS)
"(atomic macro) drop all but the indicated top-level hypotheses
Example:
(RETAIN 2 3) -- keep the second and third hypotheses, and drop
the rest
General Form:
(retain &rest args)
Drop all top-level hypotheses except those with the indicated
indices.
There must be at least one argument, and all must be in range (i.e.
integers between one and the number of top-level hypotheses,
inclusive).")
(ACL2-PC::RETRIEVE
(PROOF-CHECKER-COMMANDS)
"(macro) re-enter the proof-checker
Examples:
(retrieve associativity-of-permutationp)
retrieve
General Form:
(retrieve &optional name)
Must be used from outside the interactive proof-checker loop. If name
(which must be a symbol) is supplied and not nil, this causes
re-entry to the interactive proof-checker loop in the state at
which save was last executed for the indicated name. (See
[ACL2-pc::save].) If name is nil or is not supplied, then the user
is queried regarding which proof-checker state to re-enter. The
query is omitted, however, if there only one proof-checker state is
present that was saved with save, in which case that is the one
that is used. Also see [ACL2-pc::unsave].")
(ACL2-PC::REWRITE
(PROOF-CHECKER-COMMANDS)
"(primitive) apply a rewrite rule
Examples:
(rewrite reverse-reverse)
-- apply the rewrite rule `reverse-reverse'
(rewrite (:rewrite reverse-reverse))
-- same as above
(rewrite 2)
-- apply the second rewrite rule, as displayed by show-rewrites
rewrite
-- apply the first rewrite rule, as displayed by show-rewrites
(rewrite transitivity-of-< ((y 7)))
-- apply the rewrite rule transitivity-of-< with the substitution
that associates 7 to the ``free variable'' y
(rewrite foo ((x 2) (y 3)) t)
-- apply the rewrite rule foo by substituting 2 and 3 for free
variables x and y, respectively, and also binding all other
free variables possible by using the current context
(hypotheses and governors)
General Form:
(rewrite &optional rule-id substitution instantiate-free)
Replace the current subterm with a new term by applying a [rewrite]
or [definition] rule. The replacement will be done according to the
information provided by the show-rewrites (sr) command.
If rule-id is a positive integer n, then the nth rule as displayed by
show-rewrites is the one that is applied. If rule-id is nil or is
not supplied, then it is treated as the number 1. Otherwise,
rule-id should be either a symbol or else a :rewrite or :definition
[rune]. If a symbol is supplied, then any (:rewrite or :definition)
rule of that name may be used. We say more about this, and describe
the other optional arguments, below.
Consider first the following example. Suppose that the current
subterm is (reverse (reverse y)) and that there is a [rewrite] rule
called reverse-reverse of the form
(implies (true-listp x)
(equal (reverse (reverse x)) x)) .
Then the instruction (rewrite reverse-reverse) causes the current
subterm to be replaced by y and creates a new goal with conclusion
(true-listp y). An exception is that if the top-level hypotheses
imply (true-listp y) using only ``trivial reasoning'' (more on this
below), then no new goal is created.
If the rule-id argument is a number or is not supplied, then the
system will store an instruction of the form (rewrite name ...),
where name is the name of a rewrite rule; this is in order to make
it easier to replay instructions when there have been changes to
the history. Except: instead of the name (whether the name is
supplied or calculated), the system stores the [rune] if there is
any chance of ambiguity. (Formally, ``ambiguity'' here means that
the rune being applied is of the form (:rewrite name . index),
where index is not nil.)
Speaking in general, then, a rewrite instruction works as follows:
First, a [rewrite] or [definition] rule is selected according to the
arguments of the rewrite instruction. The selection is made as
explained under ``General Form'' above.
Next, the left-hand side of the rule is matched with the current
subterm, i.e., a substitution unify-subst is found such that if one
instantiates the left-hand side of the rule with unify-subst, then
one obtains the current subterm. If this match fails, then the
instruction fails.
Next, an attempt is made to relieve (discharge) the hypotheses, much
as the theorem prover relieves hypotheses except that there is no
call to the rewriter. First, the substitution unify-subst is
extended with the substitution argument, which may bind free
variables (see [free-variables]). Each hypothesis of the rule is
then considered in turn, from first to last. For each hypothesis,
first the current substitution is applied, and then the system
checks whether the hypothesis is ``clearly'' true in the current
context. If there are variables in the hypotheses of the rule that
are not bound by the current substitution, then a weak attempt is
made to extend that substitution so that the hypothesis is present
in the current context (see [ACL2-pc::hyps]), much as would be done
by the theorem prover's rewriter.
If in the process above there are free variables (see
[free-variables]), but the proof-checker can see how to bind them
to relieve all hypotheses, then it will do so in both the
show-rewrites (sr) and rewrite commands. But normally, if even one
hypothesis remains unrelieved, then no automatic extension of the
substitution is made. Except, if instantiate-free is not nil, then
that extension to the substitution is kept. (Technical note: in the
case of an unrelieved hypothesis and a non-nil value of
instantiate-free, if a [bind-free] hypothesis produces a list of
binding alists, then the last of those alists is the one that is
used to extend the substitution.)
Finally, the instruction is applied as follows. The current subterm
is replaced by applying the final substitution described above to
the right-hand side of the selected rule. And, one new subgoal is
created for each unrelieved hypothesis of the rule, whose top-level
hypotheses are the governors and top-level hypotheses of the
current goal and whose conclusion and current subterm are the
instance, by that same final substitution, of that unrelieved
hypothesis.
Remark: The substitution argument should be a list whose elements
have the form (variable term), where term may contain
abbreviations.")
(ACL2-PC::RUN-INSTR-ON-GOAL
(PROOF-CHECKER-COMMANDS)
"(macro) auxiliary to THEN
See [ACL2-pc::then].")
(ACL2-PC::RUN-INSTR-ON-NEW-GOALS
(PROOF-CHECKER-COMMANDS)
"(macro) auxiliary to then
See [ACL2-pc::then].")
(ACL2-PC::RUNES
(PROOF-CHECKER-COMMANDS)
"(macro) print the runes (definitions, lemmas, ...) used
Examples and general forms:
(runes t) ; print all [rune]s used during this interactive proof
(runes nil) ; print all [rune]s used by the most recent command
(runes) ; same as (runes nil)
runes ; same as (runes nil)
This command does not change the [proof-checker] state. Rather, it
simply reports runes (see [rune]) that have participated in the
interactive proof.
Note that (runes nil) will show the [rune]s used by the most recent
primitive or macro command (as displayed by :comm).")
(ACL2-PC::S
(PROOF-CHECKER-COMMANDS)
"(primitive) simplify the current subterm
Examples:
S -- simplify the current subterm
(S :backchain-limit 2 :normalize t :expand (append x z))
-- simplify the current subterm, but during the rewriting
process first ``normalize'' it by pushing IFs to the
top-level, and also force the term (append x z) to be
expanded during the rewriting process
General Form:
(s &key rewrite normalize backchain-limit repeat in-theory hands-off
expand)
Simplify the current subterm according to the keyword parameters
supplied. First if-normalization is applied (unless the normalize
argument is nil), i.e., each subterm of the form (f ... (if test x
y) ...) is replaced by the term (if test (f ... x ...) (f ... y
...)) except, of course, when f is if and the indicated if subterm
is in the second or third argument position. Then rewriting is
applied (unless the rewrite argument is nil). Finally this pair of
actions is repeated --- until the rewriting step causes no change
in the term. A description of each parameter follows.
:rewrite -- default t
When non-nil, instructs the system to use ACL2's rewriter (or,
something close to it) during simplification.
:normalize -- default t
When non-nil, instructs the system to use if-normalization (as
described above) during simplification.
:backchain-limit -- default 0
Sets the number of recursive calls to the rewriter that are allowed
for backchaining. Even with the default of 0, some reasoning is
allowed (technically speaking, type-set reasoning is allowed) in
the relieving of hypotheses. The value should be nil or a
non-negative integer, and limits backchaining only for rewriting,
not for type-set reasoning.
:repeat -- default 0
Sets the number of times the current term is to be rewritten. If this
value is t, then the default is used (as specified by the constant
*default-s-repeat-limit*).
:in-theory, :hands-off, :expand
These have their usual meaning; see [hints].
Remark: if conditional rewrite rules are used that cause case splits
because of the use of force, then appropriate new subgoals will be
created, i.e., with the same current subterm (and address) but with
each new (forced) hypothesis being negated and then used to create
a corresponding new subgoal. In that case, the current goal will
have all such new hypotheses added to the list of top-level
hypotheses.")
(ACL2-PC::S-PROP
(PROOF-CHECKER-COMMANDS)
"(atomic macro) simplify propositionally
Example:
s-prop
General Form:
(s-prop &rest names)
Simplify, using the default settings for s (which include
if-normalization and rewriting without real backchaining), but with
respect to a theory in which only basic functions and rules (the
ones in (theory 'minimal-theory)), together with the names (or
parenthesized names) in the &rest argument names, are enabled.
Also see [ACL2-pc::s].")
(ACL2-PC::SAVE
(PROOF-CHECKER-COMMANDS)
"(macro) save the proof-checker state (state-stack)
Example:
(save lemma3-attempt)
General Form:
(save &optional name do-it-flg)
Saves the current proof-checker state by ``associating'' it with the
given name, which must be a symbol. Submit (retrieve name) to Lisp
to get back to this proof-checker state. If verify was originally
supplied with an event name, then the argument can be omitted in
favor of that name as the default.
Remark that if a save has already been done with the indicated name
(or the default event name), then the user will be queried
regarding whether to go ahead with the save --- except, if
do-it-flg is supplied and not nil, then there will be no query and
the save will be effected.
Also see [ACL2-pc::retrieve] and [ACL2-pc::unsave].")
(ACL2-PC::SEQUENCE
(PROOF-CHECKER-COMMANDS)
"(meta) run the given list of instructions according to a multitude of
options
Example:
(sequence (induct p prove) t)
This is a very general command that is used to define other
sequencing commands; see [ACL2-pc::do-all], [ACL2-pc::do-strict],
[ACL2-pc::protect], and [ACL2-pc::succeed].
General Form:
(sequence
instruction-list
&optional
strict-flg protect-flg success-expr no-prompt-flg no-restore-flg)
Each instruction in the list instruction-list is run, and the
instruction ``succeeds'' if every instruction in instruction-list
``succeeds''. However, it might ``succeed'' even if some
instructions in the list ``fail''; more generally, the various
arguments control a number of aspects of the running of the
instructions. All this is explained in the paragraphs below. First
we embark on a general discussion of the instruction interpreter,
including the notions of ``succeed'' and ``fail''.
Remark: The arguments are not evaluated, except (in a sense) for
success-expr, as described below.
Each primitive and meta instruction can be thought of as returning an
[error-triple], say (erp val state). An instruction (primitive or
meta) ``succeeds'' if erp is nil and val is not nil; otherwise it
``fails''. (When we use the words ``succeed'' or ``fail'' in this
technical sense, we'll always include them in double quotes.) If an
instruction ``fails,'' we say that that the failure is ``soft'' if
erp is nil; otherwise the failure is ``hard''. The sequence command
gives the user control over how to treat ``success'' and
``failure'' when sequencing instructions, though we have created a
number of handy macro commands for this purpose, notably do-all,
do-strict and protect.
Here is precisely what happens when a sequence instruction is run.
The instruction interpreter is run on the instructions supplied in
the argument instruction-list (in order). The interpreter halts the
first time there is a hard ``failure.'' except that if strict-flg
is supplied and not nil, then the interpreter halts the first time
there is any ``failure.'' The error triple (erp val state) returned
by the sequence instruction is the triple returned by the last
instruction executed (or, the triple (nil t state) if
instruction-list is nil), except for the following provision. If
success-expr is supplied and not nil, then it is evaluated with the
state global variables pc-erp and pc-val (in the \"ACL2\" package)
bound to the corresponding components of the error triple returned
(as described above). At least two values should be returned, and
the first two of these will be substituted for erp and val in the
triple finally returned by sequence. For example, if success-expr
is (mv erp val), then no change will be made to the error triple,
and if instead it is (mv nil t), then the sequence instruction will
``succeed''.
That concludes the description of the error triple returned by a
sequence instruction, but it remains to explain the effects of the
arguments protect-flg and no-prompt-flg.
If protect-flg is supplied and not nil and if also the instruction
``fails'' (i.e., the error component of the triple is not nil or
the value component is nil), then the state is reverted so that the
proof-checker's state (including the behavior of restore) is set
back to what it was before the sequence instruction was executed.
Otherwise, unless no-restore-flg is set, the state is changed so
that the restore command will now undo the effect of this sequence
instruction (even if there were nested calls to sequence).
Finally, as each instruction in instruction-list is executed, the
prompt and that instruction will be printed, unless the global
state variable pc-print-prompt-and-instr-flg is unbound or nil and
the parameter no-prompt-flg is supplied and not nil.")
(ACL2-PC::SHOW-ABBREVIATIONS
(PROOF-CHECKER-COMMANDS)
"(macro) display the current abbreviations
Examples:
(show-abbreviations v w)
-- assuming that v and w currently abbreviate terms,
then this instruction displays them together with
the terms they abbreviate
show-abbreviations
-- display all abbreviations
Also see [ACL2-pc::add-abbreviation] for a general discussion of
abbreviations and see [ACL2-pc::remove-abbreviations].
General Form:
(show-abbreviations &rest vars)
Display each argument in vars together with the term it abbreviates
(if any). If there are no arguments, i.e. the instruction is simply
show-abbreviations, then display all abbreviations together with
the terms they abbreviate.
If the term abbreviated by a variable, say v, contains a proper
subterm that is also abbreviate by (another) variable, then both
the unabbreviated term and the abbreviated term (but not using (?
v) to abbreviate the term) are displayed with together with v.")
(ACL2-PC::SHOW-LINEARS
(PROOF-CHECKER-COMMANDS)
"(macro) display the applicable [linear] rules
Example:
show-linears
General Form:
(show-linears &optional rule-id enabled-only-flg)
This command displays [linear] rules with a trigger term that matches
the current subterm, and shows how they can be applied. This
command is analogous to the show-rewrites [proof-checker] command;
see [ACL2-pc::show-rewrites]. Also see [ACL2-pc::apply-linear] for
how to apply [linear] rules.")
(ACL2-PC::SHOW-REWRITES
(PROOF-CHECKER-COMMANDS)
"(macro) display the applicable [rewrite] rules
Example:
show-rewrites
General Form:
(show-rewrites &optional rule-id enabled-only-flg)
This command displays [rewrite] rules whose left-hand side matches
the current subterm, and shows how that command can be applied. For
each rule displayed, hypotheses are shown that would need to be
proved after the rule is applied. Note that hypotheses are omitted
from the display when the system can trivially verify that they
hold; to see all hypotheses for each rule in a display that is
independent of the arguments of the current subterm, use the pl or
pr command.
Here are details on the arguments and the output. If rule-id is
supplied and is a name (non-nil symbol) or a :[rewrite] or
:[definition] [rune], then only the corresponding rewrite rule(s)
will be displayed, while if rule-id is a positive integer n, then
only the nth rule that would be in the list is displayed. In each
case, the display will point out when a rule is currently disabled
(in the interactive environment), except that if enabled-only-flg
is supplied and not nil, then disabled rules will not be displayed
at all. Finally, among the free variables of any rule (see
[free-variables]), those that would remain free if the rule were
applied will be displayed. Also see [rewrite].")
(ACL2-PC::SHOW-TYPE-PRESCRIPTIONS
(PROOF-CHECKER-COMMANDS)
"(macro) display the applicable [type-prescription] rules
Example:
show-type-prescriptions
General Form:
(show-type-prescriptions &optional rule-id)
Display [type-prescription] rules that apply to the current subterm.
If rule-id is supplied and is a name (non-nil symbol) or a
:[rewrite] or :[definition] [rune], then only the corresponding
rewrite rule(s) will be displayed. In each case, the display will
point out when a rule is currently disabled (in the interactive
environment). Also see [type-prescription].")
(ACL2-PC::SKIP
(PROOF-CHECKER-COMMANDS)
"(macro) ``succeed'' without doing anything
Example and General Form:
skip
Make no change in the state-stack, but ``succeed''. Same as (sequence
nil).")
(ACL2-PC::SL
(PROOF-CHECKER-COMMANDS)
"(atomic macro) simplify with lemmas
Examples:
sl
(sl 3)
General Form:
(sl &optional backchain-limit)
Simplify, but with all function definitions disabled (see
[function-theory] in the top-level ACL2 loop), except for a few
basic functions (the ones in (theory 'minimal-theory)). The
backchain-limit has a default of 0, but if is supplied and not nil,
then it should be a nonnegative integer; see [ACL2-pc::s].
WARNING: This command completely ignores in-theory commands that are
executed inside the [proof-checker].")
(ACL2-PC::SLS
(PROOF-CHECKER-COMMANDS)
"(macro) same as SHOW-LINEARS
Example:
sls
General Form:
(sls &optional rule-id enabled-only-flg)
See show-linears. NOTE: In analogy to the sr abbreviation for
show-rewrites, one might expect this command to be sl; but that
name was taken (``simplify with lemmas'') before sls was
implemented.")
(ACL2-PC::SPLIT
(PROOF-CHECKER-COMMANDS)
"(atomic macro) split the current goal into cases
Example:
split
For example, if the current goal has one hypothesis (or x y) and a
conclusion of (and a b), then split will create four new goals:
one with hypothesis X and conclusion A
one with hypothesis X and conclusion B
one with hypothesis Y and conclusion A
one with hypothesis Y and conclusion B.
General Form:
SPLIT
Replace the current goal by subgoals whose conjunction is equivalent
(primarily by propositional reasoning) to the original goal, where
each such goal cannot be similarly split.
Remark: The new goals will all have their hypotheses promoted; in
particular, no conclusion will have a top function symbol of
implies. Also note that split will fail if there is exactly one new
goal created and it is the same as the existing current goal.
The way split really works is to call the ACL2 theorem prover with
only simplification (and preprocessing) turned on, and with only a
few built-in functions (especially, propositional ones) enabled,
namely, the ones in the list (theory 'minimal-theory). However,
because the prover is called, type-set reasoning can be used to
eliminate some cases. For example, if (true-listp x) is in the
hypotheses, then probably (true-listp (cdr x)) will be reduced to
t.")
(ACL2-PC::SR
(PROOF-CHECKER-COMMANDS)
"(macro) same as SHOW-REWRITES
Example:
sr
General Form:
(sr &optional rule-id enabled-only-flg)
See [ACL2-pc::show-rewrites].")
(ACL2-PC::ST
(PROOF-CHECKER-COMMANDS)
"(macro) same as SHOW-TYPE-PRESCRIPTIONS
Example:
sr
General Form:
(st &optional rule-id)
See [ACL2-pc::show-type-prescriptions].")
(ACL2-PC::SUCCEED
(PROOF-CHECKER-COMMANDS)
"(macro) run the given instructions, and ``succeed''
Example:
(succeed induct p prove)
General Form:
(succeed &rest instruction-list)
Run the indicated instructions until there is a hard ``failure'', and
``succeed''. (See [ACL2-pc::sequence] for an explanation of
``success'' and ``failure''.)")
(ACL2-PC::TH
(PROOF-CHECKER-COMMANDS)
"(macro) print the top-level hypotheses and the current subterm
Examples:
th -- print all (top-level) hypotheses and the current
subterm
(th (1 3) (2 4)) -- print hypotheses 1 and 3 and governors 2 and 4,
and the current subterm
(th (1 3) t) -- print hypotheses 1 and 3 and all governors, and
the current subterm
General Form:
(th &optional hyps-indices govs-indices)
Print hypotheses and the current subterm. The printing of hypotheses
(and perhaps governors) are controlled as in the hyps command; see
[ACL2-pc::hyps].
Historical note: The name th is adapted from the Gypsy Verification
Environment, where th abbreviates the command theorem, which says
to print information on the current goal.")
(ACL2-PC::THEN
(PROOF-CHECKER-COMMANDS)
"(macro) apply one instruction to current goal and another to new
subgoals
Example:
(then induct prove)
General Form:
(then first-instruction &optional completion must-succeed-flg)
Run first-instruction, and then run completion (another instruction)
on each subgoal created by first-instruction. If must-succeed-flg
is supplied and not nil, then halt at the first ``failure'' and
remove the effects of the invocation of completion that ``failed''.
The default for completion is reduce.")
(ACL2-PC::TOP
(PROOF-CHECKER-COMMANDS)
"(atomic macro) move to the top of the goal
Example and General Form:
top
For example, if the conclusion is (= x (* (- y) z)) and the current
subterm is y, then after executing top, the current subterm will be
the same as the conclusion, i.e., (= x (* (- y) z)).
Top is the same as (up n), where n is the number of times one needs
to execute up in order to get to the top of the conclusion. The top
command fails if one is already at the top of the conclusion.
Also see [ACL2-pc::up], [ACL2-pc::dive], [ACL2-pc::nx], and
[ACL2-pc::bk].")
(ACL2-PC::TYPE-ALIST
(PROOF-CHECKER-COMMANDS)
"(macro) display the [type-alist] from the current context
Examples:
(type-alist t t) ; display type-alist based on conclusion and governors
(type-alist t t t) ; as above, but also display forward-chaining report
type-alist ; same as (type-alist nil t) -- governors only
(type-alist nil) ; same as (type-alist nil t) -- governors only
(type-alist t) ; same as (type-alist t nil) -- conclusion only
(type-alist nil nil) ; display type-alist without considering
; conclusion or governors
General Form:
(type-alist &optional concl-flg govs-flg fc-report-flg)
where if govs-flg is omitted then it defaults to (not concl-flg), and
concl-flg and fc-report-flg default to nil.
Display the current assumptions as a [type-alist]. Note that this
display includes the result of forward chaining. When fc-report-flg
is supplied a non-nil value, the display also includes a
forward-chaining report; otherwise,the presence or absence of such
a report is controlled by the usual global settings (see
[forward-chaining-reports]).
There are two basic reasons contemplated for using this command.
1. The theorem prover has failed (either outside the proof-checker or
using a proof-checker command such as bash or reduce and you want
to debug by getting an idea of what the prover knows about the
context.
a. You really are interested in the context for the current term.
Include hypotheses and governors (i.e., accounting for tests of
surrounding if-expressions that must be true or false) but not
the current conclusion (which the theorem prover's heuristics
would generally ignore for contextual information). Command:
(type-alist nil t) ; equivalently, type-alist or (type-alist nil)
b. You are not thinking in particular about the current term; you
just want to get an idea of the context that the prover would
build at the top-level, for forward-chaining. Incorporate the
conclusion but not the governors. Command:
(type-alist t nil) ; equivalently, (type-alist t)
2. You intend to use one of the [proof-checker-commands] that does
simplification, such as s or x, and you want to see the context.
Then include the surrounding if-term governors but not the goal's
conclusion. Command:
(type-alist nil t) ; equivalently, type-alist or (type-alist nil)
See [type-set] (also see [type-prescription]) for information about
ACL2's type system, which can assist in understanding the output of
the type-alist command.")
(ACL2-PC::UNDO
(PROOF-CHECKER-COMMANDS)
"(meta) undo some instructions
Examples:
(undo 7)
undo
General Forms:
(undo n) -- Undo the last n instructions. The argument n should be
a positive integer.
undo -- Same as (undo 1).
Remark: To remove the effect of an undo command, use restore; see
[ACL2-pc::restore].
Remark: If the argument n is greater than the total number of
interactive instructions in the current session, then (undo n) will
simply take you back to the start of the session.
The undo meta command always ``succeeds''; it returns (mv nil t
state) unless its optional argument is supplied and of the wrong
type (i.e. not a positive integer) or there are no instructions to
undo.")
(ACL2-PC::UNSAVE
(PROOF-CHECKER-COMMANDS)
"(macro) remove a proof-checker state
Example:
(unsave assoc-of-append)
General Form:
(unsave &optional name)
Eliminates the association of a proof-checker state with name, if
name is supplied and not nil. The name may be nil or not supplied,
in which case it defaults to the event name supplied with the
original call to verify (if there is one --- otherwise, the
instruction ``fails'' and there is no change). The ACL2 function
unsave may also be executed outside the interactive loop, with the
same syntax.
Also see [ACL2-pc::save] and [ACL2-pc::retrieve].")
(ACL2-PC::UP
(PROOF-CHECKER-COMMANDS)
"(primitive) move to the parent (or some ancestor) of the current
subterm
Examples: if the conclusion is (= x (* (- y) z)) and the
current subterm is y, then we have:
up or (up 1) -- the current subterm becomes (- y)
(up 2) -- the current subterm becomes (* (- y) z)
(up 3) -- the current subterm becomes the entire conclusion
(up 4) -- no change; can't go up that many levels
General Form:
(up &optional n)
Move up n levels in the conclusion from the current subterm, where n
is a positive integer. If n is not supplied or is nil, then move up
one level, i.e., treat the instruction as (up 1).
Also see [ACL2-pc::dive], [ACL2-pc::top], [ACL2-pc::nx], and
[ACL2-pc::bk].")
(ACL2-PC::USE
(PROOF-CHECKER-COMMANDS)
"(atomic macro) use a lemma instance
Example:
(USE true-listp-append
(:instance assoc-of-append (x a) (y b) (z c)))
-- Add two top-level hypotheses, one the lemma called
true-listp-append, and the other an instance of the lemma called
assoc-of-append by the substitution in which x is assigned a, y
is assigned b, and z is assigned c.
General Form:
(use &rest args)
Add the given lemma instances to the list of top-level hypotheses.
See [hints] for the syntax of :use hints in defthm, which is
essentially the same as the syntax here (see the example above).
This command calls the prove command, and hence should only be used
at the top of the conclusion.")
(ACL2-PC::WRAP
(PROOF-CHECKER-COMMANDS)
"(atomic macro) execute the indicated instructions and combine all the
new goals
Example:
(wrap induct) ; induct, then replace first new goal by the conjunction of all
; the new goals, and drop all new goals after the first
General Form:
(wrap &rest instrs)
First the instructions in instrs are executed, as in do-all. If this
``fails'' then no additional action is taken. Otherwise, the
current goal after execution of instrs is conjoined with all
``new'' goals, in the sense that their names are not among the
names of goals at the time instrs was begun. This conjunction
becomes the new current goal and those ``new'' goals are dropped.
See the code for the [proof-checker] command wrap-induct for an
example of the use of wrap.")
(ACL2-PC::WRAP-INDUCT
(PROOF-CHECKER-COMMANDS)
"(atomic macro) same as induct, but create a single goal
Examples:
wrap-induct
(wrap-induct t)
(wrap-induct (append (reverse x) y))
General Form:
(wrap-induct &optional term)
The wrap-induct command is identical to the [proof-checker] induct
command (see [ACL2-pc::induct]), except that only a single goal is
created: the conjunction of the base and induction steps.
Note: The output will generally indicate that more than goal has been
created, e.g.:
Creating two new goals: (MAIN . 1) and (MAIN . 2).
However, wrap-induct always creates a unique goal (when it succeeds).
A subsequent message clarifies this, for example:
NOTE: Created ONLY one new goal, which is the current goal:
(MAIN . 1)")
(ACL2-PC::WRAP1
(PROOF-CHECKER-COMMANDS)
"(primitive) combine goals into a single goal
Examples:
; Keep (main . 1) and (main . 2) if they exist, as well as the current goal;
; and for each other goal, conjoin it into the current goal and delete it:
(wrap1 ((main . 1) (main . 2)))
; As explained below, conjoin all subsequent siblings of the current goal
; into the current goal, and then delete them:
(wrap1)
General Form:
(wrap1 &optional kept-goal-names)
If kept-goal-names is not nil, the current goal is replaced by
conjoining it with all goals other than the current goal and those
indicated by kept-goal-names, and those other goals are deleted. If
kept-goal-names is omitted, then the the current goal must be of
the form (name . n), and the goals to conjoin into the current goal
(and delete) are those with names of the form (name . k) for k >=
n.
NOTE: Wrap1 always ``succeeds'', even if there are no other goals to
conjoin into the current goal (a message is printed in that case),
and it always leaves you with no hypotheses at the top of the
current goal's conclusion (as though top and demote had been
executed, if necessary).
Also see [ACL2-pc::wrap].")
(ACL2-PC::X
(PROOF-CHECKER-COMMANDS)
"(atomic macro) expand and (maybe) simplify function call at the
current subterm
Examples:
x -- expand and simplify.
Also see [ACL2-pc::expand] and see [ACL2-pc::x-dumb], which do not
perform simplification.
For example, if the current subterm is (append a b), then after x the
current subterm will probably be (cons (car a) (append (cdr a) b))
if (consp a) and (true-listp a) are among the top-level hypotheses
and governors. If there are no top-level hypotheses and governors,
then after x the current subterm will probably be:
(if (true-listp x)
(if x
(cons (car x) (append (cdr x) y))
y)
(apply 'binary-append (list x y))).
General Form:
(X &key
rewrite normalize backchain-limit in-theory hands-off expand)
Expand the function call at the current subterm, and simplify using
the same conventions as with the s command (see [ACL2-pc::s]).
Unlike s, it is permitted to set both :rewrite and :normalize to nil,
which will result in no simplification; see [ACL2-pc::x-dumb].
Remark (obscure): On rare occasions the current address may be
affected by the use of x. For example, suppose we have the
definition
(defun g (x) (if (consp x) x 3))
and then we enter the proof-checker with
(verify (if (integerp x) (equal (g x) 3) t)) .
Then after invoking the instruction (dive 2 1), so that the current
subterm is (g x), followed by the instruction x, we would expect
the conclusion to be (if (integerp x) (equal 3 3) t). However, the
system actually replaces (equal 3 3) with t (because we use the
ACL2 term-forming primitives), and hence the conclusion is actually
(if (integerp x) t t). Therefore, the current address is put at (2)
rather than (2 1). In such cases, a warning ``NOTE'' will be
printed to the terminal.
The other primitive commands to which the above ``truncation'' note
applies are equiv, rewrite, and s.")
(ACL2-PC::X-DUMB
(PROOF-CHECKER-COMMANDS)
"(atomic macro) expand function call at the current subterm, without
simplifying
General Form:
x-dumb: expand without simplification.
Same as (expand t). See [ACL2-pc::expand].
Also see [ACL2-pc::x], which performs simplification."))
)
|