Решение линейного уравнения

Если вы пришли сюда, чтобы выбрать строки из фрейма данных, включив те, чье значение столбца НЕ является ни одним из списка значений, вот как перевернуть ответ unutbu для списка значений выше:

df.loc[~df['column_name'].isin(some_values)]

(Чтобы не включать одно значение, конечно, вы просто используете обычный оператор не равно, !=.)

Пример:

import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split()})
print(df)

дает нам

     A      B
0  foo    one
1  bar    one
2  foo    two
3  bar  three
4  foo    two
5  bar    two
6  foo    one
7  foo  three    

Подмножество только для тех строк, которые ARE NOT one или three в столбце B:

df.loc[~df['B'].isin(['one', 'three'])]

дает

     A    B
2  foo  two
4  foo  two
5  bar  two
38
задан Víctor Gómez 17 December 2015 в 13:25
поделиться

10 ответов

Исключение Гаусса Правила Крамера и является двумя хорошими, алгоритмами общего назначения (также см. Одновременные Линейные уравнения ). Если Вы ищете код, проверяете GiNaC, Максимумы , и SymbolicC ++ (в зависимости от Вашего лицензирования требований, конечно).

РЕДАКТИРОВАНИЕ: Я знаю, что Вы работаете на земле C, но я также должен произнести оправдательную речь по адресу SymPy (компьютерная система алгебры в Python). Можно узнать о много из его алгоритмов (если можно прочитать немного Python). Кроме того, это находится под новой лицензией BSD, в то время как большинство бесплатных математических пакетов является GPL.

19
ответ дан Brian Jorgensen 27 November 2019 в 03:43
поделиться

Для 3x3 система линейных уравнений я предполагаю, что она должна была бы хорошо развернуть Ваши собственные алгоритмы.

Однако Вам, возможно, придется волноваться о точности, делении на нуль или действительно небольших числах и что сделать о бесконечно многих решениях. Мое предложение должно пойти со стандартным числовым пакетом линейной алгебры такой как LAPACK.

7
ответ дан CoderCroc 27 November 2019 в 03:43
поделиться

Вы можете решить это с помощью программы точно так же, как вы решаете ее вручную (с умножением и вычитанием, а затем возвращая результаты обратно в уравнения). Это довольно стандартная математика на уровне средней школы.

-44.3940 = 50a + 37b + c (A)
-45.3049 = 43a + 39b + c (B)
-44.9594 = 52a + 41b + c (C)

(A-B): 0.9109 =  7a -  2b (D)
(B-C): 0.3455 = -9a -  2b (E)

(D-E): 1.2564 = 16a (F)

(F/16):  a = 0.078525 (G)

Feed G into D:
       0.9109 = 7a - 2b
    => 0.9109 = 0.549675 - 2b (substitute a)
    => 0.361225 = -2b (subtract 0.549675 from both sides)
    => -0.1806125 = b (divide both sides by -2) (H)

Feed H/G into A:
       -44.3940 = 50a + 37b + c
    => -44.3940 = 3.92625 - 6.6826625 + c (substitute a/b)
    => -41.6375875 = c (subtract 3.92625 - 6.6826625 from both sides)

Итак, вы получите:

a =   0.0785250
b =  -0.1806125
c = -41.6375875

Если вы включите эти значения обратно в A, B и C, вы обнаружите, что они верны.

Хитрость заключается в том, чтобы использовать простую матрицу 4x3, которая, в свою очередь, сводится к матрице 3x2, а затем к 2x1, который равен «a = n», причем n является фактическим числом. Получив это, вы вводите его в следующую матрицу, чтобы получить другое значение, затем эти два значения в следующую матрицу, пока не решите все переменные.

Если у вас есть N различных уравнений, вы всегда можете решить для N переменных. Я говорю по-разному, потому что эти два не являются:

 7a + 2b =  50
14a + 4b = 100

Они представляют собой одно и то же уравнение , умноженное на два, поэтому вы не можете получить решение из них - умножение первого на два, а затем вычитание оставляет вас с истинным, но бесполезным утверждением:

0 = 0 + 0

В качестве примера, приведем код C, который вырабатывает уравнения одновременности, которые вы поставили в своем вопросе. Сначала некоторые необходимые типы, переменные, вспомогательная функция для распечатки уравнения и начало main:

#include <stdio.h>

typedef struct { double r, a, b, c; } tEquation;
tEquation equ1[] = {
    { -44.3940,  50, 37, 1 },      // -44.3940 = 50a + 37b + c (A)
    { -45.3049,  43, 39, 1 },      // -45.3049 = 43a + 39b + c (B)
    { -44.9594,  52, 41, 1 },      // -44.9594 = 52a + 41b + c (C)
};
tEquation equ2[2], equ3[1];

