| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 | from sympy import *from itertools import product, combinationsimport plotly.graph_objects as goimport numpy as npimport mathclass solver:    corners = (-100, 100)    data: list[str]    equalations: list[Equality]    sequance = None    solutions: list    points: list    ndims: int    __X = [*symbols('x1 x2 x3')]    @staticmethod    def toEq(data):        data = data[:]        for i,linEx in enumerate(data):            data[i] = Eq(*[simplify(side) for side in linEx.split('=')])        return data    def solve(self):        result = []        for Eq in self.equalations:            lin = []            for prod in product([-100, 100], repeat=self.ndims-1):                subEq = Eq.copy()                X = self.__X[:]                high_sym = sorted(list(subEq.free_symbols), key=lambda x: x.name)[0]                X.remove(high_sym)                values = [(sym,corner) for sym, corner in zip(X, prod)]                subEq = subEq.subs(values)                solution = int(solve(subEq, high_sym)[0])                values.append((high_sym, solution))                lin.append(sorted(values, key=lambda x: x[0].name))            result.append([[dot[dim][1] for dot in lin] for dim in range(self.ndims)])        return result    def right_dote(self, dote):        flag = True        for line in self.data:            for sym, val in zip(self.__X, dote): line = line.replace(sym.name, str(val))            flag *= eval(line)        return flag    def get_dots(self):        result = []        for Eqs in combinations(self.equalations, r=2):            if Eqs[0] == Eqs[1]: continue            solution = list(solve(Eqs, Eqs[0].free_symbols | Eqs[1].free_symbols, set=True))[1]            if len(solution) == 0: continue            dot = list(solve(Eqs, Eqs[0].free_symbols | Eqs[1].free_symbols, set=True)[1])[0]            if self.right_dote(dot): result.append(dot)        reference_point = result[0]        sorted_coordinates = sorted(result, key=lambda point: math.atan2(point[1] - reference_point[1], point[0] - reference_point[0]))        return [[float(val[dim]) for val in sorted_coordinates] for dim in range(self.ndims)]    def show(self):        fig = go.Figure()        for line, names in zip(self.solutions, self.data):            fig.add_trace(go.Scatter({dim:val for val, dim in zip(line, ('x','y','z'))}, name=str(names)))        fig.add_trace(go.Scatter({dim:val for val, dim in zip(self.get_dots(), ('x','y','z'))}, mode='markers', fill='toself', fillpattern=dict(fillmode='replace', shape='x')))        fig.add_trace(go.Scatter(x=[0, self.gradient[0]], y=[0, self.gradient[1]],                                 marker=dict(color='black', symbol='arrow', size=16, angleref="previous"),                                 line = dict(width=4, dash='dot', color='black')))        touch = len(fig.data)        for step in np.arange(0, self.count, self.step):            k = ((self.gradient[1]-0) * (step-0) - (self.gradient[1]-0) * (0-0)) / ((self.gradient[1]-0)**2 + (self.gradient[0]-0)**2)            x4 = step - k * (self.gradient[1]-0)            y4 = 0 + k * (self.gradient[0]-0)            y5 = y4+y4            x5 = x4+(x4-step)            fig.add_trace(                go.Scatter(visible=False, line=dict(color='black', width=2),                           x=[step, x4, x5], y=[0, y4, y5])            )        fig.data[touch].visible = True        steps = []        for i in range(len(fig.data[touch:])):            step = dict(                method="update",                args=[{"visible": [True]*touch + [False] * (len(fig.data)-touch)},                    {"title": "Slider switched to step: " + str(i)}],  # layout attribute            )            step["args"][0]["visible"][i] = True  # Toggle i'th trace to "visible"            steps.append(step)        sliders = [dict(            active=10,            currentvalue={"prefix": "Frequency: "},            pad={"t": 50},            steps=steps        )]        fig.update_layout(            sliders=sliders        )        fig.update_xaxes(title_text='x1', gridwidth=1)        fig.update_yaxes(title_text='x2', gridwidth=1)        fig.show()    def __init__(self, seq: str, data: list[str], ndims=2, step=0.01, count=10):        self.data = data        self.gradient = list(map(int,Poly(simplify(seq)).coeffs()))        self.equalations = solver.toEq([lin.replace('>','').replace('<', '') for lin in data])        self.ndims = ndims        self.__X = self.__X[:ndims]        self.solutions = self.solve()        self.count = count        self.step = stepif __name__ == '__main__':    # solver( seq='3*x1 + 4*x2',    #         data=['4*x1 + x2 <= 8',     #         'x1 >= 0',     #         'x1 - x2 >= -3',     #         'x2 >= 0'], ndims=2).show()    # solver( seq='3*x1 + 2*x2',    #         data=['2*x1 + 3*x2 <= 6',     #         'x1 <= 2', 'x1 >= 0',     #         '2*x1 - x2 >= 0',     #         'x2 >= 0', 'x2 <= 1'], ndims=2).show()    # solver( seq='x1 + 3*x2',    #         data=['2*x1 + 3*x2 <= 24',     #         'x1 >= 0',     #         'x1 - x2 <= 7',     #         'x2 >= 0', 'x2 <= 6'], ndims=2, step=0.1, count=25).show()    # solver( seq='x1 - 1.1*x2 + 7.4',    #         data=['x1 >= 0',     #         'x2 >= 0',     #         'x1 + x2 <= 10',     #         '10 - x1 >= 0', '10 - x2 >= 0'], ndims=2, step=0.1, count=15).show()        pass
 |