itp-interface 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- itp_interface/__init__.py +0 -0
- itp_interface/agent/__init__.py +0 -0
- itp_interface/agent/simple_proof_agent.py +100 -0
- itp_interface/coq_ser_api/__init__.py +165 -0
- itp_interface/coq_ser_api/contexts.py +283 -0
- itp_interface/coq_ser_api/coq_agent.py +459 -0
- itp_interface/coq_ser_api/coq_backend.py +135 -0
- itp_interface/coq_ser_api/coq_util.py +839 -0
- itp_interface/coq_ser_api/example.py +67 -0
- itp_interface/coq_ser_api/lsp_backend.py +375 -0
- itp_interface/coq_ser_api/py.typed +0 -0
- itp_interface/coq_ser_api/serapi_backend.py +841 -0
- itp_interface/coq_ser_api/util.py +145 -0
- itp_interface/coq_ser_api_old/__init__.py +2583 -0
- itp_interface/coq_ser_api_old/contexts.py +172 -0
- itp_interface/coq_ser_api_old/util.py +146 -0
- itp_interface/lean_server/__init__.py +0 -0
- itp_interface/lean_server/commands.py +484 -0
- itp_interface/lean_server/lean3_search_tool.py +358 -0
- itp_interface/lean_server/lean4_repl_interface.py +151 -0
- itp_interface/lean_server/lean4_utils.py +255 -0
- itp_interface/lean_server/lean_cmd_server.py +111 -0
- itp_interface/lean_server/lean_context.py +60 -0
- itp_interface/lean_server/lean_sync_server.py +174 -0
- itp_interface/lean_server/lean_utils.py +199 -0
- itp_interface/lean_server/py.typed +1 -0
- itp_interface/main/__init__.py +0 -0
- itp_interface/main/config/afp_data_gen.yaml +14 -0
- itp_interface/main/config/benchmark/CompCert.yaml +366 -0
- itp_interface/main/config/benchmark/GeoCoq.yaml +930 -0
- itp_interface/main/config/benchmark/UniMath.yaml +2690 -0
- itp_interface/main/config/benchmark/afp_isabelle.yaml +29200 -0
- itp_interface/main/config/benchmark/agent_proverbot_hard.yaml +247 -0
- itp_interface/main/config/benchmark/category-theory.yaml +470 -0
- itp_interface/main/config/benchmark/compcert_118_subset.yaml +148 -0
- itp_interface/main/config/benchmark/compcert_benchmark.yaml +36 -0
- itp_interface/main/config/benchmark/compcert_benchmark_hard.yaml +498 -0
- itp_interface/main/config/benchmark/compcert_benchmark_hard_1.yaml +55 -0
- itp_interface/main/config/benchmark/compcert_benchmark_hard_2.yaml +24 -0
- itp_interface/main/config/benchmark/compcert_benchmark_hard_3.yaml +95 -0
- itp_interface/main/config/benchmark/compcert_benchmark_hard_7_per_cent.yaml +78 -0
- itp_interface/main/config/benchmark/compcert_benchmark_test.yaml +38 -0
- itp_interface/main/config/benchmark/compcert_benchmark_train.yaml +340 -0
- itp_interface/main/config/benchmark/leandojo_novel_premises_test.yaml +2908 -0
- itp_interface/main/config/benchmark/leandojo_novel_premises_train.yaml +98645 -0
- itp_interface/main/config/benchmark/leandojo_novel_premises_val.yaml +2912 -0
- itp_interface/main/config/benchmark/leandojo_random.yaml +2889 -0
- itp_interface/main/config/benchmark/leandojo_random_test.yaml +2421 -0
- itp_interface/main/config/benchmark/leandojo_random_train.yaml +62729 -0
- itp_interface/main/config/benchmark/leandojo_random_val.yaml +2504 -0
- itp_interface/main/config/benchmark/math-comp.yaml +200 -0
- itp_interface/main/config/benchmark/miniF2F_test.yaml +12 -0
- itp_interface/main/config/benchmark/miniF2F_test_aime.yaml +27 -0
- itp_interface/main/config/benchmark/miniF2F_test_algebra.yaml +30 -0
- itp_interface/main/config/benchmark/miniF2F_test_amc12.yaml +57 -0
- itp_interface/main/config/benchmark/miniF2F_test_few_shot_hard.yaml +231 -0
- itp_interface/main/config/benchmark/miniF2F_test_imo.yaml +32 -0
- itp_interface/main/config/benchmark/miniF2F_test_induction.yaml +20 -0
- itp_interface/main/config/benchmark/miniF2F_test_mathd_algebra.yaml +82 -0
- itp_interface/main/config/benchmark/miniF2F_test_mathd_algebra_hard.yaml +72 -0
- itp_interface/main/config/benchmark/miniF2F_test_mathd_numbertheory.yaml +72 -0
- itp_interface/main/config/benchmark/miniF2F_test_numbertheory.yaml +20 -0
- itp_interface/main/config/benchmark/minicompcert_benchmark_1.yaml +14 -0
- itp_interface/main/config/benchmark/proverbot_hard.yaml +104 -0
- itp_interface/main/config/benchmark/re_prover.yaml +66 -0
- itp_interface/main/config/benchmark/re_prover_hard.yaml +41 -0
- itp_interface/main/config/benchmark/re_prover_very_hard.yaml +22 -0
- itp_interface/main/config/benchmark/reprover_with_retrieval.yaml +73 -0
- itp_interface/main/config/benchmark/reprover_with_retrieval_hard.yaml +30 -0
- itp_interface/main/config/benchmark/reprover_with_retrieval_neg.yaml +195 -0
- itp_interface/main/config/benchmark/simple_benchmark_1.yaml +24 -0
- itp_interface/main/config/benchmark/simple_benchmark_8.yaml +50 -0
- itp_interface/main/config/benchmark/simple_benchmark_9.yaml +65 -0
- itp_interface/main/config/benchmark/simple_benchmark_isabelle.yaml +18 -0
- itp_interface/main/config/benchmark/simple_benchmark_lean.yaml +12 -0
- itp_interface/main/config/benchmark/simple_benchmark_lean_training_data.yaml +12 -0
- itp_interface/main/config/benchmark/simple_rl_benchmark_lean.yaml +14 -0
- itp_interface/main/config/benchmark/stack_machine.yaml +13 -0
- itp_interface/main/config/benchmark/stack_machine_hard.yaml +15 -0
- itp_interface/main/config/category_theory_data_gen.yaml +14 -0
- itp_interface/main/config/category_theory_data_gen_random.yaml +16 -0
- itp_interface/main/config/compcert_data_gen_test.yaml +10 -0
- itp_interface/main/config/compcert_data_gen_train.yaml +7 -0
- itp_interface/main/config/env_settings/bm25_retrieval.yaml +2 -0
- itp_interface/main/config/env_settings/bm25_retrieval_no_dfns.yaml +2 -0
- itp_interface/main/config/env_settings/bm25_retrieval_only_local_no_dfns.yaml +2 -0
- itp_interface/main/config/env_settings/bm25_retrieval_with_print.yaml +2 -0
- itp_interface/main/config/env_settings/bm25_retrieval_with_print_only_local.yaml +2 -0
- itp_interface/main/config/env_settings/bm25_retrieval_with_print_only_local_no_dfns.yaml +2 -0
- itp_interface/main/config/env_settings/no_retrieval.yaml +2 -0
- itp_interface/main/config/experiments.yaml +12 -0
- itp_interface/main/config/geo_coq_data_gen.yaml +14 -0
- itp_interface/main/config/geo_coq_data_gen_random.yaml +16 -0
- itp_interface/main/config/leandojo_random_data_gen.yaml +16 -0
- itp_interface/main/config/math_comp_data_gen.yaml +14 -0
- itp_interface/main/config/math_comp_data_gen_random.yaml +16 -0
- itp_interface/main/config/mathlib_data_gen.yaml +14 -0
- itp_interface/main/config/repo/coq_repos.yaml +191 -0
- itp_interface/main/config/run_settings/default_coq_data_generation_transforms.yaml +24 -0
- itp_interface/main/config/run_settings/default_isabelle_data_generation_transforms.yaml +24 -0
- itp_interface/main/config/run_settings/default_lean4_data_generation_transforms.yaml +24 -0
- itp_interface/main/config/run_settings/default_lean_data_generation_transforms.yaml +24 -0
- itp_interface/main/config/simple_coq_data_gen.yaml +12 -0
- itp_interface/main/config/simple_coq_data_gen_random.yaml +17 -0
- itp_interface/main/config/simple_lean_data_gen.yaml +12 -0
- itp_interface/main/config/simple_rl_lean_data_gen.yaml +12 -0
- itp_interface/main/config/uni_math_data_gen.yaml +14 -0
- itp_interface/main/config.py +192 -0
- itp_interface/main/extract_benchmark_dataset.py +106 -0
- itp_interface/main/filter_dataset.py +107 -0
- itp_interface/main/install.py +92 -0
- itp_interface/main/merge_dataset.py +96 -0
- itp_interface/main/run_tool.py +444 -0
- itp_interface/pisa/.git +1 -0
- itp_interface/pisa/.gitignore +125 -0
- itp_interface/pisa/.idea/.gitignore +8 -0
- itp_interface/pisa/.idea/ClojureProjectResolveSettings.xml +6 -0
- itp_interface/pisa/.idea/codeStyles/Project.xml +7 -0
- itp_interface/pisa/.idea/codeStyles/codeStyleConfig.xml +5 -0
- itp_interface/pisa/.idea/inspectionProfiles/Project_Default.xml +16 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_android_annotations_4_1_1_4_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_api_grpc_proto_google_common_protos_1_17_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_code_findbugs_jsr305_3_0_2_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_code_gson_gson_2_8_6_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_errorprone_error_prone_annotations_2_3_4_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_guava_failureaccess_1_0_1_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_guava_guava_30_0_jre_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava_jar.xml +9 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_j2objc_j2objc_annotations_1_3_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_protobuf_protobuf_java_3_12_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_google_protobuf_protobuf_java_util_3_12_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_lihaoyi_fastparse_2_13_2_3_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_lihaoyi_geny_2_13_0_6_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_lihaoyi_sourcecode_2_13_0_2_1_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_thesamet_scalapb_lenses_2_13_0_10_9_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_thesamet_scalapb_scalapb_runtime_2_13_0_10_9_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_thesamet_scalapb_scalapb_runtime_grpc_2_13_0_10_9_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_thesamet_scalapb_zio_grpc_zio_grpc_core_2_13_0_4_2_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__com_thoughtworks_paranamer_paranamer_2_8_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__commons_io_commons_io_2_8_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__de_unruh_java_patterns_0_1_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__de_unruh_scala_isabelle_2_13_master_SNAPSHOT_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__dev_zio_izumi_reflect_2_13_1_0_0_M9_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__dev_zio_izumi_reflect_thirdparty_boopickle_shaded_2_13_1_0_0_M9_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__dev_zio_zio_2_13_1_0_3_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__dev_zio_zio_stacktracer_2_13_1_0_3_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__dev_zio_zio_streams_2_13_1_0_3_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_grpc_grpc_api_1_34_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_grpc_grpc_context_1_34_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_grpc_grpc_core_1_34_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_grpc_grpc_netty_1_34_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_grpc_grpc_protobuf_1_34_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_grpc_grpc_protobuf_lite_1_34_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_grpc_grpc_services_1_34_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_grpc_grpc_stub_1_34_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_buffer_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_codec_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_codec_http2_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_codec_http_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_codec_socks_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_common_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_handler_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_handler_proxy_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_resolver_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_netty_netty_transport_4_1_51_Final_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__io_perfmark_perfmark_api_0_19_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__net_java_dev_jna_jna_5_3_1_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__net_liftweb_lift_json_2_13_3_4_3_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_apache_commons_commons_lang3_3_11_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_apache_commons_commons_text_1_9_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_checkerframework_checker_qual_3_5_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_codehaus_mojo_animal_sniffer_annotations_1_18_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_jetbrains_annotations_20_1_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_jline_jline_3_16_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_log4s_log4s_2_13_1_9_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_scala_lang_modules_scala_collection_compat_2_13_2_1_6_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_scala_lang_modules_scala_xml_2_13_1_3_0_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_scala_lang_scala_compiler_2_13_4_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_scala_lang_scala_library_2_13_4_jar.xml +23 -0
- itp_interface/pisa/.idea/libraries/sbt__org_scala_lang_scala_reflect_2_13_4_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_scala_lang_scalap_2_13_4_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_scalaz_scalaz_core_2_13_7_3_2_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_slf4j_slf4j_api_1_7_30_jar.xml +13 -0
- itp_interface/pisa/.idea/libraries/sbt__org_slf4j_slf4j_simple_1_7_30_jar.xml +13 -0
- itp_interface/pisa/.idea/misc.xml +7 -0
- itp_interface/pisa/.idea/modules/PISA-build.iml +127 -0
- itp_interface/pisa/.idea/modules/PISA.iml +94 -0
- itp_interface/pisa/.idea/modules.xml +9 -0
- itp_interface/pisa/.idea/other.xml +6 -0
- itp_interface/pisa/.idea/sbt.xml +20 -0
- itp_interface/pisa/.idea/scala_compiler.xml +6 -0
- itp_interface/pisa/.idea/uiDesigner.xml +124 -0
- itp_interface/pisa/.idea/vcs.xml +6 -0
- itp_interface/pisa/.scalafmt.conf +2 -0
- itp_interface/pisa/LICENSE +29 -0
- itp_interface/pisa/README.md +262 -0
- itp_interface/pisa/build.sbt +49 -0
- itp_interface/pisa/build.sh +26 -0
- itp_interface/pisa/command_generation/close_gaps.py +44 -0
- itp_interface/pisa/command_generation/conjecture_normal_order.py +62 -0
- itp_interface/pisa/command_generation/conjecturer_command_generator.py +36 -0
- itp_interface/pisa/command_generation/create_dirs.py +11 -0
- itp_interface/pisa/command_generation/find_std.py +67 -0
- itp_interface/pisa/command_generation/generate_build_commands_afp.py +15 -0
- itp_interface/pisa/command_generation/generate_build_commands_std.py +15 -0
- itp_interface/pisa/command_generation/generate_commands_afp.py +103 -0
- itp_interface/pisa/command_generation/generate_commands_mini.py +73 -0
- itp_interface/pisa/command_generation/generate_commands_std.py +69 -0
- itp_interface/pisa/command_generation/generate_hammer_extraction_text.py +5 -0
- itp_interface/pisa/command_generation/hammer_command_generator.py +40 -0
- itp_interface/pisa/command_generation/hp_search_command_generator.py +63 -0
- itp_interface/pisa/command_generation/oracle_command_generator.py +56 -0
- itp_interface/pisa/command_generation/search_command_generator.py +69 -0
- itp_interface/pisa/command_generation/summarise_problem_names.py +45 -0
- itp_interface/pisa/command_generation/tpu_hp_search.py +75 -0
- itp_interface/pisa/docker/Dockerfile +34 -0
- itp_interface/pisa/docker/docker_tutorial.md +64 -0
- itp_interface/pisa/eval_setup/copy_isabelle.py +42 -0
- itp_interface/pisa/eval_setup/copy_pisa_jars.py +18 -0
- itp_interface/pisa/mesh_transformer_utils/tokenization.py +86 -0
- itp_interface/pisa/project/build.properties +1 -0
- itp_interface/pisa/project/plugins.sbt +5 -0
- itp_interface/pisa/requirements.txt +4 -0
- itp_interface/pisa/scripts/extract_last_k_steps.py +28 -0
- itp_interface/pisa/scripts/extract_proof_corpus.py +26 -0
- itp_interface/pisa/scripts/gather_hammer_results.py +27 -0
- itp_interface/pisa/scripts/length_in_char_stats.py +20 -0
- itp_interface/pisa/scripts/mix.py +127 -0
- itp_interface/pisa/scripts/results_stat.py +52 -0
- itp_interface/pisa/scripts/test_array_job.sh +34 -0
- itp_interface/pisa/setup.sh +25 -0
- itp_interface/pisa/src/main/protobuf/server.proto +60 -0
- itp_interface/pisa/src/main/python/.idea/.gitignore +8 -0
- itp_interface/pisa/src/main/python/.idea/inspectionProfiles/Project_Default.xml +18 -0
- itp_interface/pisa/src/main/python/.idea/inspectionProfiles/profiles_settings.xml +6 -0
- itp_interface/pisa/src/main/python/.idea/misc.xml +4 -0
- itp_interface/pisa/src/main/python/.idea/modules.xml +8 -0
- itp_interface/pisa/src/main/python/.idea/python.iml +12 -0
- itp_interface/pisa/src/main/python/.idea/vcs.xml +6 -0
- itp_interface/pisa/src/main/python/conjecturing_parsing/conjecturer_postprocessing.py +59 -0
- itp_interface/pisa/src/main/python/data_extraction/extract_data.py +184 -0
- itp_interface/pisa/src/main/python/data_extraction/find_premises.py +221 -0
- itp_interface/pisa/src/main/python/data_extraction/process_data.py +129 -0
- itp_interface/pisa/src/main/python/legacy/PisaFlexibleClient.py +167 -0
- itp_interface/pisa/src/main/python/legacy/autof_test.py +74 -0
- itp_interface/pisa/src/main/python/legacy/cmd_client.py +23 -0
- itp_interface/pisa/src/main/python/legacy/convert_scala_dump_to_test_name_jsons.py +14 -0
- itp_interface/pisa/src/main/python/legacy/create_data_txt.py +72 -0
- itp_interface/pisa/src/main/python/legacy/create_finetune_tfrecords.py +311 -0
- itp_interface/pisa/src/main/python/legacy/demo.py +49 -0
- itp_interface/pisa/src/main/python/legacy/evaluate.py +108 -0
- itp_interface/pisa/src/main/python/legacy/extract_first_step.py +25 -0
- itp_interface/pisa/src/main/python/legacy/get_global_facts.py +35 -0
- itp_interface/pisa/src/main/python/legacy/mix_data.py +19 -0
- itp_interface/pisa/src/main/python/legacy/one_stage_extraction.py +111 -0
- itp_interface/pisa/src/main/python/legacy/prepare_episodic_transitions.py +137 -0
- itp_interface/pisa/src/main/python/legacy/prepare_translation_pairs.py +277 -0
- itp_interface/pisa/src/main/python/pisa_client.py +322 -0
- itp_interface/pisa/src/main/python/server_pb2.py +394 -0
- itp_interface/pisa/src/main/python/server_pb2_grpc.py +230 -0
- itp_interface/pisa/src/main/python/test_client.py +17 -0
- itp_interface/pisa/src/main/python/test_client2.py +79 -0
- itp_interface/pisa/src/main/python/utils/filters.py +59 -0
- itp_interface/pisa/src/main/python/utils/pisa_server_control.py +29 -0
- itp_interface/pisa/src/main/scala/pisa/agent/CheckSyntax.scala +257 -0
- itp_interface/pisa/src/main/scala/pisa/agent/DepThms.scala +29 -0
- itp_interface/pisa/src/main/scala/pisa/agent/PisaStat.scala +46 -0
- itp_interface/pisa/src/main/scala/pisa/agent/RefactorTest.scala +40 -0
- itp_interface/pisa/src/main/scala/pisa/agent/RepHammer.scala +95 -0
- itp_interface/pisa/src/main/scala/pisa/server/HammFacts.scala +63 -0
- itp_interface/pisa/src/main/scala/pisa/server/PisaOS.scala +881 -0
- itp_interface/pisa/src/main/scala/pisa/server/PisaOneStage.scala +540 -0
- itp_interface/pisa/src/main/scala/pisa/server/PisaOneStageServers.scala +1048 -0
- itp_interface/pisa/src/main/scala/pisa/utils/TheoryManager.scala +95 -0
- itp_interface/pisa/src/test/python/analyse_debug.py +33 -0
- itp_interface/pisa/src/test/python/extract_test_seq2seq.py +53 -0
- itp_interface/pisa/src/test/python/extract_test_theorem_ground_truth_indices.py +31 -0
- itp_interface/pisa/src/test/python/proof_originality.py +24 -0
- itp_interface/pisa/src/test/python/test_command_generator.py +25 -0
- itp_interface/pisa/src/test/python/test_model_sequence_accuracy.py +70 -0
- itp_interface/pisa/src/test/scala/pisa/Easy.scala +26 -0
- itp_interface/pisa/src/test/scala/pisa/TestCurl.scala +82 -0
- itp_interface/pisa/src/test/scala/pisa/TestIsa.scala +27 -0
- itp_interface/pisa/test.sh +19 -0
- itp_interface/pisa/universal_test_theorems.tar.gz +0 -0
- itp_interface/repo/build.py +78 -0
- itp_interface/repo/clone.py +79 -0
- itp_interface/repo/dataset_discovery.py +99 -0
- itp_interface/retrieval/__init__.py +0 -0
- itp_interface/retrieval/abstraction.py +35 -0
- itp_interface/retrieval/coq_bm25_reranker.py +153 -0
- itp_interface/retrieval/isabelle_bm25_reranker.py +86 -0
- itp_interface/retrieval/lean3_bm25_reranker.py +86 -0
- itp_interface/rl/__init__.py +0 -0
- itp_interface/rl/abstraction.py +168 -0
- itp_interface/rl/proof_action.py +172 -0
- itp_interface/rl/proof_state.py +149 -0
- itp_interface/rl/proof_tree.py +109 -0
- itp_interface/rl/simpl_proof_env_pool.py +16 -0
- itp_interface/rl/simple_proof_env.py +713 -0
- itp_interface/rl/simple_proof_env_pool.py +591 -0
- itp_interface/scripts/setup.sh +228 -0
- itp_interface/tools/__init__.py +0 -0
- itp_interface/tools/basic_utils.py +172 -0
- itp_interface/tools/bin_packing.py +61 -0
- itp_interface/tools/cache.py +93 -0
- itp_interface/tools/coq_build_spec.py +31 -0
- itp_interface/tools/coq_build_tool.py +319 -0
- itp_interface/tools/coq_context_helper.py +354 -0
- itp_interface/tools/coq_executor.py +508 -0
- itp_interface/tools/coq_local_data_generation_transform.py +158 -0
- itp_interface/tools/coq_parse_utils.py +154 -0
- itp_interface/tools/coq_raw_proofs.py +193 -0
- itp_interface/tools/coq_theorem_proof_pair_generation_transform.py +146 -0
- itp_interface/tools/coq_training_data_generator.py +76 -0
- itp_interface/tools/dynamic_coq_proof_exec.py +220 -0
- itp_interface/tools/dynamic_isabelle_proof_exec.py +229 -0
- itp_interface/tools/dynamic_lean4_proof_exec.py +236 -0
- itp_interface/tools/dynamic_lean_proof_exec.py +228 -0
- itp_interface/tools/isabelle_context_helper.py +66 -0
- itp_interface/tools/isabelle_executor.py +862 -0
- itp_interface/tools/isabelle_local_data_generation_transform.py +149 -0
- itp_interface/tools/isabelle_parse_utils.py +131 -0
- itp_interface/tools/isabelle_server.py +106 -0
- itp_interface/tools/lean4_context_helper.py +72 -0
- itp_interface/tools/lean4_local_data_generation_transform.py +122 -0
- itp_interface/tools/lean4_sync_executor.py +1193 -0
- itp_interface/tools/lean_cmd_executor.py +804 -0
- itp_interface/tools/lean_context_helper.py +327 -0
- itp_interface/tools/lean_dojo_data_generation_transform.py +206 -0
- itp_interface/tools/lean_executor.py +687 -0
- itp_interface/tools/lean_local_data_generation_transform.py +136 -0
- itp_interface/tools/lean_parse_utils.py +32 -0
- itp_interface/tools/log_utils.py +20 -0
- itp_interface/tools/proof_exec_callback.py +76 -0
- itp_interface/tools/ray_utils.py +265 -0
- itp_interface/tools/repl/.git +1 -0
- itp_interface/tools/repl/.github/workflows/ci.yml +24 -0
- itp_interface/tools/repl/.gitignore +7 -0
- itp_interface/tools/repl/.vscode/copyright.code-snippets +13 -0
- itp_interface/tools/repl/.vscode/extensions.json +13 -0
- itp_interface/tools/repl/.vscode/module-docstring.code-snippets +35 -0
- itp_interface/tools/repl/.vscode/settings.json +11 -0
- itp_interface/tools/repl/README.md +174 -0
- itp_interface/tools/repl/REPL/Frontend.lean +47 -0
- itp_interface/tools/repl/REPL/JSON.lean +186 -0
- itp_interface/tools/repl/REPL/Lean/ContextInfo.lean +9 -0
- itp_interface/tools/repl/REPL/Lean/Environment.lean +31 -0
- itp_interface/tools/repl/REPL/Lean/InfoTree/ToJson.lean +114 -0
- itp_interface/tools/repl/REPL/Lean/InfoTree.lean +272 -0
- itp_interface/tools/repl/REPL/Main.lean +323 -0
- itp_interface/tools/repl/REPL/Snapshots.lean +306 -0
- itp_interface/tools/repl/REPL/Util/Path.lean +36 -0
- itp_interface/tools/repl/REPL/Util/Pickle.lean +44 -0
- itp_interface/tools/repl/REPL.lean +4 -0
- itp_interface/tools/repl/lake-manifest.json +5 -0
- itp_interface/tools/repl/lakefile.lean +15 -0
- itp_interface/tools/repl/lean-toolchain +1 -0
- itp_interface/tools/repl/test/Mathlib/.gitignore +5 -0
- itp_interface/tools/repl/test/Mathlib/H20231110.sh +2 -0
- itp_interface/tools/repl/test/Mathlib/ReplMathlibTests.lean +1 -0
- itp_interface/tools/repl/test/Mathlib/lake-manifest.json +68 -0
- itp_interface/tools/repl/test/Mathlib/lakefile.lean +11 -0
- itp_interface/tools/repl/test/Mathlib/lean-toolchain +1 -0
- itp_interface/tools/repl/test/Mathlib/test/20240209.expected.out +20 -0
- itp_interface/tools/repl/test/Mathlib/test/20240209.in +3 -0
- itp_interface/tools/repl/test/Mathlib/test/20240209.lean +4 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231020.expected.out +8 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231020.in +8 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231020.lean +22 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231110.expected.out +4 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231110.in +4 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231115.expected.out +19 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231115.in +5 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231115_2.expected.out +18 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231115_2.in +4 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231115_3.expected.out +10 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231115_3.in +4 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231214.in +9 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231214.lean +30 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231215.expected.out +4 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231215.in +4 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231215_2.expected.out +14 -0
- itp_interface/tools/repl/test/Mathlib/test/H20231215_2.in +3 -0
- itp_interface/tools/repl/test/Mathlib/test/exact.expected.out +37 -0
- itp_interface/tools/repl/test/Mathlib/test/exact.in +10 -0
- itp_interface/tools/repl/test/Mathlib/test/import_Mathlib.lean +1 -0
- itp_interface/tools/repl/test/Mathlib/test/induction.expected.out +29 -0
- itp_interface/tools/repl/test/Mathlib/test/induction.in +10 -0
- itp_interface/tools/repl/test/Mathlib/test/induction.lean +6 -0
- itp_interface/tools/repl/test/Mathlib/test/on_goal.expected.out +22 -0
- itp_interface/tools/repl/test/Mathlib/test/on_goal.in +5 -0
- itp_interface/tools/repl/test/Mathlib/test/pickle.expected.out +16 -0
- itp_interface/tools/repl/test/Mathlib/test/pickle.in +6 -0
- itp_interface/tools/repl/test/Mathlib/test/pickle_2.expected.out +4 -0
- itp_interface/tools/repl/test/Mathlib/test/pickle_2.in +4 -0
- itp_interface/tools/repl/test/Mathlib/test.sh +41 -0
- itp_interface/tools/repl/test/all_tactics.expected.out +13 -0
- itp_interface/tools/repl/test/all_tactics.in +1 -0
- itp_interface/tools/repl/test/by_cases.expected.out +25 -0
- itp_interface/tools/repl/test/by_cases.in +8 -0
- itp_interface/tools/repl/test/by_cases.lean +4 -0
- itp_interface/tools/repl/test/calc.expected.out +32 -0
- itp_interface/tools/repl/test/calc.in +1 -0
- itp_interface/tools/repl/test/def_eval.expected.out +9 -0
- itp_interface/tools/repl/test/def_eval.in +3 -0
- itp_interface/tools/repl/test/enableInitializersExecution.expected.out +2 -0
- itp_interface/tools/repl/test/enableInitializersExecution.in +1 -0
- itp_interface/tools/repl/test/file.expected.out +8 -0
- itp_interface/tools/repl/test/file.in +1 -0
- itp_interface/tools/repl/test/file.lean +5 -0
- itp_interface/tools/repl/test/have_by_sorry.expected.out +28 -0
- itp_interface/tools/repl/test/have_by_sorry.in +6 -0
- itp_interface/tools/repl/test/import_lean.in +1 -0
- itp_interface/tools/repl/test/incomplete.expected.out +18 -0
- itp_interface/tools/repl/test/incomplete.in +3 -0
- itp_interface/tools/repl/test/incomplete.lean +0 -0
- itp_interface/tools/repl/test/infotree.expected.out +20 -0
- itp_interface/tools/repl/test/infotree.in +2 -0
- itp_interface/tools/repl/test/invalid_tactic.expected.out +20 -0
- itp_interface/tools/repl/test/invalid_tactic.in +3 -0
- itp_interface/tools/repl/test/name_generator.expected.out +53 -0
- itp_interface/tools/repl/test/name_generator.in +18 -0
- itp_interface/tools/repl/test/no_goal_sorry.expected.out +11 -0
- itp_interface/tools/repl/test/no_goal_sorry.in +1 -0
- itp_interface/tools/repl/test/no_goal_sorry_2.expected.out +12 -0
- itp_interface/tools/repl/test/no_goal_sorry_2.in +1 -0
- itp_interface/tools/repl/test/options.expected.out +17 -0
- itp_interface/tools/repl/test/options.in +6 -0
- itp_interface/tools/repl/test/pickle_environment.expected.out +8 -0
- itp_interface/tools/repl/test/pickle_environment.in +7 -0
- itp_interface/tools/repl/test/pickle_environment_with_imports.expected.out +10 -0
- itp_interface/tools/repl/test/pickle_environment_with_imports.in +9 -0
- itp_interface/tools/repl/test/pickle_open.expected.out +8 -0
- itp_interface/tools/repl/test/pickle_open.in +7 -0
- itp_interface/tools/repl/test/pickle_open_2.expected.out +4 -0
- itp_interface/tools/repl/test/pickle_open_2.in +3 -0
- itp_interface/tools/repl/test/pickle_open_scoped.expected.out +18 -0
- itp_interface/tools/repl/test/pickle_open_scoped.in +8 -0
- itp_interface/tools/repl/test/pickle_open_scoped_2.expected.out +14 -0
- itp_interface/tools/repl/test/pickle_open_scoped_2.in +3 -0
- itp_interface/tools/repl/test/pickle_proof_state_1.expected.out +26 -0
- itp_interface/tools/repl/test/pickle_proof_state_1.in +15 -0
- itp_interface/tools/repl/test/pickle_proof_state_2.expected.out +4 -0
- itp_interface/tools/repl/test/pickle_proof_state_2.in +3 -0
- itp_interface/tools/repl/test/pickle_proof_state_env.expected.out +26 -0
- itp_interface/tools/repl/test/pickle_proof_state_env.in +15 -0
- itp_interface/tools/repl/test/pickle_scoped_notation.in +16 -0
- itp_interface/tools/repl/test/pickle_scoped_notation_2.in +3 -0
- itp_interface/tools/repl/test/proof_step.expected.out +18 -0
- itp_interface/tools/repl/test/proof_step.in +7 -0
- itp_interface/tools/repl/test/readme.expected.out +16 -0
- itp_interface/tools/repl/test/readme.in +5 -0
- itp_interface/tools/repl/test/sorry_hypotheses.expected.out +16 -0
- itp_interface/tools/repl/test/sorry_hypotheses.in +4 -0
- itp_interface/tools/repl/test/synthesize_placeholder.expected.out +7 -0
- itp_interface/tools/repl/test/synthesize_placeholder.in +1 -0
- itp_interface/tools/repl/test/tactic_mode_sorry.expected.out +14 -0
- itp_interface/tools/repl/test/tactic_mode_sorry.in +3 -0
- itp_interface/tools/repl/test/tactic_sorry.expected.out +12 -0
- itp_interface/tools/repl/test/tactic_sorry.in +1 -0
- itp_interface/tools/repl/test/term_sorry.expected.out +12 -0
- itp_interface/tools/repl/test/term_sorry.in +1 -0
- itp_interface/tools/repl/test/trace_simp.expected.out +41 -0
- itp_interface/tools/repl/test/trace_simp.in +15 -0
- itp_interface/tools/repl/test/unfinished_tactic_block.expected.out +11 -0
- itp_interface/tools/repl/test/unfinished_tactic_block.in +1 -0
- itp_interface/tools/repl/test/unknown_environment.expected.out +2 -0
- itp_interface/tools/repl/test/unknown_environment.in +1 -0
- itp_interface/tools/repl/test/unknown_proof_state.expected.out +14 -0
- itp_interface/tools/repl/test/unknown_proof_state.in +3 -0
- itp_interface/tools/repl/test/unknown_tactic.expected.out +14 -0
- itp_interface/tools/repl/test/unknown_tactic.in +3 -0
- itp_interface/tools/repl/test/variables.expected.out +26 -0
- itp_interface/tools/repl/test/variables.in +5 -0
- itp_interface/tools/repl/test.sh +43 -0
- itp_interface/tools/run_data_generation_transforms.py +350 -0
- itp_interface/tools/theorem_details.py +25 -0
- itp_interface/tools/training_data.py +358 -0
- itp_interface/tools/training_data_format.py +599 -0
- itp_interface-1.0.0.dist-info/METADATA +78 -0
- itp_interface-1.0.0.dist-info/RECORD +485 -0
- itp_interface-1.0.0.dist-info/WHEEL +4 -0
- itp_interface-1.0.0.dist-info/entry_points.txt +3 -0
- itp_interface-1.0.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,862 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import signal
|
|
4
|
+
import sys
|
|
5
|
+
root_dir = f"{__file__.split('itp_interface')[0]}"
|
|
6
|
+
if root_dir not in sys.path:
|
|
7
|
+
sys.path.append(root_dir)
|
|
8
|
+
import os
|
|
9
|
+
import subprocess
|
|
10
|
+
import logging
|
|
11
|
+
import typing
|
|
12
|
+
import functools
|
|
13
|
+
import re
|
|
14
|
+
import time
|
|
15
|
+
import threading
|
|
16
|
+
from collections import OrderedDict
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from enum import Enum
|
|
19
|
+
from itp_interface.pisa.src.main.python.pisa_client import PisaEnv, initialise_env, IsabelleLemma
|
|
20
|
+
from itp_interface.tools.isabelle_parse_utils import IsabelleLineByLineReader, IsabelleStepByStepStdInReader
|
|
21
|
+
logger = logging.getLogger()
|
|
22
|
+
|
|
23
|
+
class Obligation(typing.NamedTuple):
|
|
24
|
+
hypotheses: typing.List[str]
|
|
25
|
+
goal: str
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def from_dict(cls, data):
|
|
29
|
+
return cls(**data)
|
|
30
|
+
|
|
31
|
+
def to_dict(self) -> typing.Dict[str, typing.Any]:
|
|
32
|
+
return {"hypotheses": self.hypotheses,
|
|
33
|
+
"goal": self.goal}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ProofContext(typing.NamedTuple):
|
|
37
|
+
fg_goals: typing.List[Obligation]
|
|
38
|
+
bg_goals: typing.List[Obligation]
|
|
39
|
+
shelved_goals: typing.List[Obligation]
|
|
40
|
+
given_up_goals: typing.List[Obligation]
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def empty(cls: typing.Type['ProofContext']):
|
|
44
|
+
return ProofContext([], [], [], [])
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_dict(cls, data):
|
|
48
|
+
fg_goals = list(map(Obligation.from_dict, data["fg_goals"]))
|
|
49
|
+
bg_goals = list(map(Obligation.from_dict, data["bg_goals"]))
|
|
50
|
+
shelved_goals = list(map(Obligation.from_dict, data["shelved_goals"]))
|
|
51
|
+
given_up_goals = list(map(Obligation.from_dict,
|
|
52
|
+
data["given_up_goals"]))
|
|
53
|
+
return cls(fg_goals, bg_goals, shelved_goals, given_up_goals)
|
|
54
|
+
|
|
55
|
+
def to_dict(self) -> typing.Dict[str, typing.Any]:
|
|
56
|
+
return {"fg_goals": list(map(Obligation.to_dict, self.fg_goals)),
|
|
57
|
+
"bg_goals": list(map(Obligation.to_dict, self.bg_goals)),
|
|
58
|
+
"shelved_goals": list(map(Obligation.to_dict,
|
|
59
|
+
self.shelved_goals)),
|
|
60
|
+
"given_up_goals": list(map(Obligation.to_dict,
|
|
61
|
+
self.given_up_goals))}
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def all_goals(self) -> typing.List[Obligation]:
|
|
65
|
+
return self.fg_goals + self.bg_goals + \
|
|
66
|
+
self.shelved_goals + self.given_up_goals
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def focused_goal(self) -> str:
|
|
70
|
+
if self.fg_goals:
|
|
71
|
+
return self.fg_goals[0].goal
|
|
72
|
+
else:
|
|
73
|
+
return ""
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def focused_hyps(self) -> typing.List[str]:
|
|
77
|
+
if self.fg_goals:
|
|
78
|
+
return self.fg_goals[0].hypotheses
|
|
79
|
+
else:
|
|
80
|
+
return []
|
|
81
|
+
|
|
82
|
+
class HammerMode(Enum):
|
|
83
|
+
NONE = 'NONE' # Prohibit hammer
|
|
84
|
+
ALLOW = 'ALLOW' # Allow agent to query hammer
|
|
85
|
+
AUTO = 'AUTO' # Automatically apply hammer to individual tactics (heuristically)
|
|
86
|
+
ONESHOT = 'ONESHOT' # Proof attempt in one shot using hammer
|
|
87
|
+
ALWAYS = 'ALWAYS' # Always use hammer on thesis after a successful proof attempt
|
|
88
|
+
|
|
89
|
+
def __str__(self):
|
|
90
|
+
return self.name
|
|
91
|
+
|
|
92
|
+
class IsabelleExecutor:
|
|
93
|
+
# This doesn't do the best job of capturing each state changing
|
|
94
|
+
# tactic separately. It relies on the fact the tactics are usually written in an
|
|
95
|
+
# atomic way on separate lines. However for a simple REPL, we can just assume that
|
|
96
|
+
# the user writes tactics in an atomic way.
|
|
97
|
+
|
|
98
|
+
# Keywords list may not be complete
|
|
99
|
+
keywords = {
|
|
100
|
+
"section", "theory", "imports", "begin", "end", "text", "lemma", "theorem", "assume", "assumes", "proof", "have",
|
|
101
|
+
"fix", "show", "shows", "then", "with", "qed", "next", "obtain", "by", "for", "?thesis", "contradiction",
|
|
102
|
+
"datatype", "fun", "where", "subsection", "term", "value", "declare", "using", "case"
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# Matches theorem declarations
|
|
106
|
+
theorem_regex = r"((((theorem\s+|lemma\s+)([\w+|\d+'_]*)))(\s*:\s*)?([\S|\s]*))"
|
|
107
|
+
theorem_match = re.compile(theorem_regex, re.MULTILINE)
|
|
108
|
+
|
|
109
|
+
# Matches proof context returned by Isabelle engine
|
|
110
|
+
proof_context_regex = r"\s*proof \((state|prove|chain)\)\s*((using )?this:([\s|\S]*?))?goal([\s|\S]*?):\s*([\s|\S]*)"
|
|
111
|
+
proof_context_match = re.compile(proof_context_regex, re.MULTILINE)
|
|
112
|
+
|
|
113
|
+
# Matches theory initialization
|
|
114
|
+
begin_theory_regex = r"theory([\s\S]*)imports([\s\S]*)begin"
|
|
115
|
+
begin_theory_match = re.compile(begin_theory_regex, re.MULTILINE)
|
|
116
|
+
|
|
117
|
+
# Matches 'assms_x:' in hypotheses
|
|
118
|
+
assms_regex = r"assms_(\d+):"
|
|
119
|
+
assms_regex_match = re.compile(assms_regex)
|
|
120
|
+
|
|
121
|
+
# Proof automation tactics: [tactics from LYRA] + `algebra`
|
|
122
|
+
auto_tactics = ["auto", "simp", "blast", "fastforce", "force", "eval", "presburger", "sos", "arith", "linarith", "(auto simp: field_simps)", "algebra"]
|
|
123
|
+
|
|
124
|
+
def __init__(self, project_root: str = None, main_file: str = None, use_hammer: HammerMode = HammerMode.AUTO, timeout_in_sec: int = 60,
|
|
125
|
+
use_human_readable_proof_context: bool = False, proof_step_iter: typing.Iterator[str] = None,
|
|
126
|
+
suppress_error_log: bool = False, port: int = 8000):
|
|
127
|
+
assert proof_step_iter is None or isinstance(proof_step_iter, typing.Iterator), \
|
|
128
|
+
"proof_step_iter must be an iterator"
|
|
129
|
+
assert main_file is not None or proof_step_iter is not None, \
|
|
130
|
+
"Either main_file or proof_step_iter must be provided"
|
|
131
|
+
assert (main_file is None) or (project_root is not None), \
|
|
132
|
+
"Project root must be provided for Isabelle, if main file is provided"
|
|
133
|
+
assert main_file is None or (os.path.exists(main_file) and main_file.endswith(".thy")), \
|
|
134
|
+
"main_file must be a valid path to a '.thy' file"
|
|
135
|
+
assert project_root is None or (os.path.exists(project_root) and os.path.isdir(project_root)), \
|
|
136
|
+
"project_root must be a valid path to a directory"
|
|
137
|
+
self.use_human_readable_proof_context = use_human_readable_proof_context
|
|
138
|
+
self.project_root = project_root if project_root is not None else "."
|
|
139
|
+
self.main_file = main_file
|
|
140
|
+
self.use_hammer = use_hammer
|
|
141
|
+
self.timeout_in_sec = min(timeout_in_sec, 120) # Maximum 120s timeout
|
|
142
|
+
self.current_stmt = None
|
|
143
|
+
self.line_num = 0
|
|
144
|
+
self.current_state = 0
|
|
145
|
+
self.line_num_to_state = {}
|
|
146
|
+
self.main_file_iter = proof_step_iter
|
|
147
|
+
self.buffer = ""
|
|
148
|
+
self.suppress_error_log = suppress_error_log
|
|
149
|
+
self.pisa_env : PisaEnv = None
|
|
150
|
+
self.proof_context : ProofContext = None
|
|
151
|
+
self.curr_lemma_name : typing.Optional[str] = None
|
|
152
|
+
self.curr_lemma : typing.Optional[str] = ""
|
|
153
|
+
self._proof_running = False
|
|
154
|
+
self._top_level = True
|
|
155
|
+
self.local_theorem_lemma_description: typing.OrderedDict[str, str] = OrderedDict()
|
|
156
|
+
self.execution_complete = False
|
|
157
|
+
self.global_lemmas = []
|
|
158
|
+
self.port = int(os.environ.get("PISA_PORT", port))
|
|
159
|
+
self._seldgehammer_cache : typing.Dict[int,typing.Dict[str, str]] = {}
|
|
160
|
+
home_dir = str(Path.home())
|
|
161
|
+
if os.path.exists(os.path.join(home_dir, "Isabelle2022")):
|
|
162
|
+
self.isa_install_dir = os.path.join(home_dir, "Isabelle2022")
|
|
163
|
+
else:
|
|
164
|
+
raise Exception("Isabelle2022 installation not found. Please install Isabelle2022 and set the path to the installation directory in the environment variable 'ISABELLE_HOME'")
|
|
165
|
+
|
|
166
|
+
def __enter__(self):
|
|
167
|
+
self._all_dep_handles = []
|
|
168
|
+
|
|
169
|
+
if self.main_file_iter is None:
|
|
170
|
+
self.main_file_iter = IsabelleLineByLineReader(self.main_file).instruction_step_generator()
|
|
171
|
+
|
|
172
|
+
# PISA clients must provide a file and working directory. If these are not provided,
|
|
173
|
+
# or if the file path is not supported by PISA, use the default header, which may or may not be sufficient.
|
|
174
|
+
if self.main_file is None:
|
|
175
|
+
logger.warning("Initialising Isabelle environment with default theory header and imports (Complex_Main). Pass in a file and project root to import additional theories")
|
|
176
|
+
default_theory_file_path = os.path.join(self.isa_install_dir, "src/HOL/Library/Discrete.thy")
|
|
177
|
+
default_working_directory = os.path.join(self.isa_install_dir, "src/HOL/Library")
|
|
178
|
+
self.pisa_env = initialise_env(port=self.port, isa_path=self.isa_install_dir, theory_file_path=default_theory_file_path, working_directory=default_working_directory)
|
|
179
|
+
self.pisa_env.initialise()
|
|
180
|
+
else:
|
|
181
|
+
try:
|
|
182
|
+
self.pisa_env = initialise_env(port=self.port, theory_file_path=self.main_file, working_directory=self.project_root)
|
|
183
|
+
self.pisa_env.initialise()
|
|
184
|
+
except:
|
|
185
|
+
logger.warning("Theory initialization failed. Most likely this file path is not supported by PISA.")
|
|
186
|
+
logger.warning("Initialising Isabelle environment with default theory header and imports (Complex_Main).")
|
|
187
|
+
self.pisa_env = initialise_env(port=self.port)
|
|
188
|
+
self.pisa_env.initialise()
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
return self
|
|
192
|
+
|
|
193
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
194
|
+
try:
|
|
195
|
+
self.main_file_iter.close() # Close the file handle
|
|
196
|
+
except:
|
|
197
|
+
pass
|
|
198
|
+
|
|
199
|
+
def start_server(logger : logging.Logger = None, port: int = 8000):
|
|
200
|
+
if "PISA_PORT" in os.environ:
|
|
201
|
+
port = int(os.environ["PISA_PORT"])
|
|
202
|
+
else:
|
|
203
|
+
os.environ["PISA_PORT"] = str(port)
|
|
204
|
+
assert port > 0, "Port number must be greater than 0"
|
|
205
|
+
assert port < 65536, "Port number must be less than 65536"
|
|
206
|
+
jar_path = "itp_interface/pisa/target/scala-2.13/PISA-assembly-0.1.jar"
|
|
207
|
+
assert os.path.exists(jar_path), "PISA jar file not found. Please build the project using 'sbt assembly' commnad"
|
|
208
|
+
logger = logger if logger is not None else logging.getLogger('isabelle_pisa_executor')
|
|
209
|
+
cmd = f"java -cp {jar_path} pisa.server.PisaOneStageServer{port}"
|
|
210
|
+
# Start the server in a separate process
|
|
211
|
+
cwd = os.getcwd()
|
|
212
|
+
server_process = subprocess.Popen(
|
|
213
|
+
cmd,
|
|
214
|
+
cwd=cwd,
|
|
215
|
+
shell=True,
|
|
216
|
+
stdout=subprocess.PIPE,
|
|
217
|
+
stderr=subprocess.PIPE,
|
|
218
|
+
preexec_fn=os.setsid) # Create a new process group so that we can kill the process and all its children
|
|
219
|
+
pid = server_process.pid
|
|
220
|
+
os.environ["PISA_SERVER_PID"] = str(pid)
|
|
221
|
+
# Log the process id
|
|
222
|
+
logger.info(f"Server process id: {pid}")
|
|
223
|
+
# Log the port number
|
|
224
|
+
logger.info(f"Server port: {port}")
|
|
225
|
+
logger.info("Waiting for server to start")
|
|
226
|
+
time.sleep(5)
|
|
227
|
+
server_running = IsabelleExecutor.check_server_running(logger)
|
|
228
|
+
if not server_running:
|
|
229
|
+
logger.error(f"Server is not running on port {port}")
|
|
230
|
+
else:
|
|
231
|
+
thread = threading.Thread(target=IsabelleExecutor._server_loggening_thread, args=(logger, server_process))
|
|
232
|
+
thread.start()
|
|
233
|
+
thread_id = thread.ident
|
|
234
|
+
os.environ["PISA_SERVER_THREAD_ID"] = str(thread_id)
|
|
235
|
+
pass
|
|
236
|
+
|
|
237
|
+
def check_server_running(logger : logging.Logger):
|
|
238
|
+
assert "PISA_PORT" in os.environ, "PISA_PORT environment variable is not set"
|
|
239
|
+
port = int(os.environ["PISA_PORT"])
|
|
240
|
+
# log the netsat result netstat -nlp | grep :{port}
|
|
241
|
+
netstat_cmd = f"netstat -nlp | grep :{port}"
|
|
242
|
+
logger.info(f"Netstat command: {netstat_cmd}")
|
|
243
|
+
output = subprocess.run(netstat_cmd, shell=True, capture_output=True)
|
|
244
|
+
logger.info(f"Netstat output: {output}")
|
|
245
|
+
output_str = output.stdout.decode("utf-8")
|
|
246
|
+
logger.info(f"Netstat output stdout: {output_str}")
|
|
247
|
+
server_running = "tcp" in output_str
|
|
248
|
+
return server_running
|
|
249
|
+
|
|
250
|
+
def _server_loggening_thread(logger : logging.Logger, process: subprocess.Popen):
|
|
251
|
+
# Keep checking the server is running
|
|
252
|
+
process_killed = False
|
|
253
|
+
while not process_killed:
|
|
254
|
+
try:
|
|
255
|
+
line = process.stdout.readline()
|
|
256
|
+
if not line:
|
|
257
|
+
break
|
|
258
|
+
logger.info(line)
|
|
259
|
+
except:
|
|
260
|
+
logger.info("Stdout is closed")
|
|
261
|
+
time.sleep(1)
|
|
262
|
+
# Reload the environment variables as they are shared across threads (not processes)
|
|
263
|
+
process_killed = os.environ.get("PISA_PROCESS_KILLED", "False") == "True"
|
|
264
|
+
logger.info("Server is shut down")
|
|
265
|
+
# Print the environment variables
|
|
266
|
+
logger.info(f"Environment variables at shutdown time: {os.environ}")
|
|
267
|
+
time.sleep(1)
|
|
268
|
+
pass
|
|
269
|
+
|
|
270
|
+
def stop_server():
|
|
271
|
+
os.environ["PISA_PROCESS_KILLED"] = "True"
|
|
272
|
+
pisa_pid = int(os.environ["PISA_SERVER_PID"])
|
|
273
|
+
try:
|
|
274
|
+
# Kill the server process
|
|
275
|
+
os.killpg(pisa_pid, signal.SIGTERM)
|
|
276
|
+
except:
|
|
277
|
+
pass
|
|
278
|
+
if "PISA_SERVER_THREAD_ID" in os.environ:
|
|
279
|
+
thread_id = int(os.environ["PISA_SERVER_THREAD_ID"])
|
|
280
|
+
# Find the right thread object
|
|
281
|
+
for thread in threading.enumerate():
|
|
282
|
+
if thread.ident == thread_id:
|
|
283
|
+
thread.join(5)
|
|
284
|
+
break
|
|
285
|
+
os.unsetenv("PISA_SERVER_THREAD_ID")
|
|
286
|
+
# Reset the environment variables
|
|
287
|
+
os.unsetenv("PISA_PROCESS_KILLED")
|
|
288
|
+
os.unsetenv("PISA_SERVER_PID")
|
|
289
|
+
pass
|
|
290
|
+
|
|
291
|
+
# The following token separators may not be completely correct
|
|
292
|
+
|
|
293
|
+
@property
|
|
294
|
+
def token_separator_set(self):
|
|
295
|
+
return set(" ()[]{}.,;:+-*/=<>!~?@#$%^&|`\"\\")
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def token_separator(self):
|
|
299
|
+
return " ()[]{}.,;:+-*/=<>!~?@#$%^&|`\"\\"
|
|
300
|
+
|
|
301
|
+
@property
|
|
302
|
+
def token_separator_regex(self):
|
|
303
|
+
return "\s+|\(|\)|\[|\]|\{|\}|\.|,|;|:|\?|@|#|\$|%|\^|&|\||`|\"|\\\\" +\
|
|
304
|
+
""#"|\+|-|\*|/|=|<|>|!|~"
|
|
305
|
+
|
|
306
|
+
@staticmethod
|
|
307
|
+
def get_token_separator_set():
|
|
308
|
+
return set(" ()[]{}.,;:+-*/=<>!~?@#$%^&|`\"\\")
|
|
309
|
+
|
|
310
|
+
@staticmethod
|
|
311
|
+
def get_token_separators():
|
|
312
|
+
return " ()[]{}.,;:+-*/=<>!~?@#$%^&|`\"\\"
|
|
313
|
+
|
|
314
|
+
@staticmethod
|
|
315
|
+
def get_token_separator_regex():
|
|
316
|
+
return "\s+|\(|\)|\[|\]|\{|\}|\.|,|;|:|\?|@|#|\$|%|\^|&|\||`|\"|\\\\" +\
|
|
317
|
+
""#"|\+|-|\*|/|=|<|>|!|~"
|
|
318
|
+
|
|
319
|
+
def is_in_proof_mode(self):
|
|
320
|
+
return True if self.proof_context else False
|
|
321
|
+
|
|
322
|
+
def needs_qed(self):
|
|
323
|
+
return self.proof_context is not None and len(self.proof_context.all_goals) == 0
|
|
324
|
+
|
|
325
|
+
def needs_cut_close(self):
|
|
326
|
+
# Not supported. Even if there is a nested proof, we still can use `qed` to close the proof
|
|
327
|
+
return False
|
|
328
|
+
|
|
329
|
+
def get_state_str(self, state_num):
|
|
330
|
+
if state_num == 0:
|
|
331
|
+
return 'default'
|
|
332
|
+
return 'state' + str(state_num)
|
|
333
|
+
|
|
334
|
+
def run_next(self, proof_search_mode=True) -> str:
|
|
335
|
+
try:
|
|
336
|
+
stmt = next(self.main_file_iter)
|
|
337
|
+
except StopIteration:
|
|
338
|
+
self.execution_complete = True
|
|
339
|
+
return ""
|
|
340
|
+
self.current_stmt = stmt
|
|
341
|
+
self.line_num += 1
|
|
342
|
+
try:
|
|
343
|
+
stmt = self._run_stmt_on_isabelle_server(stmt, proof_search_mode)
|
|
344
|
+
except:
|
|
345
|
+
if proof_search_mode:
|
|
346
|
+
if not self.suppress_error_log:
|
|
347
|
+
logger.error(f"Got an exception while running '{stmt}' on isabelle. File name: {self.main_file}")
|
|
348
|
+
logger.exception(f"Exception Log")
|
|
349
|
+
raise
|
|
350
|
+
else:
|
|
351
|
+
# If we're not in proof search mode, we can assume any errors are expected
|
|
352
|
+
pass
|
|
353
|
+
return stmt
|
|
354
|
+
|
|
355
|
+
def get_tokens_in_given_stmt(self, stmt: str, ignore_first_token: bool = False) -> typing.Generator[str, None, None]:
|
|
356
|
+
idx = -1
|
|
357
|
+
for tok in re.split(self.token_separator_regex, stmt):
|
|
358
|
+
idx += 1
|
|
359
|
+
# skip the first token as it is usually a keyword
|
|
360
|
+
if idx == 0 and ignore_first_token:
|
|
361
|
+
continue
|
|
362
|
+
tok1 = tok.strip()
|
|
363
|
+
if len(tok1) > 0:
|
|
364
|
+
yield tok1
|
|
365
|
+
|
|
366
|
+
def tokenize(stmt: str) -> typing.Generator[str, None, None]:
|
|
367
|
+
for tok in re.split(IsabelleExecutor.get_token_separator_regex(), stmt):
|
|
368
|
+
tok1 = tok.strip()
|
|
369
|
+
if len(tok1) > 0:
|
|
370
|
+
yield tok1
|
|
371
|
+
|
|
372
|
+
# Make this chacheable
|
|
373
|
+
# @functools.lru_cache(maxsize=10000)
|
|
374
|
+
def search_type_matching_defns(self, name: str) -> typing.List[IsabelleLemma]:
|
|
375
|
+
if name in IsabelleExecutor.keywords:
|
|
376
|
+
return []
|
|
377
|
+
if not self.global_lemmas:
|
|
378
|
+
assert not self.current_state == 0, 'Search tool cannot be used in top level state (before imports)'
|
|
379
|
+
self.global_lemmas = self.pisa_env.get_global_lemmas(self.get_state_str(self.current_state))
|
|
380
|
+
return self.global_lemmas
|
|
381
|
+
|
|
382
|
+
def get_all_type_matching_defns(self, name: str) -> typing.Generator[IsabelleLemma, None, None]:
|
|
383
|
+
return self.search_type_matching_defns(name)
|
|
384
|
+
|
|
385
|
+
def search_exact(self, name: str) -> typing.List[IsabelleLemma]:
|
|
386
|
+
return self.search_type_matching_defns(name)
|
|
387
|
+
|
|
388
|
+
def search_defn(self, name: str, match_until: typing.Tuple[str], max_search_res: typing.Optional[int] = None) -> typing.List[IsabelleLemma]:
|
|
389
|
+
return self.search_type_matching_defns(name)
|
|
390
|
+
|
|
391
|
+
def run_without_executing(self, stmt: str):
|
|
392
|
+
while True:
|
|
393
|
+
try:
|
|
394
|
+
stmt = next(self.main_file_iter)
|
|
395
|
+
except StopIteration:
|
|
396
|
+
return
|
|
397
|
+
self.current_stmt = stmt
|
|
398
|
+
self.line_num += 1
|
|
399
|
+
|
|
400
|
+
def run_lemma_without_executing(self):
|
|
401
|
+
while True:
|
|
402
|
+
try:
|
|
403
|
+
stmt = next(self.main_file_iter)
|
|
404
|
+
self.current_stmt = stmt
|
|
405
|
+
self.line_num += 1
|
|
406
|
+
if "qed" in stmt or "sorry" in stmt or "oops" in stmt:
|
|
407
|
+
return True
|
|
408
|
+
except StopIteration:
|
|
409
|
+
return False
|
|
410
|
+
|
|
411
|
+
def rewind_proof_steps(self) -> str:
|
|
412
|
+
raise NotImplementedError("rewind_proof_steps is not implemented")
|
|
413
|
+
|
|
414
|
+
def run_till_next_lemma(self) -> typing.Tuple[bool, typing.Optional[str]]:
|
|
415
|
+
# Run the file until the next lemma is found
|
|
416
|
+
next_stmt = None
|
|
417
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
418
|
+
if in_proof_mode or self.execution_complete:
|
|
419
|
+
# If we are already in proof mode, then we have already found a lemma
|
|
420
|
+
return False, next_stmt
|
|
421
|
+
prev_stmt = self.current_stmt
|
|
422
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
423
|
+
next_stmt = self.current_stmt
|
|
424
|
+
if not ran_last_cmd:
|
|
425
|
+
return False, None
|
|
426
|
+
assigned = False
|
|
427
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
428
|
+
while ran_last_cmd and not in_proof_mode:
|
|
429
|
+
if not assigned:
|
|
430
|
+
prev_stmt = next_stmt
|
|
431
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
432
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
433
|
+
if not assigned:
|
|
434
|
+
next_stmt = self.current_stmt
|
|
435
|
+
if in_proof_mode:
|
|
436
|
+
assigned = True
|
|
437
|
+
lemma_name = next_stmt if next_stmt.startswith("theorem") or next_stmt.startswith("lemma") else prev_stmt
|
|
438
|
+
return in_proof_mode, lemma_name
|
|
439
|
+
|
|
440
|
+
def run_till_next_lemma_return_exec_stmt(self) -> typing.Generator[str, None, None]:
|
|
441
|
+
# Run the file until the next lemma is found
|
|
442
|
+
next_stmt = None
|
|
443
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
444
|
+
if in_proof_mode or self.execution_complete:
|
|
445
|
+
# If we are already in proof mode, then we have already found a lemma
|
|
446
|
+
yield from []
|
|
447
|
+
else:
|
|
448
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
449
|
+
next_stmt = self.current_stmt
|
|
450
|
+
if not ran_last_cmd:
|
|
451
|
+
yield from []
|
|
452
|
+
else:
|
|
453
|
+
yield next_stmt
|
|
454
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
455
|
+
while ran_last_cmd and not in_proof_mode:
|
|
456
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
457
|
+
next_stmt = self.current_stmt
|
|
458
|
+
if ran_last_cmd:
|
|
459
|
+
yield next_stmt
|
|
460
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
461
|
+
|
|
462
|
+
def run_to_finish_lemma_return_exec(self) -> typing.Generator[str, None, None]:
|
|
463
|
+
# Run the file until the next lemma is found
|
|
464
|
+
next_stmt = None
|
|
465
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
466
|
+
if not in_proof_mode or self.execution_complete:
|
|
467
|
+
# If we are already in proof mode, then we have already found a lemma
|
|
468
|
+
yield from []
|
|
469
|
+
else:
|
|
470
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
471
|
+
next_stmt = self.current_stmt
|
|
472
|
+
if not ran_last_cmd:
|
|
473
|
+
yield from []
|
|
474
|
+
else:
|
|
475
|
+
yield next_stmt
|
|
476
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
477
|
+
while ran_last_cmd and in_proof_mode:
|
|
478
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
479
|
+
next_stmt = self.current_stmt
|
|
480
|
+
if ran_last_cmd:
|
|
481
|
+
yield next_stmt
|
|
482
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
483
|
+
|
|
484
|
+
def run_to_finish_lemma(self) -> bool:
|
|
485
|
+
# Run the file and finish the current lemma
|
|
486
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
487
|
+
if not in_proof_mode or self.execution_complete:
|
|
488
|
+
# If we are not in proof mode, then we are not finishing a lemma
|
|
489
|
+
return False
|
|
490
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
491
|
+
if not ran_last_cmd:
|
|
492
|
+
return False
|
|
493
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
494
|
+
while ran_last_cmd and in_proof_mode:
|
|
495
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
496
|
+
in_proof_mode = self.is_in_proof_mode()
|
|
497
|
+
return not in_proof_mode
|
|
498
|
+
|
|
499
|
+
def run_till_line_num(self, line_num: int):
|
|
500
|
+
assert line_num >= self.line_num
|
|
501
|
+
ran_last_cmd = True
|
|
502
|
+
while ran_last_cmd and self.line_num < line_num:
|
|
503
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
504
|
+
return self.line_num
|
|
505
|
+
|
|
506
|
+
def run_to_finish(self):
|
|
507
|
+
ran_last_cmd = True
|
|
508
|
+
while ran_last_cmd:
|
|
509
|
+
ran_last_cmd = self.run_next(proof_search_mode=False)
|
|
510
|
+
|
|
511
|
+
def get_lemma_name_if_running(self) -> typing.Optional[str]:
|
|
512
|
+
if not self.is_in_proof_mode():
|
|
513
|
+
return None
|
|
514
|
+
else:
|
|
515
|
+
try:
|
|
516
|
+
return self.curr_lemma_name
|
|
517
|
+
except:
|
|
518
|
+
return None
|
|
519
|
+
|
|
520
|
+
def get_lemma_stmt_if_running(self) -> typing.Optional[str]:
|
|
521
|
+
if not self.is_in_proof_mode():
|
|
522
|
+
return None
|
|
523
|
+
else:
|
|
524
|
+
try:
|
|
525
|
+
return self.local_theorem_lemma_description[self.curr_lemma_name]
|
|
526
|
+
except:
|
|
527
|
+
return None
|
|
528
|
+
|
|
529
|
+
def get_current_lemma_name(self) -> typing.Optional[str]:
|
|
530
|
+
if self.curr_lemma_name is None:
|
|
531
|
+
return None
|
|
532
|
+
else:
|
|
533
|
+
return self.curr_lemma_name
|
|
534
|
+
|
|
535
|
+
def _run_stmt_on_isabelle_server(self, stmt: str, proof_search_mode=True) -> str:
|
|
536
|
+
begin_clause = []
|
|
537
|
+
last_thm_details = []
|
|
538
|
+
start_state = self.get_state_str(self.current_state)
|
|
539
|
+
end_state = self.get_state_str(self.current_state + 1)
|
|
540
|
+
found_lemma = False
|
|
541
|
+
|
|
542
|
+
# Deal with multi-line statements:
|
|
543
|
+
# 1. theory initialization (theory... imports... begin)
|
|
544
|
+
# 2. lemma declarations over multiple lines
|
|
545
|
+
if self._top_level:
|
|
546
|
+
self.buffer += stmt + '\n' # Add current line to buffer
|
|
547
|
+
begin_clause = IsabelleExecutor.begin_theory_match.findall(self.buffer)
|
|
548
|
+
elif not self._proof_running:
|
|
549
|
+
self.buffer += stmt + '\n' # Add current line to buffer
|
|
550
|
+
# If the action succeeds, we have a new lemma
|
|
551
|
+
description = self.pisa_env.step(start_state, self.buffer, end_state)
|
|
552
|
+
if not description.startswith('Step error:'):
|
|
553
|
+
last_thm_details = IsabelleExecutor.theorem_match.findall(self.buffer)
|
|
554
|
+
|
|
555
|
+
# Complete initialization transitions found! Exit top-level mode
|
|
556
|
+
if begin_clause:
|
|
557
|
+
# Perform initialization
|
|
558
|
+
stmt = self.buffer
|
|
559
|
+
self.buffer = ""
|
|
560
|
+
self._top_level = False
|
|
561
|
+
|
|
562
|
+
start_state = self.get_state_str(0)
|
|
563
|
+
end_state = self.get_state_str(1)
|
|
564
|
+
|
|
565
|
+
# Complete lemma found! Enter proof mode
|
|
566
|
+
if last_thm_details:
|
|
567
|
+
found_lemma = True
|
|
568
|
+
# Extract lemma name and declaration
|
|
569
|
+
stmt = self.buffer
|
|
570
|
+
self.buffer = ""
|
|
571
|
+
full_thm_stmt, _, _, _, thm_name, _, thm_value = last_thm_details[-1]
|
|
572
|
+
full_thm_stmt, thm_name, thm_value = full_thm_stmt.strip(), thm_name.strip(), thm_value.strip()
|
|
573
|
+
|
|
574
|
+
# Some lemmas don't have names
|
|
575
|
+
if not thm_name:
|
|
576
|
+
thm_name = thm_value
|
|
577
|
+
|
|
578
|
+
self.local_theorem_lemma_description[thm_name] = full_thm_stmt
|
|
579
|
+
self.curr_lemma_name, self.curr_lemma = thm_name, thm_value
|
|
580
|
+
self._proof_running = True # Set proof mode
|
|
581
|
+
|
|
582
|
+
# In proof mode. Execute tactics
|
|
583
|
+
if self._proof_running or begin_clause:
|
|
584
|
+
stmt = f"{self.buffer}{stmt.strip()}"
|
|
585
|
+
|
|
586
|
+
# Throw an error if "sorry" is used, which is not allowed
|
|
587
|
+
# Note that this is a fairly simple/optimistic way of handling it
|
|
588
|
+
if proof_search_mode and "sorry" in stmt:
|
|
589
|
+
raise Exception('Error: expected tactic, got "sorry". Do not use "sorry" in your proof.')
|
|
590
|
+
|
|
591
|
+
try:
|
|
592
|
+
# Run statement. TODO: pass in timeout
|
|
593
|
+
stmt = self._handle_sledgehammer(start_state, stmt, end_state, proof_search_mode)
|
|
594
|
+
# Parse proof context
|
|
595
|
+
local_hypotheses = self.pisa_env.get_local_lemmas(self.get_state_str(self.current_state + 1))
|
|
596
|
+
proof_state = self.pisa_env.get_state(self.get_state_str(self.current_state + 1))
|
|
597
|
+
self.proof_context = self._parse_proof_context(proof_state, local_hypotheses, found_lemma)
|
|
598
|
+
except Exception as e:
|
|
599
|
+
# If we're not in proof search mode, we assume the file compiles correctly
|
|
600
|
+
# Then this error is likely the result of a tactic split between multiple lines
|
|
601
|
+
# To fix, we'll simply fill a buffer until the tactic compiles correctly
|
|
602
|
+
if not proof_search_mode:
|
|
603
|
+
self.buffer = stmt + '\n'
|
|
604
|
+
raise
|
|
605
|
+
|
|
606
|
+
self.current_state += 1
|
|
607
|
+
self.line_num_to_state[self.line_num] = self.current_state
|
|
608
|
+
self.buffer = ""
|
|
609
|
+
# print(repr(stmt) + "\n -> \n" + repr(description))
|
|
610
|
+
|
|
611
|
+
if not begin_clause:
|
|
612
|
+
is_proof_done = self.pisa_env.is_finished(end_state)
|
|
613
|
+
if is_proof_done: # Proof finished
|
|
614
|
+
self.buffer = ""
|
|
615
|
+
self._proof_running = False
|
|
616
|
+
self.curr_lemma_name, self.curr_lemma = None, ""
|
|
617
|
+
self.proof_context = None
|
|
618
|
+
return stmt
|
|
619
|
+
return "-"
|
|
620
|
+
|
|
621
|
+
# PISA only supports sledgehammer as an atomic operation. So we must split any tactic which uses it
|
|
622
|
+
def _handle_sledgehammer(self, start_state: str, step: str, end_state: str, proof_search_mode=True) -> str:
|
|
623
|
+
if step is None or len(step) == 0:
|
|
624
|
+
return None
|
|
625
|
+
|
|
626
|
+
if self.current_state in self._seldgehammer_cache and step in self._seldgehammer_cache[self.current_state]:
|
|
627
|
+
# We've already tried this tactic, so just return the cached result
|
|
628
|
+
stmt_or_description = self._seldgehammer_cache[self.current_state][step]
|
|
629
|
+
if stmt_or_description.startswith('Step error:'):
|
|
630
|
+
raise Exception(stmt_or_description)
|
|
631
|
+
return stmt_or_description
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
tactics = re.split(r'(sledgehammer)', step)
|
|
635
|
+
tactics = list(filter(None, tactics))
|
|
636
|
+
|
|
637
|
+
description = None
|
|
638
|
+
stmt = ""
|
|
639
|
+
for idx, tactic in enumerate(tactics):
|
|
640
|
+
temp_start = end_state
|
|
641
|
+
temp_end = end_state
|
|
642
|
+
if idx == 0:
|
|
643
|
+
temp_start = start_state
|
|
644
|
+
|
|
645
|
+
if tactic == 'sledgehammer':
|
|
646
|
+
if proof_search_mode and self.use_hammer == HammerMode.NONE:
|
|
647
|
+
raise Exception('Error: got "sledgehammer" query with hammer turned off. To use hammer, toggle "use_hammer"')
|
|
648
|
+
|
|
649
|
+
# Attempt to solve proof with sledgehammer
|
|
650
|
+
description = self._handle_auto_tactics(stmt, temp_start, temp_end)
|
|
651
|
+
stmt += description # Replace with hammer-provided tactic, not 'sledgehammer' literally
|
|
652
|
+
else:
|
|
653
|
+
# Run tactic normally
|
|
654
|
+
description = self._handle_reg_tactic(temp_start, tactic, temp_end, proof_search_mode)
|
|
655
|
+
stmt += description # Replace with a potentially modified tactic
|
|
656
|
+
|
|
657
|
+
return stmt
|
|
658
|
+
|
|
659
|
+
def _handle_auto_tactics(self, step: str, start_state: str, end_state: str) -> str:
|
|
660
|
+
# First we'll try easier tactics, e.g. "simp", "auto", "blast", etc.
|
|
661
|
+
for tactic in IsabelleExecutor.auto_tactics:
|
|
662
|
+
stmt = 'by ' + tactic
|
|
663
|
+
full_stmt = step + stmt
|
|
664
|
+
# Check if we've already tried this tactic
|
|
665
|
+
if self.current_state in self._seldgehammer_cache and full_stmt in self._seldgehammer_cache[self.current_state]:
|
|
666
|
+
description = self._seldgehammer_cache[self.current_state][full_stmt]
|
|
667
|
+
else:
|
|
668
|
+
description = self.pisa_env.step(start_state, stmt, end_state)
|
|
669
|
+
if self.current_state not in self._seldgehammer_cache:
|
|
670
|
+
self._seldgehammer_cache[self.current_state] = {}
|
|
671
|
+
self._seldgehammer_cache[self.current_state][full_stmt] = description
|
|
672
|
+
auto_tactic_succeeded = not description.startswith('Step error:')
|
|
673
|
+
if auto_tactic_succeeded:
|
|
674
|
+
# If the tactic succeeded, return it
|
|
675
|
+
return stmt + ' <auto tactic>'
|
|
676
|
+
|
|
677
|
+
# If those fail, run sledgehammer (more powerful but slower)
|
|
678
|
+
full_stmt = step + 'sledgehammer'
|
|
679
|
+
# Check if we've already tried this tactic
|
|
680
|
+
if self.current_state in self._seldgehammer_cache and full_stmt in self._seldgehammer_cache[self.current_state]:
|
|
681
|
+
description = self._seldgehammer_cache[self.current_state][full_stmt]
|
|
682
|
+
else:
|
|
683
|
+
description = self.pisa_env.apply_hammer(start_state, end_state)
|
|
684
|
+
if self.current_state not in self._seldgehammer_cache:
|
|
685
|
+
self._seldgehammer_cache[self.current_state] = {}
|
|
686
|
+
self._seldgehammer_cache[self.current_state][full_stmt] = description
|
|
687
|
+
sledgehammer_succeeded = not description.startswith('Step error:')
|
|
688
|
+
if sledgehammer_succeeded:
|
|
689
|
+
# If the tactic succeeded, return it
|
|
690
|
+
return description.split('<hammer>')[0] + '<hammer>'
|
|
691
|
+
else:
|
|
692
|
+
raise Exception(description)
|
|
693
|
+
|
|
694
|
+
def _handle_reg_tactic(self, start_state: str, step: str, end_state: str, proof_search_mode=True) -> str:
|
|
695
|
+
description = self.pisa_env.step(start_state, step, end_state)
|
|
696
|
+
# Check if the tactic succeeded
|
|
697
|
+
tactic_succeeded = not description.startswith('Step error:')
|
|
698
|
+
if tactic_succeeded:
|
|
699
|
+
return step
|
|
700
|
+
else:
|
|
701
|
+
# Use auto tactics correction heuristics by changing it to sledehammer
|
|
702
|
+
tactics = re.split(r'\susing\s|\sby\s', step, maxsplit=1)
|
|
703
|
+
if len(tactics) > 1 and \
|
|
704
|
+
(self.use_hammer == HammerMode.AUTO or self.use_hammer == HammerMode.ALWAYS) and \
|
|
705
|
+
proof_search_mode:
|
|
706
|
+
# Try applying sledgehammer. We do some awkward parsing to apply it to the correct portion
|
|
707
|
+
# This will not always work, but because this is a heuristic and not mission-critical, it is ok
|
|
708
|
+
new_tactic = tactics[0] + ' sledgehammer'
|
|
709
|
+
try:
|
|
710
|
+
step = self._handle_sledgehammer(start_state, new_tactic, end_state, proof_search_mode)
|
|
711
|
+
return step
|
|
712
|
+
except:
|
|
713
|
+
# Don't throw an error here -- we want to throw the original error
|
|
714
|
+
pass
|
|
715
|
+
raise Exception(description)
|
|
716
|
+
|
|
717
|
+
def _parse_proof_context(self, proof_context_str: str, local_hypotheses: typing.List[IsabelleLemma], found_lemma: bool) -> ProofContext:
|
|
718
|
+
if proof_context_str is None or len(proof_context_str) == 0:
|
|
719
|
+
return None
|
|
720
|
+
|
|
721
|
+
# Parse proof context and find 1. last proved statement (this) and 2. goals
|
|
722
|
+
all_matches = self.proof_context_match.findall(proof_context_str)
|
|
723
|
+
if len(all_matches) == 0:
|
|
724
|
+
return None
|
|
725
|
+
|
|
726
|
+
context_type, _, _, this_hyps_str, _, goals_str = all_matches[0]
|
|
727
|
+
this_hyps_str, goals_str = this_hyps_str.strip(), goals_str.strip()
|
|
728
|
+
if(goals_str == "No subgoals!"):
|
|
729
|
+
return ProofContext.empty()
|
|
730
|
+
|
|
731
|
+
if not found_lemma and not context_type == 'state':
|
|
732
|
+
raise Exception(f'Error: please provide a full tactic. This step ends in "{context_type}" mode but it should end in "state" mode')
|
|
733
|
+
|
|
734
|
+
hypotheses = []
|
|
735
|
+
for hyp in local_hypotheses:
|
|
736
|
+
# Replace assms_x with assms(x)
|
|
737
|
+
hypotheses.append(IsabelleExecutor.assms_regex_match.sub(r'assms(\1):', hyp.dfn))
|
|
738
|
+
|
|
739
|
+
goals_list = list(filter(None, goals_str.split("\n")))
|
|
740
|
+
goals = []
|
|
741
|
+
for i, goal_str in enumerate(goals_list):
|
|
742
|
+
goal_str = re.sub("\d+.", "", goal_str, 1).strip() # Remove numbering
|
|
743
|
+
if i == 0:
|
|
744
|
+
goal = Obligation(hypotheses, goal_str)
|
|
745
|
+
else:
|
|
746
|
+
goal = Obligation([], goal_str)
|
|
747
|
+
goals.append(goal)
|
|
748
|
+
|
|
749
|
+
return ProofContext(goals, [], [], [])
|
|
750
|
+
|
|
751
|
+
def get_all_lemmas_in_file(isabelle_executor: IsabelleExecutor, logger: logging.Logger) -> typing.List[str]:
|
|
752
|
+
lemmas_to_prove = []
|
|
753
|
+
while not isabelle_executor.execution_complete:
|
|
754
|
+
assert not isabelle_executor.is_in_proof_mode(), "main_executor must not be in proof mode"
|
|
755
|
+
_ = list(isabelle_executor.run_till_next_lemma_return_exec_stmt())
|
|
756
|
+
if isabelle_executor.execution_complete:
|
|
757
|
+
break
|
|
758
|
+
lemma_name = isabelle_executor.get_lemma_name_if_running()
|
|
759
|
+
if lemma_name is None:
|
|
760
|
+
_ = list(isabelle_executor.run_to_finish_lemma_return_exec())
|
|
761
|
+
if isabelle_executor.execution_complete:
|
|
762
|
+
break
|
|
763
|
+
else:
|
|
764
|
+
logger.info(f"Discovered lemma: {lemma_name}")
|
|
765
|
+
lemmas_to_prove.append(lemma_name)
|
|
766
|
+
isabelle_executor.run_to_finish_lemma()
|
|
767
|
+
return lemmas_to_prove
|
|
768
|
+
|
|
769
|
+
class IsabelleStdInOutExecutor:
|
|
770
|
+
def __init__(self):
|
|
771
|
+
self.isabelle_stdin_reader = IsabelleStepByStepStdInReader()
|
|
772
|
+
self.isabelle_exec : IsabelleExecutor = IsabelleExecutor(
|
|
773
|
+
use_human_readable_proof_context=True,
|
|
774
|
+
proof_step_iter=self.isabelle_stdin_reader.instruction_step_generator())
|
|
775
|
+
|
|
776
|
+
def __enter__(self):
|
|
777
|
+
self.isabelle_exec.__enter__()
|
|
778
|
+
return self
|
|
779
|
+
|
|
780
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
781
|
+
self.isabelle_exec.__exit__(exc_type, exc_value, traceback)
|
|
782
|
+
|
|
783
|
+
def run_in_loop(self):
|
|
784
|
+
print("In> ", end="")
|
|
785
|
+
while True:
|
|
786
|
+
try:
|
|
787
|
+
cmd_ran = self.isabelle_exec.run_next()
|
|
788
|
+
if not cmd_ran:
|
|
789
|
+
break
|
|
790
|
+
print(f"Isabelle> {cmd_ran}")
|
|
791
|
+
print(f"{self.isabelle_exec.proof_context}")
|
|
792
|
+
print("In> ", end="")
|
|
793
|
+
except Exception as e:
|
|
794
|
+
print(e)
|
|
795
|
+
pass
|
|
796
|
+
pass
|
|
797
|
+
|
|
798
|
+
class IsabelleCustomFileExec:
|
|
799
|
+
def __init__(self, file_path: str, project_root: str):
|
|
800
|
+
self.isabelle_exec : IsabelleExecutor = IsabelleExecutor(
|
|
801
|
+
use_human_readable_proof_context=True,
|
|
802
|
+
main_file=file_path,
|
|
803
|
+
project_root=project_root)
|
|
804
|
+
|
|
805
|
+
def __enter__(self):
|
|
806
|
+
self.isabelle_exec.__enter__()
|
|
807
|
+
return self
|
|
808
|
+
|
|
809
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
|
810
|
+
self.isabelle_exec.__exit__(exc_type, exc_value, traceback)
|
|
811
|
+
|
|
812
|
+
def run_in_loop(self):
|
|
813
|
+
print("In> Press 'Enter' for running next line and 'c' + 'Enter' to cancel the last command and 're-run'.", end="")
|
|
814
|
+
cmd_ran = None
|
|
815
|
+
while True:
|
|
816
|
+
try:
|
|
817
|
+
opt = input()
|
|
818
|
+
if opt == "c" and cmd_ran is not None:
|
|
819
|
+
if self.isabelle_exec.is_in_proof_mode():
|
|
820
|
+
print(f"Goals before cancelling")
|
|
821
|
+
print(self.isabelle_exec.proof_context.all_goals)
|
|
822
|
+
else:
|
|
823
|
+
print("No goals before cancelling")
|
|
824
|
+
print("cancel_last() not implemented")
|
|
825
|
+
if self.isabelle_exec.is_in_proof_mode():
|
|
826
|
+
print(f"Goals after cancelling")
|
|
827
|
+
print(self.isabelle_exec.proof_context.all_goals)
|
|
828
|
+
else:
|
|
829
|
+
print("No goals after cancelling")
|
|
830
|
+
print(f"Canceled last statement: {cmd_ran}")
|
|
831
|
+
print(f"Re-running: {cmd_ran}")
|
|
832
|
+
print("re-running not implemented")
|
|
833
|
+
print(f"Isabelle> Ran {cmd_ran} again")
|
|
834
|
+
continue
|
|
835
|
+
cmd_ran = self.isabelle_exec.run_next(proof_search_mode=False)
|
|
836
|
+
if not cmd_ran:
|
|
837
|
+
break
|
|
838
|
+
print(f"Isabelle> {self.isabelle_exec.current_stmt}")
|
|
839
|
+
print(f"Parsed Tactic> {cmd_ran}")
|
|
840
|
+
print(f"{self.isabelle_exec.proof_context}")
|
|
841
|
+
print("In> ", end="")
|
|
842
|
+
except Exception as e:
|
|
843
|
+
print(e)
|
|
844
|
+
pass
|
|
845
|
+
pass
|
|
846
|
+
|
|
847
|
+
if __name__ == "__main__":
|
|
848
|
+
logging.basicConfig(filename='isabelle_executor.log', filemode='w', level=logging.INFO)
|
|
849
|
+
# with IsabelleStdInOutExecutor() as isabelle_exec:
|
|
850
|
+
# isabelle_exec.run_in_loop()
|
|
851
|
+
|
|
852
|
+
# os.chdir(root_dir)
|
|
853
|
+
# with IsabelleCustomFileExec("data/benchmarks/miniF2F/isabelle/test/aime_1983_p1.thy", "data/benchmarks/miniF2F") as isabelle_exec:
|
|
854
|
+
# isabelle_exec.run_in_loop()
|
|
855
|
+
|
|
856
|
+
os.chdir(root_dir)
|
|
857
|
+
IsabelleExecutor.start_server(port=13000)
|
|
858
|
+
try:
|
|
859
|
+
with IsabelleCustomFileExec("data/test/isabelle/custom_hol/Basic_Logic.thy", "data/test/isabelle/custom_hol") as isabelle_exec:
|
|
860
|
+
isabelle_exec.run_in_loop()
|
|
861
|
+
finally:
|
|
862
|
+
IsabelleExecutor.stop_server()
|