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/ce29e63d591b3ce15c939e3d6a66cc05 to your computer and use it in GitHub Desktop.
Save Shekharrajak/ce29e63d591b3ce15c939e3d6a66cc05 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`.
"""
# stores imageset <expr: imageset(Lambda(n, expr), base)>.
soln_imageset = {}
total_solveset_call_inner = 0
total_conditionset_inner = 0
def _extract_main_soln(sol):
"""separate the Complements, Intersections, ImageSet lambda expr
and it's base_set.
"""
# if there is union, then need to check
# complement, intersection, Imageset
# order should not be changed.
if isinstance(sol, Complement):
# extract solution and complement
complements[sym] = sol.args[1]
sol = sol.args[0]
# complement will be added at the end
if isinstance(sol, Intersection):
# Interval will be at 0th index always
if sol.args[0] != Interval(-oo, oo):
# sometimes solveset returns soln
# with intersection S.Reals, to confirm that
# soln is in domain=S.Reals
intersections[sym] = sol.args[0]
sol = sol.args[1]
# after intersection and complement Imageset should
# be checked.
if isinstance(sol, ImageSet):
soln_imagest = sol
sol = sol.lamda.expr
soln_imageset[sol] = soln_imagest
return sol
# end of def _extract_main_soln
# 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):
newresult = []
got_symbol = set() # symbols solved in one iteration
hit = False
original_imageset = {}
# if imageset expr is used to solve other symbol
imgset_yes = False
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_yes = (dummy_n, base)
soln_imageset = {}
# 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
for sym in unsolved_syms:
not_solvable = False
try:
soln = solver(eq2, sym)
total_solveset_call_inner += 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:
# If sovleset not able to solver eq2. Next time we may
# get soln using next eq2
continue
if isinstance(soln, ConditionSet):
soln = S.EmptySet
# dont do `continue` we may get soln
# in terms of other symbol(s)
not_solvable = True
total_conditionset_inner += 1
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
# if there is union of Imageset in soln
# no testcase is written for this if block
if isinstance(soln, Union):
soln_args = soln.args
soln = []
# need to use list.
# (finiteset union imageset).args is
# (finiteset, Imageset). But we want only iteration
# so append finteset elements and imageset.
for soln_arg2 in soln_args:
if isinstance(soln_arg2, FiniteSet):
list_finiteset = list(
[sol_1 for sol_1 in soln_arg2])
soln += list_finiteset
else:
# ImageSet or Intersection or complement
# append them directly
soln.append(soln_arg2)
for sol in soln:
# helper funciton. used in this loop
def _append_new_soln(rnew):
"""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_yes:
local_n = imgset_yes[0]
base = imgset_yes[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)
# end of def _append_new_soln
sol = _extract_main_soln(sol)
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
continue
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
_append_new_soln(rnew)
hit = True
# solution got for sym
if not not_solvable:
got_symbol.add(sym)
if not hit:
return _return_conditionset()
else:
result = newresult
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