Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Shekharrajak/8925cb5c79d548d9e0e80014baffd7ca to your computer and use it in GitHub Desktop.
Save Shekharrajak/8925cb5c79d548d9e0e80014baffd7ca to your computer and use it in GitHub Desktop.
def _solve_using_known_values(result, solver):
"""Solves the system using already known solution
(result contains the dict <symbol: value>).
solver is `solveset_complex` or `solveset_real`.
"""
# helper functions
def _append_new_soln(sol, rnew, newresult, imgset_info):
"""If rnew (A dict <symbol: soln> ) contains valid soln
append it to newresult list.
"""
# for check_sol using imageset expr if imageset
# present.
# TODO: put n = 0 in imageset expr
if not any(checksol(d, rnew) for d in exclude):
# if sol was imageset then add imageset
local_n = None
if imgset_info:
local_n = imgset_info[0]
base = imgset_info[1]
# use ImageSet, we have dummy in sol
dummy_list = list(sol.atoms(Dummy))
# use one dummy `n` which is in
# previous imageset
local_n_list = [
local_n for i in range(
0, len(dummy_list))]
dummy_zip = zip(dummy_list, local_n_list)
lam = Lambda(local_n, sol.subs(dummy_zip))
rnew[sym] = ImageSet(lam, base)
elif soln_imageset:
rnew[sym] = soln_imageset[sol]
# restore original imageset
restore_sym = set(rnew.keys()) & \
set(original_imageset.keys())
for key_sym in restore_sym:
img = original_imageset[key_sym]
rnew[key_sym] = img
newresult.append(rnew)
return newresult
# end of def _append_new_soln
def _do_solveset(eq2, unsolved_syms, newresult, imgset_info):
soln_imageset = {}
for sym in unsolved_syms:
not_solvable = False
solveset_call = 0
conditionset_got = 0
try:
soln = solver(eq2, sym)
solveset_call += 1
soln_new = S.EmptySet
if isinstance(soln, Complement):
# extract solution and complement
complements[sym] = soln.args[1]
soln = soln.args[0]
# complement will be added at the end
if isinstance(soln, Intersection):
# Interval will be at 0th index always
if soln.args[0] != Interval(-oo, oo):
# sometimes solveset returns soln
# with intersection S.Reals, to confirm that
# soln is in domain=S.Reals
intersections[sym] = soln.args[0]
soln_new += soln.args[1]
soln = soln_new if soln_new else soln
if index > 0 and solver == solveset_real:
# one symbol's real soln , another symbol may have
# corresponding complex soln.
if not isinstance(soln, ImageSet):
soln += solveset_complex(eq2, sym)
except NotImplementedError:
return S.EmptySet, solveset_call, conditionset_got
if isinstance(soln, ConditionSet):
soln = S.EmptySet
# dont do `continue` we may get soln
# in terms of other symbol(s)
not_solvable = True
conditionset_got += 1
soln, soln_imageset = _extract_main_soln(soln, soln_imageset)
# remove this
# if isinstance(soln, Complement):
# # extract solution and complement
# complements[sym] = soln.args[1]
# soln = soln.args[0]
# # complement will be added at the end
# if isinstance(soln, ImageSet):
# soln_imagest = soln
# expr2 = soln.lamda.expr
# soln = FiniteSet(expr2)
# soln_imageset[expr2] = soln_imagest
# end remove
for sol in soln:
newresult = _add_valid_soln(
sol, newresult, soln_imageset, imgset_info)
# solution got for sym
if not not_solvable:
got_symbol.add(sym)
return soln, soln_imageset,
newresult, solveset_call, conditionset_got
# end of def _do_solveset()
def _add_valid_soln(sol, newresult, soln_imageset, imgset_info):
sol, soln_imageset = _extract_main_soln(
sol, soln_imageset)
# sol will be in FiniteSet
sol = list(sol)[0]
free = sol.free_symbols
if got_symbol and any([
ss in free for ss in got_symbol
]):
# sol depends on previously solved symbols
# then continue
return
rnew = res.copy()
# put each solution in res and append the new result
# in the new result list (solution for symbol `s`)
# along with old results.
for k, v in res.items():
if isinstance(v, Expr):
# if any unsolved symbol is present
# Then subs known value
rnew[k] = v.subs(sym, sol)
# and add this new solution
rnew[sym] = sol
newresult = _append_new_soln(sol, rnew, newresult, imgset_info)
return newresult
def _new_soln_using_eq(eq, index, result, soln_imageset):
solveset_call = 0
conditionset_got = 0
newresult = []
# if imageset expr is used to solve other symbol
imgset_info = ()
for res in result:
if soln_imageset:
# find the imageset and use it's expr.
for key_res, value_res in res.items():
if isinstance(value_res, ImageSet):
res[key_res] = value_res.lamda.expr
original_imageset[key_res] = value_res
dummy_n = value_res.lamda.expr.atoms(Dummy).pop()
base = value_res.base_set
imgset_info = (dummy_n, base)
# update eq with everything that is known so far
eq2 = eq.subs(res)
unsolved_syms = _unsolved_syms(eq2, sort=True)
if not unsolved_syms:
if res:
newresult.append(res)
break # skip as it's independent of desired symbols
(soln, soln_imageset, newresult, solvest_call,
conditionst_got) = _do_solveset(
eq2, unsolved_syms, newresult, imgset_info)
solveset_call += solvest_call
conditionset_got += conditionst_got
result = newresult
return result, solveset_call, conditionset_got
# end of def _new_soln_using_eq()
# main code of def _solve_using_known_values()
# stores imageset <expr: imageset(Lambda(n, expr), base)>.
soln_imageset = {}
total_solveset_call_inner = 0
total_conditionset_inner = 0
# sort such that equation with the fewest potential symbols is first.
# means eq with less variable first
for index, eq in enumerate(eqs_in_better_order):
got_symbol = set() # symbols solved in one iteration
original_imageset = {}
result, solvset_call, conditionset_got = \
_new_soln_using_eq(eq, index, result, soln_imageset)
total_solveset_call_inner += solvset_call
total_conditionset_inner += conditionset_got
return result, total_solveset_call_inner, total_conditionset_inner
# end def _solve_using_know_values
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment