def solve_for_one_nonzero_variable(conditions,vars):
     conds=[]
     for var in vars:
         conds.append(conditions+[var != 0])
     #print conds
     solutions=SE.solve_ext(conds,*vars)
     return solutions
def max_index_cond_k(cond_tuples,k,var_vec,in_pos_eigenspace_conds):
    cond_k = cond_tuples[k]
    rest_conds = map(lambda cts:map(lambda ct: ct[1], cts),
        cond_tuples[0:k] + cond_tuples[k+1:])
    rest_conditions_combinations = map(lambda css: list(itertools.chain(*css)),
        SE.any_combination_of(rest_conds))
    vars=in_pos_eigenspace_conds[1]+in_pos_eigenspace_conds[2]
    # print "cond_k",cond_k
    # print "rest_conds",rest_conds
    # print "combinations",rest_conditions_combinations
    for idx,conds in cond_k:
        cond_disjunct=map(lambda cs:cs+in_pos_eigenspace_conds[0]+conds,rest_conditions_combinations)
        # print idx, cond_disjunct
        # print idx, in_pos_eigenspace_conds[0]
        # print idx, conds
        # print idx, in_pos_eigenspace_conds[1]+in_pos_eigenspace_conds[2]
        solutions=SE.solve_ext(cond_disjunct,*vars)
        # print "solutions:", solutions
        if len(solutions) > 0:
            return (idx,solutions)
    return (None,[])
def find_Q_min(S_min,space_exts):
    def solve_for_one_nonzero_variable(conditions,vars):
        conds=[]
        for var in vars:
            conds.append(conditions+[var != 0])
        #print conds
        solutions=SE.solve_ext(conds,*vars)
        return solutions
    def gen_vars(col_count,exts):
        vardict=dict()
        vars=[]
        for c in range(col_count):
            vardict[c]=dict()
            for e_id in range(len(exts)):
                v=var("v_c"+str(c)+"_e"+str(e_id))
                vardict[c][exts[e_id]]=v
                vars.append(v)
                assume(v,'rational')
        return vardict,vars
    def solution_to_coefficients(solution,vardict,vars):
        idict=dict()
        for eq in solution:
            for v in vars:
                if eq.operator() == operator.eq:
                    if eq.lhs() == v:
                        idict[v]=eq.rhs()
                    if eq.rhs() == v:
                        idict[v]=eq.lhs()
                if eq.operator() == operator.ne:
                    if (eq.lhs() == v and eq.rhs() == 0) or (eq.rhs() == v and eq.lhs() == 0):
                        idict[v] = SR(1)
        idict = dict(map(lambda x:(x[0],x[1].substitute(idict)),idict.items())) # maybe mor than one subtitution step is needed
        coeffs=[]
        for c in vardict.keys():
            coeff=0
            for ext in vardict[c].keys():
                v = vardict[c][ext]
                if not idict.has_key(v):
                    idict[v]=0
                coeff = coeff + idict[v]*ext.radical_expression()
            coeffs.append(coeff)
        # print "idict",idict
        return coeffs

    S_min_matrix = S_min.matrix().transpose()
    dims = S_min_matrix.dimensions()
    vecs = S_min_matrix.columns()
    exts = map(abs,[AA(1)]+space_exts) # it does not suffice to take the space extension of S_min
    # print exts
    conditions=[]
    vardict,vars=gen_vars(dims[1],exts)
    for r in range(dims[0]):
        #print "row", S_min_matrix.row(r)
        d=dict()
        for c in range(dims[1]):
            for e_id in range(len(exts)):
                num_part=QQbar(S_min_matrix[r,c])*exts[e_id]
                nf_gens=QQbar(num_part).as_number_field_element()[2].im_gens()
                # print "np:",vardict[c][exts[e_id]],num_part,nf_gens
                signf=1
                if QQbar(num_part) < 0:
                    signf = -1
                for gen in nf_gens:
                    #v=var("v_c"+str(c)+"_e"+str(e_id))
                    v=vardict[c][exts[e_id]]
                    k=abs(gen) # only use positive extensions as key
                    if d.has_key(k):
                        d[k].append(signf*v)
                    else:
                        d[k] = [signf*v]
            # print "d:",d
        for ext in d.keys():
            #print ext,ext != 1
            if ext != 1:
                conditions.append(sum(d[ext]) == 0)
    # print "basic conditions", conditions
    # print vardict
    # print vars
    solutions= solve_for_one_nonzero_variable(conditions,vars) # find as many possible solutions to get all vectors of Q_min
    # print solutions
    # reduce to real solutions not containing 0 != 0
    solutions= SE.solve_ext(solutions,vars)
    # print solutions
    forget() # forget that the variables are rational
    coeffs=map(lambda s: solution_to_coefficients(s,vardict,vars),solutions)
    # print "coeffs",coeffs
    vecs=map(lambda v:MX.linear_combination_of(vector(v),S_min_matrix),coeffs)
    # print vecs
    V=VectorSpace(QQ,S_min.degree())
    Q_min=V.span(vecs)
    return Q_min