static void dumpEqu (char *desc, tEquation *e, char *post) {
    printf ("%10s: %12.8lf = %12.8lfa + %12.8lfb + %12.8lfc (%s)\n",
        desc, e->r, e->a, e->b, e->c, post);
}

int main (void) {
    double a, b, c;

Затем, приведение трех уравнений с тремя неизвестными к двум уравнениям с двумя неизвестными :

    // First step, populate equ2 based on removing c from equ.

    dumpEqu (">", &(equ1[0]), "A");
    dumpEqu (">", &(equ1[1]), "B");
    dumpEqu (">", &(equ1[2]), "C");
    puts ("");

    // A - B
    equ2[0].r = equ1[0].r * equ1[1].c - equ1[1].r * equ1[0].c;
    equ2[0].a = equ1[0].a * equ1[1].c - equ1[1].a * equ1[0].c;
    equ2[0].b = equ1[0].b * equ1[1].c - equ1[1].b * equ1[0].c;
    equ2[0].c = 0;

    // B - C
    equ2[1].r = equ1[1].r * equ1[2].c - equ1[2].r * equ1[1].c;
    equ2[1].a = equ1[1].a * equ1[2].c - equ1[2].a * equ1[1].c;
    equ2[1].b = equ1[1].b * equ1[2].c - equ1[2].b * equ1[1].c;
    equ2[1].c = 0;

    dumpEqu ("A-B", &(equ2[0]), "D");
    dumpEqu ("B-C", &(equ2[1]), "E");
    puts ("");

Далее, приведение двух уравнений с двумя неизвестными к одному уравнению с одним неизвестным:

    // Next step, populate equ3 based on removing b from equ2.

    // D - E
    equ3[0].r = equ2[0].r * equ2[1].b - equ2[1].r * equ2[0].b;
    equ3[0].a = equ2[0].a * equ2[1].b - equ2[1].a * equ2[0].b;
    equ3[0].b = 0;
    equ3[0].c = 0;

    dumpEqu ("D-E", &(equ3[0]), "F");
    puts ("");

Теперь, когда у нас есть формула типа number1 = unknown * number2, мы можем просто определить неизвестное значение с помощью unknown <- number1 / number2. Затем, как только вы вычислили это значение, подставьте его в одно из уравнений с двумя неизвестными и определите второе значение. Затем подставьте оба этих (теперь известных) неизвестных в одно из исходных уравнений, и теперь у вас есть значения для всех трех неизвестных:

    // Finally, substitute values back into equations.

    a = equ3[0].r / equ3[0].a;
    printf ("From (F    ), a = %12.8lf (G)\n", a);

    b = (equ2[0].r - equ2[0].a * a) / equ2[0].b;
    printf ("From (D,G  ), b = %12.8lf (H)\n", b);

    c = (equ1[0].r - equ1[0].a * a - equ1[0].b * b) / equ1[0].c;
    printf ("From (A,G,H), c = %12.8lf (I)\n", c);

    return 0;
}

Вывод этого кода соответствует более ранним вычислениям в этом ответе:

         >: -44.39400000 =  50.00000000a +  37.00000000b +   1.00000000c (A)
         >: -45.30490000 =  43.00000000a +  39.00000000b +   1.00000000c (B)
         >: -44.95940000 =  52.00000000a +  41.00000000b +   1.00000000c (C)

       A-B:   0.91090000 =   7.00000000a +  -2.00000000b +   0.00000000c (D)
       B-C:  -0.34550000 =  -9.00000000a +  -2.00000000b +   0.00000000c (E)

       D-E:  -2.51280000 = -32.00000000a +   0.00000000b +   0.00000000c (F)

From (F    ), a =   0.07852500 (G)
From (D,G  ), b =  -0.18061250 (H)
From (A,G,H), c = -41.63758750 (I)
15
ответ дан paxdiablo 27 November 2019 в 03:43
поделиться

Взгляните на Microsoft Solver Foundation .

С его помощью вы можете написать такой код:

  SolverContext context = SolverContext.GetContext();
  Model model = context.CreateModel();

  Decision a = new Decision(Domain.Real, "a");
  Decision b = new Decision(Domain.Real, "b");
  Decision c = new Decision(Domain.Real, "c");
  model.AddDecisions(a,b,c);
  model.AddConstraint("eqA", -44.3940 == 50*a + 37*b + c);
  model.AddConstraint("eqB", -45.3049 == 43*a + 39*b + c);
  model.AddConstraint("eqC", -44.9594 == 52*a + 41*b + c);
  Solution solution = context.Solve();
  string results = solution.GetReport().ToString();
  Console.WriteLine(results); 

Вот результат:
=== Отчет службы поддержки Solver ===
Дата и время: 20.04.2009 23:29:55
Название модели: по умолчанию
Запрошенные возможности: LP
Время решения (мс): 1027
Общее время (мс): 1414
Статус завершения решения: оптимальный
Выбранный решатель: Microsoft.SolverFoundation.Solvers.SimplexSolver
Директивы:
Microsoft.SolverFoundation.Services.Directive
Алгоритм: Первичный
Арифметика: Гибрид
Цены (точные): По умолчанию
Цены (двойные) : SteepestEdge
Основа: Slack
Pivot Count: 3
=== Детали решения ===
Цели:

