PySWIP访问SWI-Prolog知识库报错:atom_chars/2参数未充分实例化
问题:PySWIP调用consult时出现instantiation_error错误
环境配置
- macOS 13.1
- Python 3.11
- PySWIP 0.2.10
- x86_64-darwin版本SWI-Prolog 9.0.4
错误详情
运行Python脚本调用prolog.consult("knowledge_base.pl")时触发以下错误:
ERROR: atom_chars/2: Arguments are not sufficiently instantiated Traceback (most recent call last): File "/Users/user/PycharmProjects/ExpertSystem/venv/expert_system.py", line 5, in prolog.consult("knowledge_base.pl") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/user/PycharmProjects/ExpertSystem/venv/lib/python3.11/site-packages/pyswip/prolog.py", line 156, in consult next(cls.query(filename.join(["consult('", "')"]), catcherrors=catcherrors)) File "/Users/user/PycharmProjects/ExpertSystem/venv/lib/python3.11/site-packages/pyswip/prolog.py", line 126, in __call__ raise PrologError("".join(["Caused by: '", query, "'. ", pyswip.prolog.PrologError: Caused by: 'consult('knowledge_base.pl')'. Returned: 'error(instantiation_error, context(:(system, /(atom_chars, 2)), _654))'.
Prolog知识库代码
% Facts % Regular Covid virus symptoms covid_symptom(fever). covid_symptom(cough). covid_symptom(shortness_of_breath). covid_symptom(fatigue). covid_symptom(loss_of_taste_or_smell). % Kraken (XBB.1.5) variant symptoms kraken_symptom(intense_headache). kraken_symptom(chest_pain). kraken_symptom(sudden_loss_of_hearing). % Omicron Variant symptoms omicron_symptom(sore_throat). omicron_symptom(rapid_heartbeat). omicron_symptom(skin_rash). % Underlying conditions underlying_condition(diabetes). underlying_condition(hypertension). underlying_condition(asthma). underlying_condition(cardiovascular_disease). % Rules % Person is at risk of Covid if they have Covid symptoms and risk factors (underlying conditions) risk_of_covid(Person) :- has_covid_symptom(Person), has_risk_factor(Person). % Person has Covid symptom if they have a symptom that is a Covid symptom has_covid_symptom(Person) :- symptom(Person, Symptom), covid_symptom(Symptom). % Person has a risk factor if they have a condition that is an underlying condition has_risk_factor(Person) :- condition(Person, Condition), underlying_condition(Condition). % Person is at risk of Kraken variant if they have Kraken symptoms and risk factors (underlying conditions) risk_of_kraken_variant(Person) :- has_kraken_symptom(Person), has_risk_factor(Person). % Person has Kraken symptom if they have a symptom that is a Kraken symptom has_kraken_symptom(Person) :- symptom(Person, Symptom), kraken_symptom(Symptom). % Person is at risk of Omicron variant if they have Omicron symptoms and risk factors (underlying conditions) risk_of_omicron_variant(Person) :- has_omicron_symptom(Person), has_risk_factor(Person). % Person has Omicron symptom if they have a symptom that is an Omicron symptom has_omicron_symptom(Person) :- symptom(Person, Symptom), omicron_symptom(Symptom). % Person has low blood pressure if their systolic and diastolic readings are below certain thresholds low_blood_pressure(Systolic, Diastolic) :- Systolic < 90, Diastolic < 60. % Person has high blood pressure if their systolic or diastolic readings are above certain thresholds high_blood_pressure(Systolic, Diastolic) :- Systolic > 129, Diastolic > 79. % Conversion of temperature from Fahrenheit to Celsius convert_fahrenheit_to_celsius(F, C) :- C is (F - 32) * 5 / 9. % Person has fever if their temperature in Celsius is above a certain threshold has_fever(Person) :- temperature_celsius(Person, Temp), Temp >= 37.5. % Person has Covid symptoms if they have a fever or another Covid symptom has_covid_symptom(Person) :- has_fever(Person); symptom(Person, Symptom), covid_symptom(Symptom). % Rules for counting mild and severe symptoms are unchanged mild_symptom_count(Count) :- findall(Person, (has_covid_symptom(Person), symptom(Person, S), mild_symptom(S)), Persons), length(Persons, Count). severe_symptom_count(Count) :- findall(Person, (has_covid_symptom(Person), symptom(Person, S), severe_symptom(S)), Persons), length(Persons, Count). % Define your rules for identifying Kraken and Omicron variants here has_kraken_variant(Person) :- risk_of_kraken_variant(Person). has_omicron_variant(Person) :- risk_of_omicron_variant(Person). % Rules for counting Kraken and Omicron variants kraken_variant_count(Count) :- findall(Person, has_kraken_variant(Person), Persons), length(Persons, Count). omicron_variant_count(Count) :- findall(Person, has_omicron_variant(Person), Persons), length(Persons, Count). % Rules for counting persons with underlying conditions persons_with_conditions_count(Count) :- findall(Person, (has_covid_symptom(Person), condition(Person, _)), Persons), length(Persons, Count). % Rule for finding top 3 underlying conditions top_conditions(Top3) :- findall((Count, Condition), (condition(_, Condition), aggregate(count, Person, condition(Person, Condition), Count)), Counts), sort(Counts, SortedCounts), reverse(SortedCounts, DescCounts), length(DescCounts, Length), (Length >= 3 -> length(Top3, 3); length(Top3, Length)), append(Top3, _, DescCounts).
Python代码
import sys from pyswip import Prolog prolog = Prolog() prolog.consult("knowledge_base.pl") # Load the Prolog knowledge base def consult_knowledge_base(query, variable=None): results = list(prolog.query(query)) if variable: return [result[variable] for result in results] else: return bool(results) def add_knowledge(fact): prolog.assertz(fact) def add_underlying_condition(person, condition): fact = f"condition({person}, {condition})" add_knowledge(fact) def add_temperature_fahrenheit(person, temperature_f): temperature_c = (temperature_f - 32) * 5 / 9 fact = f"temperature_celsius({person}, {temperature_c})" add_knowledge(fact) def add_blood_pressure(person, systolic, diastolic): fact_systolic = f"systolic_bp({person}, {systolic})" fact_diastolic = f"diastolic_bp({person}, {diastolic})" add_knowledge(fact_systolic) add_knowledge(fact_diastolic) def ask_questions(person): while True: print("\nOptions:") print("1. Add underlying condition") print("2. Add temperature (Fahrenheit)") print("3. Add symptom") print("4. Add blood pressure") print("5. Done") choice = input("Enter your choice: ") if choice == "1": condition = input("Enter underlying condition: ") add_underlying_condition(person, condition) elif choice == "2": temperature_f = float(input("Enter temperature in Fahrenheit: ")) add_temperature_fahrenheit(person, temperature_f) elif choice == "3": symptom = input("Enter symptom: ") add_symptom(person, symptom) elif choice == "4": systolic = float(input("Enter systolic blood pressure (mm Hg): ")) diastolic = float(input("Enter diastolic blood pressure (mm Hg): ")) add_blood_pressure(person, systolic, diastolic) elif choice == "5": break else: print("Invalid choice. Please try again.") def add_symptom(person, symptom): fact = f"symptom({person}, {symptom})" add_knowledge(fact) def diagnose(person): query_regular_covid = f"risk_of_covid({person})" query_kraken_variant = f"risk_of_kraken_variant({person})" query_omicron_variant = f"risk_of_omicron_variant({person})" diagnosis = {} if list(prolog.query(query_regular_covid)): diagnosis["Regular COVID-19"] = True else: diagnosis["Regular COVID-19"] = False if list(prolog.query(query_kraken_variant)): diagnosis["Kraken (XBB.1.5) variant"] = True else: diagnosis["Kraken (XBB.1.5) variant"] = False if list(prolog.query(query_omicron_variant)): diagnosis["Omicron variant"] = True else: diagnosis["Omicron variant"] = False diagnosis["at_risk_of_covid"] = consult_knowledge_base(f"at_risk_of_covid({person})") diagnosis["short_term_action"] = consult_knowledge_base(f"short_term_action({person}, Action)", "Action") diagnosis["long_term_action"] = consult_knowledge_base(f"long_term_action({person}, Action)", "Action") return diagnosis def display_statistics(): total_count = consult_knowledge_base("total_persons_diagnosed(Total)", "Total") mild_count = consult_knowledge_base("mild_symptom_count(Count)", "Count") severe_count = consult_knowledge_base("severe_symptom_count(Count)", "Count") kraken_count = consult_knowledge_base("kraken_variant_count(Count)", "Count") omicron_count = consult_knowledge_base("omicron_variant_count(Count)", "Count") conditions_count = consult_knowledge_base("persons_with_conditions_count(Count)", "Count") top_conditions = consult_knowledge_base("top_conditions(Conditions)", "Conditions") print("\nCOVID-19 Statistics:") print(f"Percentage of persons with mild symptoms: {100 * mild_count / total_count:.2f}%") print(f"Percentage of persons with severe symptoms: {100 * severe_count / total_count:.2f}%") print(f"Percentage of persons with the Kraken (XBB.1.5) variant: {100 * kraken_count / total_count:.2f}%") print(f"Percentage of persons with the Omicron Variant: {100 * omicron_count / total_count:.2f}%") print(f"Percentage of affected persons with underlying conditions: {100 * conditions_count / total_count:.2f}%") print(f"Top 3 underlying conditions: {', '.join(top_conditions)}") # Check for any spikes or unusual increases in reports spike_thresholds = { 'mild_symptoms': 30, 'severe_symptoms': 10, 'kraken_variant': 15, 'omicron_variant': 15, 'underlying_conditions': 40 } spikes = [] if 100 * mild_count / total_count > spike_thresholds['mild_symptoms']: spikes.append("mild symptoms") if 100 * severe_count / total_count > spike_thresholds['severe_symptoms']: spikes.append("severe symptoms") if 100 * kraken_count / total_count > spike_thresholds['kraken_variant']: spikes.append("Kraken (XBB.1.5) variant") if 100 * omicron_count / total_count > spike_thresholds['omicron_variant']: spikes.append("Omicron variant") if 100 * conditions_count / total_count > spike_thresholds['underlying_conditions']: spikes.append("affected persons with underlying conditions") if spikes: print("\nAlert:") print( "There is an unusual increase in reports of persons prone to having (or possibly has) COVID-19 with the following characteristics:") for spike in spikes: print(f"- {spike}") print("Please take necessary actions and inform the relevant authorities.")
排查情况
已确认错误与知识库代码无关,问题出在PySWIP层面。尝试重装PySWIP十次仍无法解决,无法定位具体原因,确定问题与PySWIP相关。
内容的提问来源于stack exchange,提问作者Demali Gregg
相关产品推荐
相关产品推荐

