18 Star 18 Fork 7

Bohua Zhan/holpy

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
integral.py 21.84 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
# Author: Runqing Xu, Bohua Zhan
"""API for computing integrals."""
import json
from flask import request
from flask.json import jsonify
import os
import integral
from integral import compstate
from integral import slagle
from app.app import app
dirname = os.path.dirname(__file__)
@app.route("/api/integral-load-book-list", methods=['POST'])
def integral_load_book_list():
# Load book list from index.json
file_name = os.path.join(dirname, "../integral/examples/index.json")
with open(file_name, 'r', encoding='utf-8') as f:
f_data = json.load(f)
return jsonify(f_data)
@app.route("/api/integral-load-book-content", methods=['POST'])
def integral_load_book_content():
data = json.loads(request.get_data().decode('utf-8'))
file_name = os.path.join(dirname, "../integral/examples/" + data['bookname'] + '.json')
# Load raw data
with open(file_name, 'r', encoding='utf-8') as f:
f_data = json.load(f)
# For each expression, load its latex form
for item in f_data['content']:
# Expressions in item
if 'expr' in item:
e = integral.parser.parse_expr(item['expr'])
latex_str = integral.latex.convert_expr(e)
item['latex_str'] = latex_str
# Conditions in item
if 'conds' in item:
latex_conds = []
for cond_str in item['conds']:
cond = integral.parser.parse_expr(cond_str)
latex_conds.append(integral.latex.convert_expr(cond))
item['latex_conds'] = latex_conds
# Table elements
if item['type'] == 'table':
new_table = list()
funcexpr = integral.expr.Fun(item['name'], integral.expr.Var('x'))
item['funcexpr'] = integral.latex.convert_expr(funcexpr)
for x, y in item['table'].items():
x = integral.parser.parse_expr(x)
y = integral.parser.parse_expr(y)
new_table.append({
'x': integral.latex.convert_expr(x),
'y': integral.latex.convert_expr(y)
})
item['latex_table'] = new_table
return jsonify(f_data)
@app.route("/api/integral-open-file", methods=['POST'])
def integral_open_file():
data = json.loads(request.get_data().decode('utf-8'))
file_name = os.path.join(dirname, "../integral/examples/" + data['filename'] + '.json')
with open(file_name, 'r', encoding='utf-8') as f:
f_data = json.load(f)
for item in f_data['content']:
if 'problem' in item:
problem = integral.parser.parse_expr(item['problem'])
item['_problem_latex'] = integral.latex.convert_expr(problem)
return jsonify(f_data)
@app.route("/api/integral-save-file", methods=['POST'])
def integral_save_file():
data = json.loads(request.get_data().decode('utf-8'))
file_name = os.path.join(dirname, "../integral/examples/" + data['filename'])
with open(file_name, 'w', encoding='utf-8') as f:
json.dump({"content": data['content']}, f, indent=4, ensure_ascii=False, sort_keys=True)
return jsonify({
'status': 'success'
})
@app.route("/api/clear-item", methods=['POST'])
def clear_item():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
st.get_by_label(label).clear()
res = {
"status": "ok",
"item": st.export(),
}
if isinstance(st, (compstate.Calculation)):
if len(st.steps) == 0:
res['selected_item'] = str(compstate.Label([]))
else:
res['selected_item'] = str(compstate.Label([len(st.steps) - 1]))
return jsonify(res)
@app.route("/api/query-integral", methods=['POST'])
def query_integral():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
if isinstance(subitem, compstate.CalculationStep):
integrals = subitem.res.separate_integral()
elif isinstance(subitem, compstate.Calculation):
integrals = subitem.start.separate_integral()
elif isinstance(subitem, compstate.RewriteGoalProof):
integrals = subitem.begin.start.separate_integral()
else:
return jsonify({
"status": "error",
"msg": "Selected item is not part of a calculation."
})
res = []
for e, loc in integrals:
res.append({
"expr": str(e),
"var_name": e.var,
"body": str(e.body),
"latex_expr": integral.latex.convert_expr(e),
"latex_body": integral.latex.convert_expr(e.body),
"loc": str(loc)
})
return jsonify({
"status": "ok",
"integrals": res
})
@app.route("/api/query-latex-expr", methods=['POST'])
def query_latex_expr():
"""Find latex form of an expression."""
data = json.loads(request.get_data().decode('UTF-8'))
try:
e = integral.parser.parse_expr(data['expr'])
selected = integral.parser.parse_expr(data['selected_expr'])
locs = e.find_subexpr(selected)
assert len(locs) > 0
if len(locs) > 1:
print('Warning: multiple locations', flush=True)
loc = locs[0]
return jsonify({
"status": "ok",
"latex_expr": integral.latex.convert_expr(selected),
"loc": str(loc)
})
except Exception as e:
return jsonify({
"status": "fail",
"exception": str(e)
})
@app.route("/api/query-identities", methods=['POST'])
def query_identities():
"""Find list of identity rewerites for an expression."""
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
try:
e = integral.parser.parse_expr(data['expr'])
results = integral.rules.ApplyIdentity.search(e, subitem.ctx)
json_results = []
for res in results:
json_results.append({
"res": str(res),
"latex_res": integral.latex.convert_expr(res)
})
return jsonify({
"status": "ok",
"latex_expr": integral.latex.convert_expr(e),
"results": json_results
})
except Exception as e:
return jsonify({
"status": "fail",
"exception": str(e)
})
@app.route("/api/add-function-definition", methods=['POST'])
def add_function_definition():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
eq = integral.parser.parse_expr(data['eq'])
conds = list(integral.parser.parse_expr(cond) for cond in data['conds'])
file.add_definition(eq, conds=conds)
return jsonify({
"status": "ok",
"state": file.export()['content'],
"selected_item": str(compstate.Label(""))
})
@app.route("/api/add-goal", methods=["POST"])
def add_goal():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
goal = integral.parser.parse_expr(data['goal'])
conds = list(integral.parser.parse_expr(cond) for cond in data['conds'])
file.add_goal(goal, conds=conds)
return jsonify({
"status": "ok",
"state": file.export()['content'],
"selected_item": str(compstate.Label(""))
})
@app.route("/api/proof-by-calculation", methods=["POST"])
def proof_by_calculation():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
if isinstance(subitem, compstate.Goal):
subitem.proof_by_calculation()
return jsonify({
"status": "ok",
"item": st.export(),
"selected_item": str(compstate.Label(label.data + [0]))
})
else:
return jsonify({
"status": "error",
"msg": "Selected item is not a goal."
})
@app.route("/api/proof-by-induction", methods=["POST"])
def proof_by_induction():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
induct_var = data['induct_var']
start = integral.parser.parse_expr(data['start'])
if isinstance(subitem, compstate.Goal):
proof = subitem.proof_by_induction(induct_var, start=start)
proof.base_case.proof_by_calculation()
proof.induct_case.proof_by_calculation()
return jsonify({
"status": "ok",
"item": st.export(),
"selected_item": str(compstate.Label(label.data + [0]))
})
else:
return jsonify({
"status": "error",
"msg": "Selected item is not a goal."
})
@app.route("/api/proof-by-rewrite-goal", methods=["POST"])
def proof_by_rewrite_goal():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
begin = integral.parser.parse_expr(data['begin'])
if isinstance(subitem, compstate.Goal):
# Find the goal corresponding to begin
begin_goal = None
for item in file.content[:cur_id]:
if isinstance(item, compstate.Goal) and item.goal == begin:
begin_goal = item
break
assert begin_goal is not None
subitem.proof_by_rewrite_goal(begin=begin_goal)
return jsonify({
"status": "ok",
"item": st.export(),
"selected_item": str(compstate.Label(label.data + [0]))
})
@app.route("/api/expand-definition", methods=["POST"])
def expand_definition():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
if isinstance(subitem, (compstate.CalculationStep, compstate.Calculation)):
if isinstance(subitem, compstate.Calculation):
e = subitem.start
else:
e = subitem.res
results = integral.rules.ExpandDefinition.search(e, subitem.ctx)
if len(results) == 1:
sube, loc = results[0]
if sube.is_fun():
rule = integral.rules.ExpandDefinition(sube.func_name)
elif sube.is_var():
rule = integral.rules.ExpandDefinition(sube.name)
else:
raise TypeError
if loc.data:
rule = integral.rules.OnLocation(rule, loc)
subitem.perform_rule(rule)
return jsonify({
"status": "ok",
"item": st.export(),
"selected_item": str(compstate.get_next_step_label(subitem, label))
})
else:
choices = []
for sube, loc in results:
choices.append({
'subexpr': str(sube),
'latex_subexpr': integral.latex.convert_expr(sube),
'func_name': sube.func_name,
'loc': str(loc)
})
return jsonify({
"status": "choose",
"choices": choices
})
else:
return jsonify({
"status": "error",
"msg": "Selected item is not part of a calculation."
})
@app.route("/api/fold-definition", methods=["POST"])
def fold_definition():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
if isinstance(subitem, (compstate.CalculationStep, compstate.Calculation)):
if isinstance(subitem, compstate.Calculation):
e = subitem.start
else:
e = subitem.res
results = integral.rules.FoldDefinition.search(e, subitem.ctx)
if len(results) == 1:
_, loc, func_name = results[0]
rule = integral.rules.FoldDefinition(func_name)
if loc.data:
rule = integral.rules.OnLocation(rule, loc)
subitem.perform_rule(rule)
return jsonify({
"status": "ok",
"item": st.export(),
"selected_item": str(compstate.get_next_step_label(subitem, label))
})
else:
return jsonify({
"status": "choose",
"item": st.export(),
"selected_item": str(compstate.get_next_step_label(subitem, label))
})
else:
return jsonify({
"status": "error",
"msg": "Selected item is not part of a calculation."
})
@app.route("/api/solve-equation", methods=["POST"])
def integral_solve_equation():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
facts = data['selected_facts']
if len(facts) != 1:
return jsonify({
"status": "error",
"msg": "Exactly one fact must be selected"
})
lhs: integral.expr.Expr
for fact_label in facts:
fact = st.get_by_label(integral.compstate.Label(fact_label))
if isinstance(fact, compstate.CalculationStep):
lhs = fact.res
elif isinstance(fact, compstate.Calculation):
lhs = fact.start
else:
return jsonify({
"status": "error",
"msg": "Selected fact is not part of a calculation."
})
if isinstance(subitem, (compstate.CalculationStep, compstate.Calculation)):
rule = integral.rules.IntegrateByEquation(lhs)
subitem.perform_rule(rule)
return jsonify({
"status": "ok",
"item": st.export(),
"selected_item": str(compstate.get_next_step_label(subitem, label))
})
else:
return jsonify({
"status": "error",
"msg": "Selected item is not part of a calculation."
})
@app.route("/api/perform-step", methods=["POST"])
def integral_perform_step():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
rule = compstate.parse_rule(data['rule'])
if isinstance(rule, (integral.rules.ApplyInductHyp, integral.rules.DerivIntExchange,
integral.rules.IntSumExchange, integral.rules.SeriesEvaluationIdentity)):
rule = integral.rules.OnSubterm(rule)
subitem = st.get_by_label(label)
if isinstance(subitem, (compstate.CalculationStep, compstate.Calculation)):
subitem.perform_rule(rule)
elif isinstance(subitem, compstate.RewriteGoalProof):
subitem.begin.perform_rule(rule)
else:
return jsonify({
"status": "error",
"msg": "Selected item is not part of a calculation."
})
return jsonify({
"status": "ok",
"item": st.export(),
"selected_item": str(compstate.get_next_step_label(subitem, label))
})
@app.route("/api/perform-slagle", methods=["POST"])
def integral_perform_slagle():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
if isinstance(subitem, compstate.Calculation):
e = subitem.last_expr
elif isinstance(subitem, compstate.CalculationStep):
e = subitem.parent.last_expr
else:
raise NotImplementedError
steps = slagle.Slagle(e).export_step()
subitem.perform_rules(steps)
return jsonify({
"status": "ok",
"item": st.export(),
"selected_item": str(compstate.get_next_step_label(subitem, label))
})
@app.route("/api/query-theorems", methods=["POST"])
def integral_query_theorems():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
eqs = []
for prev_item in file.content[:cur_id]:
for eq in prev_item.get_facts():
eqs.append({
'eq': str(eq),
'latex_eq': integral.latex.convert_expr(eq)
})
return jsonify({
"status": "ok",
"theorems": eqs
})
@app.route("/api/query-vars", methods=["POST"])
def integral_query_vars():
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
if isinstance(subitem, (compstate.CalculationStep, compstate.Calculation)):
res = subitem.res if isinstance(subitem, compstate.CalculationStep) else subitem.start
elif isinstance(subitem, compstate.RewriteGoalProof):
res = subitem.begin.start
else:
return jsonify({
"status": "error",
})
vars = list(res.get_vars())
query_vars = []
for var in vars:
query_vars.append({'var': var, 'expr': ""})
return jsonify({
"status": "ok",
"query_vars": query_vars
})
@app.route("/api/query-expr", methods=['POST'])
def integral_query_expr():
data = json.loads(request.get_data().decode('UTF-8'))
try:
e = integral.parser.parse_expr(data['expr'])
return jsonify({
"status": "ok",
"latex_expr": integral.latex.convert_expr(e)
})
except Exception as e:
return jsonify({
"status": "fail",
"exception": str(e)
})
@app.route("/api/query-last-expr", methods=["POST"])
def integral_query_last_expr():
# Query selected expression according to label
data = json.loads(request.get_data().decode('UTF-8'))
book_name = data['book']
filename = data['file']
cur_id = data['cur_id']
file = compstate.CompFile(book_name, filename)
for item in data['content']:
file.add_item(compstate.parse_item(file, item))
label = compstate.Label(data['selected_item'])
st: compstate.StateItem = file.content[cur_id]
subitem = st.get_by_label(label)
if isinstance(subitem, (compstate.CalculationStep, compstate.Calculation)):
res = subitem.res if isinstance(subitem, compstate.CalculationStep) else subitem.start
elif isinstance(subitem, compstate.RewriteGoalProof):
res = subitem.begin.start
else:
return jsonify({
"status": "error",
})
return jsonify({
"last_expr": str(res),
"latex_expr": integral.latex.convert_expr(res),
"status": "ok",
})
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/bhzhan/holpy.git
git@gitee.com:bhzhan/holpy.git
bhzhan
holpy
holpy
master

搜索帮助