/ / la mejor manera de obtener una respuesta que satisfaga una ecuación lineal en matlab - matlab, linear-schedule, linear-equation

mejor forma de obtener una respuesta que satisfaga una ecuación lineal en matlab - matlab, programación lineal, ecuación lineal

Tengo una ecuación lineal:

vt = v1*x1 + v2*x2 + v3*x3

vt, v1, v2, v3 son escalares con valores entre 0 y 1. ¿Cuál es la mejor manera de generar un conjunto (cualquier conjunto estará bien) de x1, x2 y x3 que satisfacen la ecuación anterior? y también satisfacer

x1>0
x2>0
x3>0

Tengo un par de miles de juegos de vt, v1, v2 y v3, por lo tanto, necesito poder generar x1, x2 y x3 mediante programación.

Respuestas

3 para la respuesta № 1

Hay dos maneras en que puedes enfocar esto:

  1. Del método que has ideado en tu post. Generar aleatoriamente x1 y x2 y asegurar que vt < v1*x1 + v2*x2, luego seguir adelante y resolver para x3.
  2. Formular esto en programa lineal. Un programa lineal es básicamente resolver un sistema de ecuaciones que están sujetos a restricciones de desigualdad o igualdad. En otras palabras:

paja

Como tal, podemos traducir su problema para ser de unaProblema de programación lineal. La declaración "maximizar" es lo que se conoce como la función objetivo, el objetivo general de lo que está tratando de lograr. En problemas de programación lineal, estamos tratando de minimizar o maximizar este objetivo. Para ello, debemos satisfacer las desigualdades observadas en el sujeto a condición. Por lo general, este programa está representado en forma canónicaY así, las restricciones en cada variable deberían ser positivas.

La condición de maximizar puede ser arbitraria ya que no te importa el objetivo. Solo te preocupas por cualquier solución. Todo este paradigma puede lograrse mediante linprog en MATLAB. Con lo que deberías tener cuidado es cómo linprog está especificado. De hecho, el objetivo es minimizado en lugar de maximizado Sin embargo, las condiciones son las mismas con la excepción de garantizar que todas las variables sean positivas. Tendremos que codificar eso en nosotros mismos.

En términos del objetivo arbitrario, simplemente podemos hacer x1 + x2 + x3. Como tal, c = [1 1 1]. Nuestra restricción de igualdad es: v1*x1 + v2*x2 + v3*x3 = vt. También debemos asegurarnos de que x es positivo. Para codificar esto, lo que podemos hacer es elegir una pequeña constante para que todos los valores de x son mayores que este valor. Ahora mismo, linprog no admite desigualdades estrictas (es decir, x > 0) y por eso tenemos que sortear esto haciendo este truco. Además, para garantizar que los valores sean positivos, linprog asume que el Ax <= b. Por lo tanto, un truco común que se utiliza es negar la desigualdad de x >= 0, y así esto es equivalente a -x <= 0. Para asegurarnos de que los valores no sean cero, en realidad haríamos: -x <= -eps, dónde eps Es una pequeña constante. Sin embargo, cuando estaba haciendo experimentos, al hacerlo de esta manera, dos de las variables terminan siendo la misma solución. Como tal, lo que recomendaría que hiciéramos es generar buenas soluciones que sean aleatorias cada vez, dibujemos b ser de una distribución aleatoria uniforme como dijiste. Esto nos dará un punto de partida cada vez que queramos resolver este problema.

Por lo tanto, nuestras desigualdades son:

 -x1 <= -rand1
-x2 <= -rand2
-x3 <= -rand3

rand1, rand2, rand3 Hay tres números generados al azar que están entre 0 y 1. En forma matricial, esto es:

 [-1 0 0][x1]      [-rand1]
[0 -1 0][x2]  <=  [-rand2]
[0 0 -1][x3]      [-rand3]

Finalmente, nuestra restricción de igualdad desde antes es:

[v1 v2 v3][x1]     [vt]
[x2]  =
[x3]

Ahora, para usar linprog, harías esto:

X = linprog(c, A, b, Aeq, beq);

c Es una matriz de coeficientes que se define para el objetivo. En este caso, se definiría como [1 1 1], A y b es la matriz y el vector de columna definidos para las restricciones de desigualdad y Aeq y beq es la matriz y el vector de columna definidos para las restricciones de igualdad. X Así nos daría la solución después de linprog converge (es decir, x1, x2, x3). Como tal, harías esto:

A = -eye(3,3);
b = -rand(3,1);
Aeq = [v1 v2 v3];
beq = vt;
c = [1 1 1];
X = linprog(c, A, b, Aeq, beq);

Como ejemplo, supongamos v1 = 0.33, v2 = 0.5, v3 = 0.2y vt = 2.5. Por lo tanto:

rng(123); %// Set seed for reproducibility
v1 = 0.33; v2 = 0.5; v3 = 0.2;
vt = 2.5;
A = -eye(3,3);
b = -rand(3,1);
Aeq = [v1 v2 v3];
beq = vt;
c = [1 1 1];
X = linprog(c, A, b, Aeq, beq);

Yo obtengo:

X =

0.6964
4.4495
0.2268

Para verificar que esto es igual a vt, haríamos:

s = Aeq*X

s = 2.5000

Lo anterior simplemente hace v1*x1 + v2*x2 + v3*x3. Esto se calcula en forma de producto de puntos para facilitar las cosas como X es un vector de columna y v1, v2, v3 ya están establecidos en Aeq y es un vector de fila.


Como tal, de cualquier manera es buena, pero al menos con linprog, ¡no tienes que seguir repitiendo hasta que obtengas esa condición para estar satisfecho!

Una pequeña advertencia que olvidé mencionar en el enfoque anterior es que debe asegurarse de que vt >= v1*rand1 + v2*rand2 + v3*rand3 para garantizar la convergencia. Ya que dijiste eso v1,v2,v3 están limitados entre 0 y 1, el peor de los casos es cuando v1,v2,v3 todos son iguales a 1. Como tal, realmente necesitamos asegurarnos de que vt > rand1 + rand2 + rand3. Si esto es no el caso, entonces simplemente tomar cada valor de rand1, rand2, rand3y dividir por (rand1 + rand2 + rand3) / vt. Como tal, esto asegurará que la suma total sea igual a vt suponiendo que todas las ponderaciones son 1, y esto permitirá que el programa lineal converja correctamente.

Si no lo hace, entonces la solución no convergerá debido a las condiciones de desigualdad puestas en b, y no obtendrás la respuesta correcta. ¡Solo un poco de reflexión! Como tal, haz esto por b antes de correr linprog

if sum(-b) > vt
b = b ./ (sum(-b) / vt);
end

¡Buena suerte!