1 # bend-mathlib/bool.bend: Bool algebra (not, and, or, xor). 2 import Base 3 4 # Negating a boolean twice gives it back. 5 law not_not: 6 for b: Bool 7 {Bool.not(Bool.not(b)) == b : Bool} 8 9 def not_not(b): 10 match b: 11 case True{}: 12 {==} 13 case False{}: 14 {==} 15 16 # Boolean and is commutative. 17 law and_comm: 18 for a: Bool 19 for b: Bool 20 {Bool.and(a, b) == Bool.and(b, a) : Bool} 21 22 def and_comm(a, b): 23 match a b: 24 case True{} True{}: 25 {==} 26 case True{} False{}: 27 {==} 28 case False{} True{}: 29 {==} 30 case False{} False{}: 31 {==} 32 33 # Boolean or is commutative. 34 law or_comm: 35 for a: Bool 36 for b: Bool 37 {Bool.or(a, b) == Bool.or(b, a) : Bool} 38 39 def or_comm(a, b): 40 match a b: 41 case True{} True{}: 42 {==} 43 case True{} False{}: 44 {==} 45 case False{} True{}: 46 {==} 47 case False{} False{}: 48 {==} 49 50 # Boolean and is associative. 51 law and_assoc: 52 for a: Bool 53 for -b: Bool 54 for -c: Bool 55 {Bool.and(Bool.and(a, b), c) == Bool.and(a, Bool.and(b, c)) : Bool} 56 57 def and_assoc(a, b, c): 58 match a: 59 case True{}: 60 {==} 61 case False{}: 62 {==} 63 64 # Boolean or is associative. 65 law or_assoc: 66 for a: Bool 67 for -b: Bool 68 for -c: Bool 69 {Bool.or(Bool.or(a, b), c) == Bool.or(a, Bool.or(b, c)) : Bool} 70 71 def or_assoc(a, b, c): 72 match a: 73 case True{}: 74 {==} 75 case False{}: 76 {==} 77 78 # True is a right identity for and: a and true is a. 79 law and_true: 80 for a: Bool 81 {Bool.and(a, True{}) == a : Bool} 82 83 def and_true(a): 84 match a: 85 case True{}: 86 {==} 87 case False{}: 88 {==} 89 90 # True is a left identity for and: true and a is a. 91 law true_and: 92 for -a: Bool 93 {Bool.and(True{}, a) == a : Bool} 94 95 def true_and(a): 96 {==} 97 98 # False absorbs and on the right: a and false is false. 99 law and_false: 100 for a: Bool 101 {Bool.and(a, False{}) == False{} : Bool} 102 103 def and_false(a): 104 match a: 105 case True{}: 106 {==} 107 case False{}: 108 {==} 109 110 # False absorbs and on the left: false and a is false. 111 law false_and: 112 for -a: Bool 113 {Bool.and(False{}, a) == False{} : Bool} 114 115 def false_and(a): 116 {==} 117 118 # False is a right identity for or: a or false is a. 119 law or_false: 120 for a: Bool 121 {Bool.or(a, False{}) == a : Bool} 122 123 def or_false(a): 124 match a: 125 case True{}: 126 {==} 127 case False{}: 128 {==} 129 130 # False is a left identity for or: false or a is a. 131 law false_or: 132 for -a: Bool 133 {Bool.or(False{}, a) == a : Bool} 134 135 def false_or(a): 136 {==} 137 138 # True absorbs or on the right: a or true is true. 139 law or_true: 140 for a: Bool 141 {Bool.or(a, True{}) == True{} : Bool} 142 143 def or_true(a): 144 match a: 145 case True{}: 146 {==} 147 case False{}: 148 {==} 149 150 # True absorbs or on the left: true or a is true. 151 law true_or: 152 for -a: Bool 153 {Bool.or(True{}, a) == True{} : Bool} 154 155 def true_or(a): 156 {==} 157 158 # De Morgan: not (a and b) is (not a) or (not b). 159 law de_morgan_and: 160 for a: Bool 161 for -b: Bool 162 {Bool.not(Bool.and(a, b)) == Bool.or(Bool.not(a), Bool.not(b)) : Bool} 163 164 def de_morgan_and(a, b): 165 match a: 166 case True{}: 167 {==} 168 case False{}: 169 {==} 170 171 # De Morgan: not (a or b) is (not a) and (not b). 172 law de_morgan_or: 173 for a: Bool 174 for -b: Bool 175 {Bool.not(Bool.or(a, b)) == Bool.and(Bool.not(a), Bool.not(b)) : Bool} 176 177 def de_morgan_or(a, b): 178 match a: 179 case True{}: 180 {==} 181 case False{}: 182 {==} 183 184 def internal_true_ne_false(e: {True{} == False{} : Bool}) -> Empty: 185 %e : Bool.pick(Type, _, Unit, Empty) 186 Unit{} 187 188 # True and False are different booleans. 189 law true_ne_false: 190 {True{} != False{} : Bool} 191 192 def true_ne_false(): 193 e => internal_true_ne_false(e) 194 195 # And with itself: a and a is a. 196 law and_self: 197 for a: Bool 198 {Bool.and(a, a) == a : Bool} 199 200 def and_self(a): 201 match a: 202 case True{}: 203 {==} 204 case False{}: 205 {==} 206 207 # Or with itself: a or a is a. 208 law or_self: 209 for a: Bool 210 {Bool.or(a, a) == a : Bool} 211 212 def or_self(a): 213 match a: 214 case True{}: 215 {==} 216 case False{}: 217 {==} 218 219 # A boolean and its negation are never both true: a and (not a) is false. 220 law and_not_self: 221 for a: Bool 222 {Bool.and(a, Bool.not(a)) == False{} : Bool} 223 224 def and_not_self(a): 225 match a: 226 case True{}: 227 {==} 228 case False{}: 229 {==} 230 231 # A boolean or its negation is always true: a or (not a) is true. 232 law or_not_self: 233 for a: Bool 234 {Bool.or(a, Bool.not(a)) == True{} : Bool} 235 236 def or_not_self(a): 237 match a: 238 case True{}: 239 {==} 240 case False{}: 241 {==} 242 243 # And distributes over or: a and (b or c) is (a and b) or (a and c). 244 law and_or_distrib_left: 245 for a: Bool 246 for -b: Bool 247 for -c: Bool 248 {Bool.and(a, Bool.or(b, c)) == Bool.or(Bool.and(a, b), Bool.and(a, c)) : Bool} 249 250 def and_or_distrib_left(a, b, c): 251 match a: 252 case True{}: 253 {==} 254 case False{}: 255 {==} 256 257 # Or distributes over and: a or (b and c) is (a or b) and (a or c). 258 law or_and_distrib_left: 259 for a: Bool 260 for -b: Bool 261 for -c: Bool 262 {Bool.or(a, Bool.and(b, c)) == Bool.and(Bool.or(a, b), Bool.or(a, c)) : Bool} 263 264 def or_and_distrib_left(a, b, c): 265 match a: 266 case True{}: 267 {==} 268 case False{}: 269 {==} 270 271 # Absorption: a and (a or b) is a. 272 law and_or_absorb: 273 for a: Bool 274 for -b: Bool 275 {Bool.and(a, Bool.or(a, b)) == a : Bool} 276 277 def and_or_absorb(a, b): 278 match a: 279 case True{}: 280 {==} 281 case False{}: 282 {==} 283 284 # Absorption: a or (a and b) is a. 285 law or_and_absorb: 286 for a: Bool 287 for -b: Bool 288 {Bool.or(a, Bool.and(a, b)) == a : Bool} 289 290 def or_and_absorb(a, b): 291 match a: 292 case True{}: 293 {==} 294 case False{}: 295 {==} 296 297 # Exclusive or is commutative. 298 law xor_comm: 299 for a: Bool 300 for b: Bool 301 {Bool.xor(a, b) == Bool.xor(b, a) : Bool} 302 303 def xor_comm(a, b): 304 match a b: 305 case True{} True{}: 306 {==} 307 case True{} False{}: 308 {==} 309 case False{} True{}: 310 {==} 311 case False{} False{}: 312 {==} 313 314 # Exclusive or is associative. 315 law xor_assoc: 316 for a: Bool 317 for b: Bool 318 for c: Bool 319 {Bool.xor(Bool.xor(a, b), c) == Bool.xor(a, Bool.xor(b, c)) : Bool} 320 321 def xor_assoc(a, b, c): 322 match a b c: 323 case True{} True{} True{}: 324 {==} 325 case True{} True{} False{}: 326 {==} 327 case True{} False{} True{}: 328 {==} 329 case True{} False{} False{}: 330 {==} 331 case False{} True{} True{}: 332 {==} 333 case False{} True{} False{}: 334 {==} 335 case False{} False{} True{}: 336 {==} 337 case False{} False{} False{}: 338 {==} 339 340 # A boolean xor itself is false. 341 law xor_self: 342 for a: Bool 343 {Bool.xor(a, a) == False{} : Bool} 344 345 def xor_self(a): 346 match a: 347 case True{}: 348 {==} 349 case False{}: 350 {==} 351 352 # False is an identity for xor: a xor false is a. 353 law xor_false: 354 for a: Bool 355 {Bool.xor(a, False{}) == a : Bool} 356 357 def xor_false(a): 358 match a: 359 case True{}: 360 {==} 361 case False{}: 362 {==} 363 364 # Xor with true negates: a xor true is not a. 365 law xor_true: 366 for a: Bool 367 {Bool.xor(a, True{}) == Bool.not(a) : Bool} 368 369 def xor_true(a): 370 match a: 371 case True{}: 372 {==} 373 case False{}: 374 {==} 375 376 # Negation is injective: not a = not b implies a = b. 377 law not_inj: 378 for a: Bool 379 for b: Bool 380 for h: {Bool.not(a) == Bool.not(b) : Bool} 381 {a == b : Bool} 382 383 def not_inj(a, b, h): 384 match a b: 385 case True{} True{}: 386 {==} 387 case True{} False{}: 388 Empty.absurd({True{} == False{} : Bool}, internal_true_ne_false(Equal.sym(Bool, False{}, True{}, h))) 389 case False{} True{}: 390 Empty.absurd({False{} == True{} : Bool}, internal_true_ne_false(h)) 391 case False{} False{}: 392 {==} 393 394 # A boolean that is not false is true. 395 law eq_true_of_ne_false: 396 for a: Bool 397 for h: {a == False{} : Bool} -> Empty 398 {a == True{} : Bool} 399 400 def eq_true_of_ne_false(a, h): 401 match a: 402 case True{}: 403 {==} 404 case False{}: 405 Empty.absurd({False{} == True{} : Bool}, h({==})) 406 407 # --- generated: _sym twins (tools/mathlib/twins.ts), do not edit --- 408 409 # Negating a boolean twice gives it back, reversed to rewrite toward the simple side. 410 law not_not_sym: 411 for b: Bool 412 {b == Bool.not(Bool.not(b)) : Bool} 413 414 def not_not_sym(b): 415 Equal.sym(Bool, Bool.not(Bool.not(b)), b, not_not(b)) 416 417 # Boolean and is commutative, reversed to rewrite toward the simple side. 418 law and_comm_sym: 419 for a: Bool 420 for b: Bool 421 {Bool.and(b, a) == Bool.and(a, b) : Bool} 422 423 def and_comm_sym(a, b): 424 Equal.sym(Bool, Bool.and(a, b), Bool.and(b, a), and_comm(a, b)) 425 426 # Boolean or is commutative, reversed to rewrite toward the simple side. 427 law or_comm_sym: 428 for a: Bool 429 for b: Bool 430 {Bool.or(b, a) == Bool.or(a, b) : Bool} 431 432 def or_comm_sym(a, b): 433 Equal.sym(Bool, Bool.or(a, b), Bool.or(b, a), or_comm(a, b)) 434 435 # Boolean and is associative, reversed to rewrite toward the simple side. 436 law and_assoc_sym: 437 for a: Bool 438 for -b: Bool 439 for -c: Bool 440 {Bool.and(a, Bool.and(b, c)) == Bool.and(Bool.and(a, b), c) : Bool} 441 442 def and_assoc_sym(a, b, c): 443 Equal.sym(Bool, Bool.and(Bool.and(a, b), c), Bool.and(a, Bool.and(b, c)), and_assoc(a, b, c)) 444 445 # Boolean or is associative, reversed to rewrite toward the simple side. 446 law or_assoc_sym: 447 for a: Bool 448 for -b: Bool 449 for -c: Bool 450 {Bool.or(a, Bool.or(b, c)) == Bool.or(Bool.or(a, b), c) : Bool} 451 452 def or_assoc_sym(a, b, c): 453 Equal.sym(Bool, Bool.or(Bool.or(a, b), c), Bool.or(a, Bool.or(b, c)), or_assoc(a, b, c)) 454 455 # True is a right identity for and: a and true is a, reversed to rewrite toward the simple side. 456 law and_true_sym: 457 for a: Bool 458 {a == Bool.and(a, True{}) : Bool} 459 460 def and_true_sym(a): 461 Equal.sym(Bool, Bool.and(a, True{}), a, and_true(a)) 462 463 # True is a left identity for and: true and a is a, reversed to rewrite toward the simple side. 464 law true_and_sym: 465 for -a: Bool 466 {a == Bool.and(True{}, a) : Bool} 467 468 def true_and_sym(a): 469 Equal.sym(Bool, Bool.and(True{}, a), a, true_and(a)) 470 471 # False absorbs and on the right: a and false is false, reversed to rewrite toward the simple side. 472 law and_false_sym: 473 for a: Bool 474 {False{} == Bool.and(a, False{}) : Bool} 475 476 def and_false_sym(a): 477 Equal.sym(Bool, Bool.and(a, False{}), False{}, and_false(a)) 478 479 # False absorbs and on the left: false and a is false, reversed to rewrite toward the simple side. 480 law false_and_sym: 481 for -a: Bool 482 {False{} == Bool.and(False{}, a) : Bool} 483 484 def false_and_sym(a): 485 Equal.sym(Bool, Bool.and(False{}, a), False{}, false_and(a)) 486 487 # False is a right identity for or: a or false is a, reversed to rewrite toward the simple side. 488 law or_false_sym: 489 for a: Bool 490 {a == Bool.or(a, False{}) : Bool} 491 492 def or_false_sym(a): 493 Equal.sym(Bool, Bool.or(a, False{}), a, or_false(a)) 494 495 # False is a left identity for or: false or a is a, reversed to rewrite toward the simple side. 496 law false_or_sym: 497 for -a: Bool 498 {a == Bool.or(False{}, a) : Bool} 499 500 def false_or_sym(a): 501 Equal.sym(Bool, Bool.or(False{}, a), a, false_or(a)) 502 503 # True absorbs or on the right: a or true is true, reversed to rewrite toward the simple side. 504 law or_true_sym: 505 for a: Bool 506 {True{} == Bool.or(a, True{}) : Bool} 507 508 def or_true_sym(a): 509 Equal.sym(Bool, Bool.or(a, True{}), True{}, or_true(a)) 510 511 # True absorbs or on the left: true or a is true, reversed to rewrite toward the simple side. 512 law true_or_sym: 513 for -a: Bool 514 {True{} == Bool.or(True{}, a) : Bool} 515 516 def true_or_sym(a): 517 Equal.sym(Bool, Bool.or(True{}, a), True{}, true_or(a)) 518 519 # De Morgan: not (a and b) is (not a) or (not b), reversed to rewrite toward the simple side. 520 law de_morgan_and_sym: 521 for a: Bool 522 for -b: Bool 523 {Bool.or(Bool.not(a), Bool.not(b)) == Bool.not(Bool.and(a, b)) : Bool} 524 525 def de_morgan_and_sym(a, b): 526 Equal.sym(Bool, Bool.not(Bool.and(a, b)), Bool.or(Bool.not(a), Bool.not(b)), de_morgan_and(a, b)) 527 528 # De Morgan: not (a or b) is (not a) and (not b), reversed to rewrite toward the simple side. 529 law de_morgan_or_sym: 530 for a: Bool 531 for -b: Bool 532 {Bool.and(Bool.not(a), Bool.not(b)) == Bool.not(Bool.or(a, b)) : Bool} 533 534 def de_morgan_or_sym(a, b): 535 Equal.sym(Bool, Bool.not(Bool.or(a, b)), Bool.and(Bool.not(a), Bool.not(b)), de_morgan_or(a, b)) 536 537 # And with itself: a and a is a, reversed to rewrite toward the simple side. 538 law and_self_sym: 539 for a: Bool 540 {a == Bool.and(a, a) : Bool} 541 542 def and_self_sym(a): 543 Equal.sym(Bool, Bool.and(a, a), a, and_self(a)) 544 545 # Or with itself: a or a is a, reversed to rewrite toward the simple side. 546 law or_self_sym: 547 for a: Bool 548 {a == Bool.or(a, a) : Bool} 549 550 def or_self_sym(a): 551 Equal.sym(Bool, Bool.or(a, a), a, or_self(a)) 552 553 # A boolean and its negation are never both true: a and (not a) is false, reversed to rewrite toward the simple side. 554 law and_not_self_sym: 555 for a: Bool 556 {False{} == Bool.and(a, Bool.not(a)) : Bool} 557 558 def and_not_self_sym(a): 559 Equal.sym(Bool, Bool.and(a, Bool.not(a)), False{}, and_not_self(a)) 560 561 # A boolean or its negation is always true: a or (not a) is true, reversed to rewrite toward the simple side. 562 law or_not_self_sym: 563 for a: Bool 564 {True{} == Bool.or(a, Bool.not(a)) : Bool} 565 566 def or_not_self_sym(a): 567 Equal.sym(Bool, Bool.or(a, Bool.not(a)), True{}, or_not_self(a)) 568 569 # And distributes over or: a and (b or c) is (a and b) or (a and c), reversed to rewrite toward the simple side. 570 law and_or_distrib_left_sym: 571 for a: Bool 572 for -b: Bool 573 for -c: Bool 574 {Bool.or(Bool.and(a, b), Bool.and(a, c)) == Bool.and(a, Bool.or(b, c)) : Bool} 575 576 def and_or_distrib_left_sym(a, b, c): 577 Equal.sym(Bool, Bool.and(a, Bool.or(b, c)), Bool.or(Bool.and(a, b), Bool.and(a, c)), and_or_distrib_left(a, b, c)) 578 579 # Or distributes over and: a or (b and c) is (a or b) and (a or c), reversed to rewrite toward the simple side. 580 law or_and_distrib_left_sym: 581 for a: Bool 582 for -b: Bool 583 for -c: Bool 584 {Bool.and(Bool.or(a, b), Bool.or(a, c)) == Bool.or(a, Bool.and(b, c)) : Bool} 585 586 def or_and_distrib_left_sym(a, b, c): 587 Equal.sym(Bool, Bool.or(a, Bool.and(b, c)), Bool.and(Bool.or(a, b), Bool.or(a, c)), or_and_distrib_left(a, b, c)) 588 589 # Absorption: a and (a or b) is a, reversed to rewrite toward the simple side. 590 law and_or_absorb_sym: 591 for a: Bool 592 for -b: Bool 593 {a == Bool.and(a, Bool.or(a, b)) : Bool} 594 595 def and_or_absorb_sym(a, b): 596 Equal.sym(Bool, Bool.and(a, Bool.or(a, b)), a, and_or_absorb(a, b)) 597 598 # Absorption: a or (a and b) is a, reversed to rewrite toward the simple side. 599 law or_and_absorb_sym: 600 for a: Bool 601 for -b: Bool 602 {a == Bool.or(a, Bool.and(a, b)) : Bool} 603 604 def or_and_absorb_sym(a, b): 605 Equal.sym(Bool, Bool.or(a, Bool.and(a, b)), a, or_and_absorb(a, b)) 606 607 # Exclusive or is commutative, reversed to rewrite toward the simple side. 608 law xor_comm_sym: 609 for a: Bool 610 for b: Bool 611 {Bool.xor(b, a) == Bool.xor(a, b) : Bool} 612 613 def xor_comm_sym(a, b): 614 Equal.sym(Bool, Bool.xor(a, b), Bool.xor(b, a), xor_comm(a, b)) 615 616 # Exclusive or is associative, reversed to rewrite toward the simple side. 617 law xor_assoc_sym: 618 for a: Bool 619 for b: Bool 620 for c: Bool 621 {Bool.xor(a, Bool.xor(b, c)) == Bool.xor(Bool.xor(a, b), c) : Bool} 622 623 def xor_assoc_sym(a, b, c): 624 Equal.sym(Bool, Bool.xor(Bool.xor(a, b), c), Bool.xor(a, Bool.xor(b, c)), xor_assoc(a, b, c)) 625 626 # A boolean xor itself is false, reversed to rewrite toward the simple side. 627 law xor_self_sym: 628 for a: Bool 629 {False{} == Bool.xor(a, a) : Bool} 630 631 def xor_self_sym(a): 632 Equal.sym(Bool, Bool.xor(a, a), False{}, xor_self(a)) 633 634 # False is an identity for xor: a xor false is a, reversed to rewrite toward the simple side. 635 law xor_false_sym: 636 for a: Bool 637 {a == Bool.xor(a, False{}) : Bool} 638 639 def xor_false_sym(a): 640 Equal.sym(Bool, Bool.xor(a, False{}), a, xor_false(a)) 641 642 # Xor with true negates: a xor true is not a, reversed to rewrite toward the simple side. 643 law xor_true_sym: 644 for a: Bool 645 {Bool.not(a) == Bool.xor(a, True{}) : Bool} 646 647 def xor_true_sym(a): 648 Equal.sym(Bool, Bool.xor(a, True{}), Bool.not(a), xor_true(a))