Helpex - Trao đổi & giúp đỡ Đăng nhập
28

Tôi đang mã hóa một hàm giải một số phương trình đồng thời tùy ý. Số lượng phương trình được thiết lập bởi một trong các tham số của hàm và mỗi phương trình được xây dựng từ một số ký hiệu - càng nhiều ký hiệu thì càng có nhiều phương trình. Điều này có nghĩa là tôi không thể đơn giản mã hóa các phương trình, hoặc thậm chí các ký hiệu cần thiết để ghép các phương trình lại với nhau; hàm cần có khả năng xử lý bất kỳ số phương trình nào. Vì vậy, câu hỏi của tôi là, làm cách nào để tạo ra một danh sách các ký hiệu?

Tôi có một giải pháp khả thi, nhưng ruột của tôi nói với tôi rằng nó sẽ không hiệu quả lắm. Xin vui lòng cho tôi biết nếu có một cách tốt hơn để làm điều này.

Tôi mới làm quen với SymPy và vẫn đang cảm thấy theo cách của mình. Theo như tôi thấy, Biểu tượng cần được định nghĩa bằng một chuỗi. Do đó, tôi có thể tạo một chuỗi chuỗi bằng cách thêm một số tăng dần vào một chữ cái (giả sử 't0', 't1', v.v.), thêm chúng vào danh sách và sau đó tạo các ký hiệu bằng cách sử dụng các chuỗi đó làm tham số. Bản thân những ký hiệu đó sẽ được lưu trữ trong một danh sách và sẽ được sử dụng để tạo ra các phương trình.

def solveEquations(numEquations):
    symbolNameList = []
    symbolList = []
    equationList = []
    for i in range(numEquations):
        name = 't' + str(i)
        symbolNameList.append(name)
        symbolList.append(Symbol(name))

    for i in range(numEquations):
        equation = 0
        for sym in symbolList:
            equation += sym ** i # Or whatever structure the equation needs
        equationList.append(equation)


    #Then go on to solve the equations...

Đây có phải là cách tốt nhất để làm điều này, hay có một cách tiếp cận hiệu quả hơn?

28 hữu ích 0 bình luận 14k xem chia sẻ
45

Các symbolschức năng có thể được sử dụng để dễ dàng tạo ra danh sách các biểu tượng

In [1]: symbols('a0:3')
Out[1]: (a₀, a₁, a₂)

In [2]: numEquations = 15

In [3]: symbols('a0:%d'%numEquations)
Out[3]: (a₀, a₁, a₂, a₃, a₄, a₅, a₆, a₇, a₈, a₉, a₁₀, a₁₁, a₁₂, a₁₃, a₁₄)
45 hữu ích 1 bình luận chia sẻ
13

numbered_symbols("t")sẽ trả về một máy phát điện mà tạo ra t0, t1, t2, vv Bạn có thể sử dụng các starttham số để chọn một giá trị khởi đầu khác nhau. Và nếu bạn muốn sử dụng biến giả, hãy sử dụng numbered_symbols("t", cls=Dummy).

13 hữu ích 0 bình luận chia sẻ
7

Không biết có thêm thông tin hữu ích nào vào chủ đề hay không, nhưng tôi sử dụng phương pháp sau để tạo danh sách các biến tượng trưng:

x = [sympy.symbols('x%d' % i) for i in range(3)]

Và sau đó tôi có thể sử dụng nó bình thường trong một phương trình:

eq = x[0]**2 + x[1]*2 + x[2]
print(sympy.diff(eq,x[0]))
>>> 2*x0
7 hữu ích 0 bình luận chia sẻ
4

Với locals()và tính năng hiểu từ điển, bạn có thể tạo lặp đi lặp lại cả biểu tượng và biến cục bộ python có tên tương tự. Ví dụ:

>>> symbols_dict = dict(('a%d'%k, symbols('a%d'%k)) for k in range(3))
>>> locals().update(symbols_dict)

Kiểm tra xem nó có hoạt động không:

>>> print(expand((a0+a2)*(a0+a1**2)))
a0**2 + a0*a1**2 + a0*a2 + a1**2*a2
4 hữu ích 0 bình luận chia sẻ
3

Bạn có thể tạo một lớp con dicttự động trả về Symbols:

import sympy as sym

class SymDict(dict):
    # http://stackoverflow.com/a/3405143/190597
    def __missing__(self, key):
        self[key]=sym.Symbol(key)
        return self[key]

def solveEquations(numEquations):
    symbol = SymDict()
    symbolList = ['t'+str(i) for i in range(numEquations)]
    equationList = [sum(symbol[s]**i for s in symbolList)
                    for i in range(numEquations)]
    print(equationList)

solveEquations(3)    
# [3, t0 + t1 + t2, t0**2 + t1**2 + t2**2]
3 hữu ích 0 bình luận chia sẻ
2

Cách tiếp cận của bạn là tốt, mặc dù không cần phải lưu trữ các tên biểu tượng một cách riêng biệt (bạn có thể truy cập vào tên của biểu tượng thông qua thuộc tính của nó name).

Ngoài ra, bạn có thể diễn đạt việc tạo biểu tượng ngắn gọn hơn một chút (mặc dù không hiệu quả hơn), ví dụ:

symbolList = map(lambda i: Symbol('t' + str(i)), xrange(numEquations))

Tuy nhiên, đối với trường hợp sử dụng của bạn (biến tạm thời), biến giả có thể là cách để thực hiện:

symbolList = map(Dummy, xrange(numEquations))

Điều này không thực sự hiệu quả hơn, vì bên trong Dummylớp cũng đang sử dụng bộ đếm để tạo ra các tên duy nhất, nhưng nó gọn gàng và rõ ràng hơn một chút.

2 hữu ích 0 bình luận chia sẻ
2

Tôi thích cách tiếp cận do @ jp-sena đưa ra và những gì tôi sẽ đề xuất trông rất giống nó. Sự khác biệt là bạn không cần phải biết mình sẽ cần bao nhiêu ký hiệu - bạn sẽ chỉ có quyền truy cập vào bao nhiêu ký tự mà bạn cần theo chỉ mục. Sử dụng IndexedBaselàm biểu tượng của bạn:

>>> x = IndexedBase('x')  # you've got access to a virtual array of x values
>>> solve(x[1]**2 + 1/x[4], x[4])
[-1/x[1]**2]

Đối với mục đích hiển thị, bạn có thể muốn tạo một từ điển thay thế. Để tạo các ký hiệu được đánh số, bạn có thể làm

>>> reps = dict(zip([x[i] for i in range(n_used+1)], numbered_symbols('c')))
>>> (x[2]**2 + 1/x[4]).subs(reps)
c2**2 + 1/c4

Hoặc, nếu bạn đang sử dụng ít hơn 26 ký hiệu, bạn có thể sử dụng các chữ cái với

>>> reps = dict(zip([x[i] for i in range(n_used+1)], symbols('a:z')))
>>> (x[2]**2 + 1/x[4]).subs(reps)
c**2 + 1/e

BTW, xlà một IndexedBase và x[1]là một đối tượng Indexed mà .basexvà có .indiceslà một tuple của bất cứ con số xuất hiện trong dấu ngoặc đơn. Cả IndexedBase và Indexed sẽ hiển thị trong một .free_symbolstruy vấn.

>>> (x[1,2] + 3).free_symbols
{x, x[1, 2]}
>>> x[1, 2].indices
(1, 2)
>>> x[1].base
x
2 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ python symbols sympy equation-solving , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading