0

I'm looking for a way to easily manipulate the results given by the solveset method in the SymPy package. In particular, I have a function omega(x,n,p,gamma) and I want to compute its roots while keeping gamma as a symbolic variable:

def omega(x,n,p,gamma):
    #do stuff
    
gamma, x=var('gamma x')
roots=solveset(omega_complete(x,30,1,gamma), x)

omega returns a non-linear combination of x and gamma, so other methods in the same library such as linsolve or solve do not work. Currently I am stuck with an output of type FiniteSet after calling solveset: the result is printed in LaTeX and looks like this.

The naive conversion list(roots) gives the error TypeError: did not evaluate to a bool: None. The alternative way that I found in this answer using roots.args[0], roots.args[1] is also not what I'm looking for. Can anyone help?


The full code (note that are actually two functions, omega_complete and omega_cycle, that are similarly defined):

import numpy as np
import cmath as cm
from sympy import *

def target(n,p):
    w=[]
    for j in range(n):
        if j==p:
            w.append(1)
        else: w.append(0)
    return np.array(w)

###---complete---####

def change_basis_complete(N):
    
    matrix=np.zeros((N,N),dtype=complex)
    for n in range(0,N):
        for m in range(0,N):
            matrix[n,m]=(1/cm.sqrt(N))*cm.exp(2*np.pi*1j*(n+1)*(m+1)/N)
    return matrix  

def new_target_complete(N,p):
    return np.dot(change_basis_complete(N),target(N,p))

def omega_complete(x,N,p,gamma):
    
    w=new_target_complete(N,p)
    
    old_spectrum=np.zeros(N)
    for i in range(N-1):
        old_spectrum[i]=N
    old_spectrum[N-1]=0
    
    sigma=0
    for i in range(N):
        sigma+=(abs(w[i])**2)/(gamma*old_spectrum[i]-x)
    return 1-sigma

###---cycle---####

def change_basis_cycle(N):
    
    matrix=np.zeros((N,N),dtype=complex)
    for n in range(0,N):
        for m in range(0,N):
            matrix[n,m]=(1/cm.sqrt(N))*cm.exp(-2*np.pi*1j*(n+1)*(m+1)/N)
    return matrix  

def new_target_cycle(N,p):
    return np.dot(change_basis_cycle(N),target(N,p))

def omega_cycle(x,N,p,gamma):
    
    w=new_target_cycle(N,p)
    
    old_spectrum=np.zeros(N)
    for n in range(N):
        old_spectrum[n]=2-2*cm.cos((2*cm.pi*n)/N)
   
    sigma=0
    for i in range(N):
        sigma+=(abs(w[i])**2)/(gamma*old_spectrum[i]-x)
    return 1-sigma
  • What about `list(roots.args)`? – Oscar Benjamin Apr 28 '21 at 21:17
  • Are you sure it's a FiniteSet? If it is then I think `list(roots)` should work. It's hard to comment given that your code is incomplete but perhaps you could show the output from `srepr(roots)`. – Oscar Benjamin Apr 28 '21 at 21:18
  • @OscarBenjamin Thank you, `list(roots.args)` seems to be working. Yes, it is `FiniteSet`, but strangely enough `list()` does not work! There is still one last issue, for which I should probably ask a separate question. `solveset` does not specify the multiplicity of the roots, and besides the data it returns are organized in a pretty strange way: as you can see in the image above the converted output is a nested list with two elements each. Weird, huh? – Optimus Prime Number Apr 28 '21 at 23:00
  • @OscarBenjamin If you add your comment as an answer I will accept it! – Optimus Prime Number Apr 28 '21 at 23:01
  • @OscarBenjamin One last thing: do you happen to know how to deal if the result is of type `ConditionSet`? The same approach gives me an error (`ConditionSet` object is not iterable). – Optimus Prime Number Apr 28 '21 at 23:24
  • Can you show the actual examples in the question? You don't need to show all the code calling `solveset` just `srepr(roots)` to show the output from `solveset`. – Oscar Benjamin Apr 29 '21 at 11:33
  • @OscarBenjamin I've made a pastebin with the result of calling `srepr(roots)` with `roots=solveset(omega_cycle(x,4,1,gamma), x)`: the link is https://pastebin.com/5bcB14xD. – Optimus Prime Number Apr 30 '21 at 00:24
  • Actually the best thing would be to show what `omega_cycle(x,4,1,gamma)` is. I'm guessing it's a polynomial and you would be better off using `roots` rather than `solveset` – Oscar Benjamin Apr 30 '21 at 11:32
  • @OscarBenjamin At this point it's probably best if I simply add the full code, it's actually not that long or complicated. You can find it above! – Optimus Prime Number Apr 30 '21 at 16:22

1 Answers1

0

SymPy issues would love to know the equation you are trying to solve so this can be reproduced: there is no reason that list(finite_set_object) should not give you a list of the args. But if list(finite_set_object.args) works...hmm.

Regarding the ConditionSet or any of the other objects that solveset returns, you have to read what they mean to understand what you can do with them. Often, ConditionSet is returned like ConditionSet(Eq(eq, 0), domain) to say "the solution of eq = 0 was not found" and so there is no way to convert that to a list of solutions.

smichr
  • 16,948
  • 2
  • 27
  • 34
  • I can add the code to the github page, no problem. As for the ConditionSet object, what does it mean exactly that no solution is found? I know for sure that my equation has a certain number of real solutions. Could it be due to the complexity of the calculation? – Optimus Prime Number Apr 30 '21 at 00:28
  • An equation can have numerical solutions that cannot be represented in closed form. I can't tell unless you show the equation. – smichr Apr 30 '21 at 11:29
  • The output is now linked to in a comment on the OP. It is a Complement set rather than a FiniteSet. The finite set can be obtained with `.args[0]`. – Oscar Benjamin Apr 30 '21 at 11:33
  • The link in the OP shows a single opening and closing brace around two elements i.e., a FiniteSet. Perhaps the link changed? It would be good to have the right link there. – smichr Apr 30 '21 at 12:33
  • First of all, thank you both for your interest. I have added the full code in the original post, to remove all possible doubts. It's not very long or complicated to read, I hope. – Optimus Prime Number Apr 30 '21 at 16:24
  • OK, I can see it is a Complement but in the pic that is shown in the link the " \ {0, 30.0⋅γ}" part is missing: that means "...but x cannot be 0 or 30.0⋅γ." – smichr Apr 30 '21 at 17:09