|
12 | 12 |
|
13 | 13 | (** #<style> .doc { font-family: monospace; white-space: pre; } </style># **) |
14 | 14 |
|
| 15 | +Require Import Setoid. |
15 | 16 | Require Import ssreflect ssrfun. |
16 | 17 |
|
17 | 18 | (** |
@@ -503,8 +504,15 @@ Structure decProp := DecProp { |
503 | 504 | propbP : reflect prop propb |
504 | 505 | }. |
505 | 506 |
|
| 507 | +Notation "? b" := (propb b) (at level 2). |
| 508 | +Arguments propb : simpl nomatch. |
| 509 | + |
506 | 510 | #[global] Hint Resolve propbP : core. |
507 | 511 |
|
| 512 | +Class Unfold_prop {T : Type} (x y : T) := {}. |
| 513 | +Hint Extern 1 (@Unfold_prop _ ?x ?y) => |
| 514 | + rewrite /prop; exact (@Build_Unfold_prop _ y y) : typeclass_instances. |
| 515 | + |
508 | 516 | (** Predicate family to reflect excluded middle in bool. **) |
509 | 517 | Variant alt_spec (P : decProp) : bool -> Type := |
510 | 518 | | AltTrue of P : alt_spec P true |
@@ -1244,6 +1252,299 @@ Ltac bool_congr := |
1244 | 1252 | | |- (~~ ?X1 = ?X2) => congr 1 negb |
1245 | 1253 | end. |
1246 | 1254 |
|
| 1255 | +Lemma iffT P : P -> P <-> True. Proof. by []. Qed. |
| 1256 | +Lemma iffF P : ~ P -> P <-> False. Proof. by []. Qed. |
| 1257 | + |
| 1258 | +Lemma iffpp P : P <-> P. Proof. by []. Qed. |
| 1259 | +Lemma iffpC P Q : (P <-> Q) <-> (Q <-> P). Proof. by split=> -[]. Qed. |
| 1260 | + |
| 1261 | +Lemma iffpT P : (P <-> True) <-> P. |
| 1262 | +Proof. by split=> // -[] _; apply. Qed. |
| 1263 | + |
| 1264 | +Lemma iffTp P : (True <-> P) <-> P. |
| 1265 | +Proof. by split=> // -[] + _; apply. Qed. |
| 1266 | + |
| 1267 | +Lemma iffpF P : (P <-> False) <-> (~ P). |
| 1268 | +Proof. by split=> // -[]. Qed. |
| 1269 | + |
| 1270 | +Lemma iffFp P : (False <-> P) <-> (~ P). |
| 1271 | +Proof. by split=> // -[]. Qed. |
| 1272 | + |
| 1273 | +Lemma reflectP (P Q : decProp) : (P <-> Q) <-> (? P = ? Q). |
| 1274 | +Proof. |
| 1275 | +by case: (propbP P) => [/iffT|/iffF] ->; |
| 1276 | + case: (propbP Q) => [/iffT|/iffF] -> //; split=> // -[]//. |
| 1277 | +Qed. |
| 1278 | + |
| 1279 | +Lemma propbE (P Q : decProp) {RP RQ : Prop} `{@Unfold_prop Prop (prop P) RP} `{@Unfold_prop Prop (prop Q) RQ} : (P <-> Q) -> (? (reverse_coercion P RP) = ? (reverse_coercion Q RQ)). |
| 1280 | +Proof. by move/reflectP. Qed. |
| 1281 | + |
| 1282 | +Lemma negpF : ~ False. Proof. by []. Qed. |
| 1283 | + |
| 1284 | +Lemma negpK (P : decProp) : ~ ~ P <-> P. |
| 1285 | +Proof. by (split=> p; last by apply); case: (propbP P) => // /p. Qed. |
| 1286 | + |
| 1287 | +Lemma andTp P : True /\ P <-> P. |
| 1288 | +Proof. by split=> [[]|]. Qed. |
| 1289 | + |
| 1290 | +Lemma andFp P : ~ (False /\ P). |
| 1291 | +Proof. by move=> []. Qed. |
| 1292 | + |
| 1293 | +Lemma andpT P : P /\ True <-> P. |
| 1294 | +Proof. by split=> [[]|]. Qed. |
| 1295 | + |
| 1296 | +Lemma andpF P : ~ (P /\ False). |
| 1297 | +Proof. by move=> []. Qed. |
| 1298 | + |
| 1299 | +Lemma andpp P : P /\ P <-> P. |
| 1300 | +Proof. by split=> [[]|]. Qed. |
| 1301 | + |
| 1302 | +Lemma andpC P Q : P /\ Q <-> Q /\ P. |
| 1303 | +Proof. by split=> -[]. Qed. |
| 1304 | + |
| 1305 | +Lemma andpA P Q R : (P /\ Q) /\ R <-> P /\ Q /\ R. |
| 1306 | +Proof. by split=> [[][]|[]+[]]. Qed. |
| 1307 | + |
| 1308 | +Lemma andpCA P Q R : P /\ (Q /\ R) <-> Q /\ (P /\ R). |
| 1309 | +Proof. by split=> -[]+[]. Qed. |
| 1310 | + |
| 1311 | +Lemma andpAC P Q R : (P /\ Q) /\ R <-> (P /\ R) /\ Q. |
| 1312 | +Proof. by split=> -[][]. Qed. |
| 1313 | + |
| 1314 | +Lemma andpACA P Q R S : (P /\ Q) /\ (R /\ S) <-> (P /\ R) /\ (Q /\ S). |
| 1315 | +Proof. by split=> -[][]++[]. Qed. |
| 1316 | + |
| 1317 | +Lemma orTp P : True \/ P. |
| 1318 | +Proof. by left. Qed. |
| 1319 | + |
| 1320 | +Lemma orFp P : False \/ P <-> P. |
| 1321 | +Proof. by split=> [[]//|?]; right. Qed. |
| 1322 | + |
| 1323 | +Lemma orpT P : P \/ True. |
| 1324 | +Proof. by right. Qed. |
| 1325 | + |
| 1326 | +Lemma orpF P : P \/ False <-> P. |
| 1327 | +Proof. by split=> [[]//|?]; left. Qed. |
| 1328 | + |
| 1329 | +Lemma orpp P : P \/ P <-> P. |
| 1330 | +Proof. by split=> [[]//|?]; left. Qed. |
| 1331 | + |
| 1332 | +Lemma orpC P Q : P \/ Q <-> Q \/ P. |
| 1333 | +Proof. by split; (move=> -[]?; [right|left]). Qed. |
| 1334 | + |
| 1335 | +Lemma orpA P Q R : (P \/ Q) \/ R <-> P \/ Q \/ R. |
| 1336 | +Proof. |
| 1337 | +by split; move=> -[]; (try case) => ?; |
| 1338 | + [left|right; left|right; right|left; left|left; right|right]. |
| 1339 | +Qed. |
| 1340 | + |
| 1341 | +Lemma orpCA P Q R : P \/ (Q \/ R) <-> (Q \/ (P \/ R)). |
| 1342 | +Proof. by rewrite -orpA (orpC P) orpA. Qed. |
| 1343 | + |
| 1344 | +Lemma orpAC P Q R : (P \/ Q) \/ R <-> (P \/ R) \/ Q. |
| 1345 | +Proof. by rewrite orpA (orpC Q) -orpA. Qed. |
| 1346 | + |
| 1347 | +Lemma orpACA P Q R S : (P \/ Q) \/ (R \/ S) <-> (P \/ R) \/ (Q \/ S). |
| 1348 | +Proof. by rewrite orpAC -orpA -orpAC orpA. Qed. |
| 1349 | + |
| 1350 | +Lemma andpN P : ~ (P /\ ~ P). |
| 1351 | +Proof. by move=> [] ?; apply. Qed. |
| 1352 | + |
| 1353 | +Lemma andNp P : ~ (~ P /\ P). |
| 1354 | +Proof. by move=> [] /[apply]. Qed. |
| 1355 | + |
| 1356 | +Lemma orpN (P : decProp) : P \/ ~ P. |
| 1357 | +Proof. by case: (propbP P) => p; [left|right]. Qed. |
| 1358 | + |
| 1359 | +Lemma orNp (P : decProp) : ~ P \/ P. |
| 1360 | +Proof. by rewrite orpC (iffT (orpN _)). Qed. |
| 1361 | + |
| 1362 | +Lemma andp_orl P Q R : (P \/ Q) /\ R <-> (P /\ R) \/ (Q /\ R). |
| 1363 | +Proof. |
| 1364 | +by (split=> -[][]??; [left|right| |]) => //; split=> //; [left|right]. |
| 1365 | +Qed. |
| 1366 | + |
| 1367 | +Lemma andp_orr P Q R : P /\ (Q \/ R) <-> (P /\ Q) \/ (P /\ R). |
| 1368 | +Proof. by rewrite andpC andp_orl andpC (andpC R). Qed. |
| 1369 | + |
| 1370 | +Lemma orp_andl P Q R : (P /\ Q) \/ R <-> (P \/ R) /\ (Q \/ R). |
| 1371 | +Proof. |
| 1372 | +by split=> [[[]?|]?|[][?[]?|? _]]; [split; left|split; right|left|right|right]. |
| 1373 | +Qed. |
| 1374 | + |
| 1375 | +Lemma orp_andr P Q R : P \/ (Q /\ R) <-> (P \/ Q) /\ (P \/ R). |
| 1376 | +Proof. by rewrite orpC orp_andl orpC (orpC R). Qed. |
| 1377 | + |
| 1378 | + |
| 1379 | +Lemma andp_idl P Q : (Q -> P) -> P /\ Q <-> Q. |
| 1380 | +Proof. by move=> QP; split=> [[]|/[dup]/QP]. Qed. |
| 1381 | +Lemma andp_idr P Q : (P -> Q) -> P /\ Q <-> P. |
| 1382 | +Proof. by rewrite andpC (iffT (@andp_idl _ _)). Qed. |
| 1383 | +Lemma andp_id2l P Q R : (P -> Q <-> R) -> P /\ Q <-> P /\ R. |
| 1384 | +Proof. by move=> PQR; split=> -[] ?; rewrite PQR. Qed. |
| 1385 | +Lemma andp_id2r P Q R : (Q -> P <-> R) -> P /\ Q <-> R /\ Q. |
| 1386 | +Proof. by rewrite ![_ /\ Q]andpC (iffT (@andp_id2l _ _ _)). Qed. |
| 1387 | + |
| 1388 | +Lemma orp_idl P Q : (Q -> P) -> P \/ Q <-> P. |
| 1389 | +Proof. by move=> QP; split=> [[|/QP]//|]?; left. Qed. |
| 1390 | +Lemma orp_idr P Q : (P -> Q) -> P \/ Q <-> Q. |
| 1391 | +Proof. by rewrite orpC (iffT (@orp_idl _ _)). Qed. |
| 1392 | +Lemma orp_id2l (P : decProp) Q R : |
| 1393 | + (~ P -> Q <-> R) -> P \/ Q <-> P \/ R. |
| 1394 | +Proof. by move=> PQR; case: (propbP P) => [|/PQR -> //]; split; left. Qed. |
| 1395 | +Lemma orp_id2r P (Q : decProp) R : (~ Q -> P <-> R) -> P \/ Q <-> R \/ Q. |
| 1396 | +Proof. by rewrite ![_ \/ Q]orpC (iffT (@orp_id2l _ _ _)). Qed. |
| 1397 | + |
| 1398 | +Lemma negp_and (P Q : decProp) : ~ (P /\ Q) <-> ~ P \/ ~ Q. |
| 1399 | +Proof. |
| 1400 | +by case: (propbP P) => [/iffT|/iffF] ->; |
| 1401 | + case: (propbP Q) => [/iffT|/iffF] ->; |
| 1402 | + apply/propbP. |
| 1403 | +Qed. |
| 1404 | + |
| 1405 | +Lemma negp_or P Q : ~ (P \/ Q) <-> (~ P) /\ ~ Q. |
| 1406 | +Proof. by split=> [pq|[]p q [/p|/q]//]; split=> ?; apply: pq; [left|right]. Qed. |
| 1407 | + |
| 1408 | +(** Pseudo-cancellation -- i.e, absorption **) |
| 1409 | + |
| 1410 | +Lemma andpK P Q : P /\ Q \/ P <-> P. Proof. by split=> [[[]|]//|?]; right. Qed. |
| 1411 | +Lemma andKp P Q : P \/ Q /\ P <-> P. Proof. by split=> [[|[]]//|?]; left. Qed. |
| 1412 | +Lemma orpK P Q : (P \/ Q) /\ P <-> P. |
| 1413 | +Proof. by split=> [[]//|?]; split=> //; left. Qed. |
| 1414 | +Lemma orKp P Q : P /\ (Q \/ P) <-> P. |
| 1415 | +Proof. by split=> [[]//|?]; split=> //; right. Qed. |
| 1416 | + |
| 1417 | +(** Imply **) |
| 1418 | + |
| 1419 | +Lemma implypT P : P -> True. Proof. by []. Qed. |
| 1420 | +Lemma implypF P : (P -> False) <-> ~ P. Proof. by []. Qed. |
| 1421 | +Lemma implyFP P : False -> P. Proof. by []. Qed. |
| 1422 | +Lemma implyTp P : (True -> P) <-> P. Proof. by split=> //; apply. Qed. |
| 1423 | +Lemma implypp P : P -> P. Proof. by []. Qed. |
| 1424 | + |
| 1425 | +Lemma negp_imply (P : decProp) Q : ~ (P -> Q) <-> P /\ ~ Q. |
| 1426 | +Proof. |
| 1427 | +split=> [|[]p q /(_ p)/q//] pq; split=> [|q]; last exact: pq. |
| 1428 | +by case: (propbP P) => // p; elim: pq => /p. |
| 1429 | +Qed. |
| 1430 | + |
| 1431 | +Lemma implypE (P : decProp) Q : (P -> Q) <-> ~ P \/ Q. |
| 1432 | +Proof. by split=> [pq|[]//]; case: (propbP P) => [/pq|] ?; [right|left]. Qed. |
| 1433 | + |
| 1434 | +Lemma implyNp (P : decProp) Q : (~ P -> Q) <-> P \/ Q. |
| 1435 | +Proof. by rewrite implypE negpK. Qed. |
| 1436 | + |
| 1437 | +Lemma implypN P Q : (P -> ~ Q) <-> (Q -> ~ P). |
| 1438 | +Proof. by split=> /[apply]. Qed. |
| 1439 | + |
| 1440 | +Lemma implypNN (P : decProp) Q : (~ P -> ~ Q) <-> (Q -> P). |
| 1441 | +Proof. by split=> [/[apply]|qp ? /qp//]; rewrite [_ -> False]negpK. Qed. |
| 1442 | + |
| 1443 | +Lemma iffNN (P Q : decProp) : (~ P <-> ~ Q) <-> (P <-> Q). |
| 1444 | +Proof. by rewrite /iff !implypNN ![(Q -> _) /\ _]andpC. Qed. |
| 1445 | + |
| 1446 | +Lemma implyp_idl (P : decProp) Q : (~ P -> Q) -> (P -> Q) <-> Q. |
| 1447 | +Proof. by move=> npq; split=> // pq; case: (propbP P) => [/pq|/npq]. Qed. |
| 1448 | +Lemma implyp_idr (P : decProp) Q : (Q -> ~ P) -> (P -> Q) <-> ~ P. |
| 1449 | +Proof. |
| 1450 | +by move=> qnp; split=> [pq|/[apply]//]; case: (propbP P) => [/pq/qnp|]. |
| 1451 | +Qed. |
| 1452 | +Lemma implyp_id2l T P Q : (forall x : T, P x <-> Q x) -> (forall x, P x) <-> (forall x, Q x). |
| 1453 | +Proof. |
| 1454 | +move=> xqr; split=> + x. |
| 1455 | +(* FIXME: This looks like a bug either in setoid_rewrite or in ssrmatching. *) |
| 1456 | + by rewrite -(xqr x); apply. |
| 1457 | +by rewrite (xqr x); apply. |
| 1458 | +Qed. |
| 1459 | + |
| 1460 | +Definition xor (P Q : Prop) := |
| 1461 | + (P \/ Q) /\ ~ (P /\ Q). |
| 1462 | + |
| 1463 | +Instance xor_iff_morphism : Morphisms.Proper (iff ==> iff ==> iff) xor. |
| 1464 | +Proof. by move=> P Q PQ R S RS; rewrite /xor PQ RS. Qed. |
| 1465 | + |
| 1466 | +Lemma xorpC P Q : xor P Q <-> xor Q P. |
| 1467 | +Proof. by rewrite /xor orpC (andpC P). Qed. |
| 1468 | + |
| 1469 | +Lemma xorFp P : xor False P <-> P. |
| 1470 | +Proof. by split=> [[]/orFp//|p]; split=> [|[]//]; right. Qed. |
| 1471 | + |
| 1472 | +Lemma xorpF P : xor P False <-> P. |
| 1473 | +Proof. by rewrite xorpC xorFp. Qed. |
| 1474 | + |
| 1475 | +Lemma xorTp P : xor True P <-> ~ P. |
| 1476 | +Proof. by rewrite /xor (iffT (orTp _)) !andTp. Qed. |
| 1477 | + |
| 1478 | +Lemma xorpT P : xor P True <-> ~ P. |
| 1479 | +Proof. by rewrite xorpC xorTp. Qed. |
| 1480 | + |
| 1481 | +Lemma xorP (P Q : decProp) : reflect (xor P Q) (addb P Q). |
| 1482 | +Proof. |
| 1483 | +case: (propbP P) => [/iffT|/iffF] p. |
| 1484 | + apply: (@equivP (~ Q)); first exact: negPP. |
| 1485 | + by rewrite p xorTp. |
| 1486 | +apply: (@equivP Q); first exact: propbP. |
| 1487 | +by rewrite p xorFp. |
| 1488 | +Qed. |
| 1489 | + |
| 1490 | +Canonical xor_decProp (P Q : decProp) := {| |
| 1491 | + prop := xor P Q; |
| 1492 | + propb := addb P Q; |
| 1493 | + propbP := xorP P Q |
| 1494 | +|}. |
| 1495 | + |
| 1496 | +Lemma xorpp P : ~ (xor P P). |
| 1497 | +Proof. by move=> [] /orpp p; rewrite andpp; apply. Qed. |
| 1498 | + |
| 1499 | +Lemma xorpN (P : decProp) Q : xor P (~ Q) <-> ~ (xor P Q). |
| 1500 | +Proof. by case: (propbP P) => [/iffT|/iffF] ->; rewrite ?xorTp ?xorFp. Qed. |
| 1501 | + |
| 1502 | +Lemma xorNp P (Q : decProp) : xor (~ P) Q <-> ~ (xor P Q). |
| 1503 | +Proof. by rewrite xorpC xorpN xorpC. Qed. |
| 1504 | + |
| 1505 | +Lemma xorpA (P : decProp) Q (R : decProp) : xor P (xor Q R) <-> xor (xor P Q) R. |
| 1506 | +Proof. |
| 1507 | +by case: (propbP P) => [/iffT|/iffF] ->; rewrite ?xorFp// !xorTp xorNp. |
| 1508 | +Qed. |
| 1509 | + |
| 1510 | +Lemma xorpCA (P Q : decProp) R : xor P (xor Q R) <-> xor Q (xor P R). |
| 1511 | +Proof. |
| 1512 | +by case: (propbP P) => [/iffT|/iffF] ->; rewrite ?xorFp// !xorTp xorpN. |
| 1513 | +Qed. |
| 1514 | + |
| 1515 | +Lemma xorpAC P (Q R : decProp) : xor (xor P Q) R <-> xor (xor P R) Q. |
| 1516 | +Proof. by rewrite ![xor (xor _ _) _]xorpC !(xorpC P) xorpCA. Qed. |
| 1517 | + |
| 1518 | +Lemma xorpACA (P Q R S : decProp) : |
| 1519 | + xor (xor P Q) (xor R S) <-> xor (xor P R) (xor Q S). |
| 1520 | +Proof. by rewrite !xorpA/= -(xorpA _ _ R) (xorpC Q) xorpA. Qed. |
| 1521 | + |
| 1522 | +Lemma andp_xorl P Q R : (xor P Q) /\ R <-> xor (P /\ R) (Q /\ R). |
| 1523 | +Proof. |
| 1524 | +rewrite /xor -andp_orl andpACA andpp andpAC. |
| 1525 | +by apply: andp_id2l => -[] _ /iffT ->; rewrite andpT. |
| 1526 | +Qed. |
| 1527 | + |
| 1528 | +Lemma andp_xorr P Q R : P /\ (xor Q R) <-> xor (P /\ Q) (P /\ R). |
| 1529 | +Proof. by rewrite andpC andp_xorl !(andpC P). Qed. |
| 1530 | + |
| 1531 | +Lemma xorKp (P Q : decProp) : xor P (xor P Q) <-> Q. |
| 1532 | +Proof. |
| 1533 | +by case: (propbP P) => [/iffT|/iffF] ->; rewrite ?xorFp// !xorTp negpK. |
| 1534 | +Qed. |
| 1535 | + |
| 1536 | +Lemma xorpK (P Q : decProp) : xor (xor Q P) P <-> Q. |
| 1537 | +Proof. by rewrite ![xor _ P]xorpC xorKp. Qed. |
| 1538 | + |
| 1539 | +Lemma xorpP (P : decProp) Q : xor P Q <-> (~ P <-> Q). |
| 1540 | +Proof. |
| 1541 | +case: (propbP P) => [/iffT|/iffF] ->. |
| 1542 | + by rewrite xorTp (iffF (_ : ~ ~ True))// iffFp. |
| 1543 | +by rewrite xorFp (iffT negpF) iffTp. |
| 1544 | +Qed. |
| 1545 | + |
| 1546 | +Arguments xorpP {P Q}. |
| 1547 | + |
1247 | 1548 |
|
1248 | 1549 | (** |
1249 | 1550 | Predicates, i.e., packaged functions to bool. |
@@ -1367,6 +1668,10 @@ Canonical dec_predDecPredType T := DecPredType (@id (dec_pred T)). |
1367 | 1668 | #[warning="-redundant-canonical-projection"] |
1368 | 1669 | Canonical decPropfunDecPredType T := DecPredType (@id (T -> decProp)). |
1369 | 1670 |
|
| 1671 | +Lemma iff_forall T (P Q : pred T) : |
| 1672 | + (forall x, P x <-> Q x) -> (forall x, P x) <-> (forall x, Q x). |
| 1673 | +Proof. by move=> PQ; split=> pq x; apply/PQ/pq. Qed. |
| 1674 | + |
1370 | 1675 | (** The type of abstract collective predicates. |
1371 | 1676 | While {pred T} is convertible to pred T, it presents the pred_sort coercion |
1372 | 1677 | class, which crucially does _not_ coerce to Funclass. Term whose type P coerces |
@@ -1519,7 +1824,7 @@ Coercion pred_of_mem {T} mp : {pred T} := let: Mem p := mp in [eta p]. |
1519 | 1824 | Canonical memPredType T := PredType (@pred_of_mem T). |
1520 | 1825 |
|
1521 | 1826 | Definition in_mem {T} (x : T) mp := pred_of_mem mp x. |
1522 | | -Definition eq_mem {T} mp1 mp2 := forall x : T, in_mem x mp1 = in_mem x mp2. |
| 1827 | +Definition eq_mem {T} mp1 mp2 := forall x : T, in_mem x mp1 <-> in_mem x mp2. |
1523 | 1828 | Definition sub_mem {T} mp1 mp2 := forall x : T, in_mem x mp1 -> in_mem x mp2. |
1524 | 1829 |
|
1525 | 1830 | Arguments in_mem {T} x mp : simpl never. |
@@ -1752,7 +2057,7 @@ Structure keyed_pred (k : pred_key p) := |
1752 | 2057 | PackKeyedPred {unkey_pred :> {pred T}; _ : unkey_pred =i p}. |
1753 | 2058 |
|
1754 | 2059 | Variable k : pred_key p. |
1755 | | -Definition KeyedPred := @PackKeyedPred k p (frefl _). |
| 2060 | +Definition KeyedPred := @PackKeyedPred k p (fun x => iff_refl _). |
1756 | 2061 |
|
1757 | 2062 | Variable k_p : keyed_pred k. |
1758 | 2063 | Lemma keyed_predE : k_p =i p. Proof. by case: k_p. Qed. |
|
0 commit comments