Решения:
a: 0.0785250000000004
b: -0.180612500000001
c: -41.6375875

7
ответ дан Bobby Ortiz 27 November 2019 в 03:43
поделиться

Вы ищете программный пакет, который будет выполнять работу или фактически выполнять матричные операции и тому подобное и выполнять каждый шаг?

Первый, мой коллега, только что использовавший Ocaml GLPK . Это просто оболочка для GLPK , но она устраняет многие этапы настройки. Похоже, что вам придется придерживаться GLPK, в C, хотя. Что касается последнего, то, благодаря восхитительному сохранению старой статьи, я некоторое время назад изучал LP, PDF . Если вам нужна конкретная помощь в настройке, дайте нам знать, и я уверен, что я или кто-то еще вернусь и помогу, но, думаю, отсюда довольно просто. Удачи!

3
ответ дан nlucaroni 27 November 2019 в 03:43
поделиться

Шаблон Числовой Инструментарий от NIST имеет инструменты для того, чтобы сделать это.

Один из более надежных путей состоит в том, чтобы использовать Разложение четверти .

Вот пример обертки так, чтобы я мог назвать "GetInverse (A, InvA)" в моем коде, и это поместит инверсию в InvA.

void GetInverse(const Array2D<double>& A, Array2D<double>& invA)
   {
   QR<double> qr(A);  
   invA = qr.solve(I); 
   }

Array2D определяется в библиотеке.

3
ответ дан Baltimark 27 November 2019 в 03:43
поделиться

Судя по формулировке вашего вопроса, у вас больше уравнений, чем неизвестных, и вы хотите минимизировать несоответствия Обычно это делается с помощью линейной регрессии, которая минимизирует сумму квадратов несоответствий. В зависимости от размера данных вы можете сделать это в электронной таблице или в статистическом пакете. R - это высококачественный бесплатный пакет, который выполняет линейную регрессию и многое другое. Существует много линейной регрессии (и много ошибок), но, как это легко сделать для простых случаев. Вот пример R с использованием ваших данных. Обратите внимание, что «tx» - это перехват вашей модели.

> y <- c(-44.394, -45.3049, -44.9594)
> a <- c(50.0, 43.0, 52.0)
> b <- c(37.0, 39.0, 41.0)
> regression = lm(y ~ a + b)
> regression

Call:
lm(formula = y ~ a + b)

Coefficients:
(Intercept)            a            b  
  -41.63759      0.07852     -0.18061  
2
ответ дан David Nehme 27 November 2019 в 03:43
поделиться

Что касается эффективности во время выполнения, другие ответили лучше, чем я. Если у вас всегда будет то же число уравнений, что и для переменных, мне нравится правило Крамера , поскольку его легко реализовать. Просто напишите функцию для вычисления определителя матрицы (или используйте уже написанную, я уверен, что вы можете найти ее там) и разделите определители двух матриц.

2
ответ дан JZL003 27 November 2019 в 03:43
поделиться

Лично, я неравнодушен к алгоритмам Числовые Рецепты . (Я люблю выпуск C++.)

Эта книга будет учить Вас, почему алгоритмы работают, плюс шоу Вы некоторые вполне прилично отладили реализации тех алгоритмов.

, Конечно, Вы могли просто вслепую использовать CLAPACK (я использовал его с большим успехом), но я был бы тип первой руки алгоритм Исключения Гаусса, чтобы, по крайней мере, иметь слабую идею вида работы, которая вошла в создание этих стабильных алгоритмов.

Позже при выполнении более интересной линейной алгебры, осматривая исходный код Октава ответит на большое количество вопросов.

1
ответ дан Frank Krueger 27 November 2019 в 03:43
поделиться
function x = LinSolve(A,y)
%
% Recursive Solution of Linear System Ax=y
% matlab equivalent: x = A\y 
% x = n x 1
% A = n x n
% y = n x 1
% Uses stack space extensively. Not efficient.
% C allows recursion, so convert it into C. 
% ----------------------------------------------
n=length(y);
x=zeros(n,1);
if(n>1)
    x(1:n-1,1) = LinSolve( A(1:n-1,1:n-1) - (A(1:n-1,n)*A(n,1:n-1))./A(n,n) , ...
                           y(1:n-1,1) - A(1:n-1,n).*(y(n,1)/A(n,n))); 
    x(n,1) = (y(n,1) - A(n,1:n-1)*x(1:n-1,1))./A(n,n); 
else
    x = y(1,1) / A(1,1);
end
1
ответ дан Bulent S. 27 November 2019 в 03:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: