Linear.c: Il codice...
/*
* file: linear.c
* --------------
* risoluzione di problemi di programmazione lineare.
*
* *** METODO DELLE DUE FASI. ***
*
* release 0.1.2000
*
* (C) 2000 - Alfonso PRISCO & Michele VOLPE
*
* e-mail: alf.mil@tiscalinet.it - micvolpe@tiscalinet.it
* home-page: http://web.tiscalinet.it/APSoft
*/
#include <stdio.h>
#include <malloc.h>
/* definizioni */
typedef double elemento_t; /* elementi delle matrici */
#define SCAN "%lf" /* codice di conversione per scanf (double) */
#define PRINT "%.2f | " /* codice di conversione per printf (double) */
/* variabili e matrici globali */
static int num_base = 0; /* numero della base considerata */
static int vincoli, variabili; /* dimensioni del problema */
static elemento_t **A; /* matrice vincoli */
static elemento_t **Ab_inv; /* matrice inversa */
static elemento_t **C; /* vettore costi unitari C */
static elemento_t **C1; /* vettore costi unitari per il problema espanso */
static elemento_t **Cb; /* partizione dei costi unitari */
static elemento_t **b; /* vettore termini noti b */
static elemento_t **Z0; /* valore funzione obbietivo: E'IL RISULTATO DI PRODOTTO DI MATRICI */
static elemento_t **Yk; /* valutazione variabile uscente */
static elemento_t *X; /* vettore soluzioni */
static int *B; /* vettore indici delle variabili in base */
static int *N; /* vettore indici delle variabili fuori base */
static elemento_t *ZjCj; /* valutazione variabile entrante */
/* funzioni */
/*
* funzione: aiuto
* ---------------
* questa funzione stampa a video le generalitā del programma
* e le linee guida da seguire per la risoluzione di un problema.
* USO: aiuto ();
*/
void aiuto (void) {
printf("\nRISOLUZIONE DI PROBLEMI DI POGRAMMAZIONE LINEARE:\n");
printf(" *** Metodo delle due fasi ***\n");
printf(" Release 0.1_2000\n");
printf("\n\nInserisci i dati del problema ridotto alla seguente forma:\n");
printf("\n\t===================\n");
printf("\n\tZmin = Cx\n");
printf("\n\tAx >= o <= b\n");
printf("\n\tb >= 0;\n");
printf("\t===================\n");
printf("\nTieni presente che le matrici sono sempre indicizzate come:\n");
printf("\n\tmatrice[riga][colonna]\n");
printf("\nQuindi i dati vanno inseriti per riga:\n");
printf("\n\telemento (1,2) č l'elemento sulla riga 1 colonna 2...\n");
printf("\nATTENZIONE: un valore (-1) nel vettore b/Yk, indica che il rapporto\n");
printf(" in quella posizione, non č ammissibile!!!\n");
printf("\n\n\n\t\t*** I N I Z I A M O P U R E... ***\n");
}
/*
* funzione: dammi_matrice
* -----------------------
* questa funzione prende in input le dimensioni della matrice
* e restituisce il puntatore alla zona di memoria allocata.
* USO: p = dammi_matrice (m, n); dove p č un puntatore a elemento_t
* ed m e n le dimensioni (righe, colonne).
*/
elemento_t **dammi_matrice (int m, int n) {
int i;
elemento_t **p;
p = malloc (m * sizeof(elemento_t *));
p -= 1; /* sposto a sx il puntatore per avere gli indici che partono da 1 */
if (p == NULL) {
printf ("Memoria insufficiente per la matrice.\n");
}
else {
for (i = 1; i <= m; i++) {
p[i] = malloc (n * sizeof(elemento_t));
p[i] -= 1; /* sposto a sx il puntatore */
if (p[i] == NULL) {
printf ("Memoria insufficiente per la matrice.\n");
}
}
}
return (p);
}
/*
* funzione: cancella_matrice
* --------------------------
* questa funzione elimina una matrice precedentemente allocata liberando la memoria.
* USO: cancella_matrice (matrice, int m); dove matrice č il puntatore alla matrice ed
* m sono le righe della matrice da eliminare.
*/
void cancella_matrice (elemento_t **matrice, int m) {
int i;
if (matrice == NULL) return;
for (i = 1; i <= m; ++i) {
free (matrice[i] + 1);
}
free (matrice + 1);
}
/*
* funzione: inserisci_elementi
* ----------------------------
* questa funzione, inserisce gli elementi nella matrice passata per argomento.
* USO: inserisci_elementi (p, m, n); dove p = puntatore alla matrice
* m ed n sono le dimensioni (righe, colonne).
*/
void inserisci_elementi (elemento_t **p, int m, int n) {
int i, j;
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
printf ("\t(%d,%d) = ", i, j);
scanf (SCAN, &p[i][j]);
}
}
}
/*
* funzione: vincolo
* -----------------
* questa funzione stabilisce il tipo di vincolo attraverso l'input dell'utente,
* e restituisce: 0 per maggiore o uguale; 1 per minore o uguale.
* USO: controllo = vincolo ().
*/
int vincolo (void) {
char tipo[3];
static int conta;
getchar(); /* non considero la pressione di INVIO */
printf("\tVincolo n. %d (>= o <=):", ++conta);
fgets (tipo, 3, stdin);
while ((tipo[0] != '>' && tipo[1] != '=') || (tipo[0] != '<' && tipo[1] != '=')) {
printf("\t\tTipo vincolo non riconosciuto!!!\n");
printf("\t\tVincoli ammessi: >= o <=...\n");
printf("\tVincolo n. %d (>= o <=):",conta);
fgets (tipo, 3, stdin);
}
return (tipo[0] == '>' && tipo[1] == '=') ? 0 : 1;
}
/*
* funzione: moltiplica_matrici
* ----------------------------
* questa funzione moltiplica due matrici e restituisce la matrice
* risultante.
* USO: moltiplica_matrici (mx, nx, prima, m, n, seconda, m1, n1);
* dove: prima e seconda sono (elemento_t **), m?, n? le dimensioni,
* la funzione restituisce il puntatore alla matrice prodotto e le sue
* dimensioni in mx ed nx.
*/
elemento_t **moltiplica_matrici (int *mx, int *nx, elemento_t **prima,
int m, int n, elemento_t **seconda, int m1, int n1) {
elemento_t **risultato;
int mr, nr; /* dimensioni matrice risultante */
int i, j, k; /* contatori per le tre matrici */
/* verifica conformabilitā */
if (n != m1) printf ("matrici non conformabili!\n");
if (n == m1) {
mr = m;
nr = n1;
risultato = dammi_matrice (mr, nr); /* alloco matrice prodotto */
for (i = 1; i <= mr; i++) {
for (j = 1; j <= nr; j++) {
risultato[i][j] = 0;
for (k = 1; k <= n; k++) {
risultato[i][j] += (prima[i][k] * seconda[k][j]);
}
}
}
if (mx != NULL) *mx = mr;
if (nx != NULL) *nx = nr;
return (risultato);
}
}
/*
* funzione: estrai_colonne
* ------------------------
* questa funzione estrae (n_col indicate in colonne da passare come argomento) dalla matrice
* di partenza (matrice) e restituisce il puntatore alla nuova matrice.
* USO: m_estratta = estrai_colonne (matrice, m, n, n_col, colonne[])
*/
elemento_t **estrai_colonne (elemento_t **matrice, int m, int n, int n_col, int *colonne) {
elemento_t **matrice_estratta;
int i, j;
matrice_estratta = dammi_matrice (m, n_col);
for (i = 1; i <= n_col; i++) {
for (j = 1; j <= m; j++) {
matrice_estratta[j][i] = matrice[j][colonne[i]];
}
}
return (matrice_estratta);
}
/*
* funzione: togli_riga_colonna
* ----------------------------
* questa funzione toglie dalla matrice quadrata d'ingresso una riga ed una colonna passate come
* parametro e restituisce il puntatore alla matrice risultante.
* USO: togli_riga_colonna (matrice, n, riga, colonna).
*/
elemento_t **togli_riga_colonna (elemento_t **matrice, int n, int riga, int colonna) {
int i, j; /* contatori per matrice d'ingresso */
int k = 1, y = 1; /* contatori per matrice d'uscita */
elemento_t **risultato; /* matrice d'uscita */
risultato = dammi_matrice (n-1, n-1);
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
if (i != riga && j != colonna) {
risultato[k][y] = matrice[i][j];
y++;
if (y > n-1) {
y = 1; k++;
}
}
}
}
return (risultato);
}
/*
* funzione: eleva
* ---------------
* questa funzione esegue l'elevamento a potenza di un numero intero.
* USO: y = eleva (x, y).
*/
int eleva (int x, int y) {
int i, ris = 1;
for (i = 1; i <= y; i++) {
ris *= x;
}
return (ris);
}
/*
* funzione: determinante
* ----------------------
* questa funzione calcola e restituisce il determinante della matrice in input.
* USO: det = determinante (matrice, n); dove det č una variabile intera, matrice
* il puntatore alla matrice ed n la dimensione della matrice quadrata.
* ATTENZIONE: č una funzione ricorsiva!!!
*/
elemento_t determinante (elemento_t **matrice, int n) {
int i, j = 1;
elemento_t risultato = 0; /* risultato del calcolo */
elemento_t **minore;
/* condizioni di uscita */
if (n == 1)
return (matrice[1][1]);
if (n == 2) {
return ((matrice[1][1] * matrice[2][2]) - (matrice[1][2] * matrice[2][1]));
}
/* sezione ricorsiva */
for (i = 1; i <= n; i++) {
minore = togli_riga_colonna (matrice, n, i, j);
risultato += eleva (-1, i+j) * matrice[i][j] * determinante (minore, n-1);
}
cancella_matrice (minore, n-1);
return (risultato);
}
/*
* funzione: trasposta
* -------------------
* questa funzione calcola e restituisce la matrice trasposta di quella in input.
* USO: trasp = trasposta (matrice, n).
*/
elemento_t **trasposta (elemento_t **matrice, int n) {
int i, j;
elemento_t **risultato;
risultato = dammi_matrice (n, n);
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
risultato[j][i] = matrice[i][j];
}
}
return (risultato);
}
/*
* funzione: inversa
* -----------------
* questa funzione, calcola l'inversa della matrice in input, verificando prima se questa
* esiste, se non esiste, la funzione restituisce NULL.
* USO: inv = inversa (matrice, n).
*/
elemento_t **inversa (elemento_t **matrice, int n) {
elemento_t det;
int i, j;
elemento_t **risultato, **trasp, **minore;
det = determinante (matrice, n); /* determinante della matrice d'ingresso */
if (det == 0) return (NULL);
risultato = dammi_matrice (n, n); /* alloco matrice inversa d'uscita */
trasp = trasposta (matrice, n); /* trasposta della matrice d'ingresso */
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
minore = togli_riga_colonna (trasp, n, i, j);
risultato[i][j] = determinante (minore, n - 1) / det;
if (risultato[i][j] != 0) risultato[i][j] *= eleva (-1, i+j); /* segno - per posiz. dispari */
cancella_matrice (minore, n-1);
}
}
cancella_matrice (trasp, n);
return (risultato);
}
/*
* funzione: allinea_elemento
* --------------------------
* questa funzione allinea a destra gli elementi della matrice.
* USO: allinea_elemento (valore); dove valore č il valore dell'elemento.
*/
void allinea_elemento (elemento_t valore) {
char *spazio = " ";
if (valore < 0) {
spazio++;
valore *= -1;
}
if (valore >= 0 && valore < 10) printf ("%s", spazio);
if (valore >= 10 && valore < 100) printf ("%s", spazio + 1);
if (valore >= 100 && valore < 1000) printf ("%s", spazio + 2);
}
/*
* funzione: stampa_matrice
* ------------------------
* questa funzione stampa la matrice passata come parametro.
* USO: stampa_matrice (p, m, n); dove p = puntatore alla matrice
* m ed n sono le dimensioni (righe, colonne).
*/
void stampa_matrice (elemento_t **p, int m, int n) {
int i, j, k;
/* interlinea */
printf ("\n");
printf ("|");
for (k = 1; k <= n; k++) {
printf (k < 10 ? "----%d----|" : "----%d---|" ,k);
}
printf ("\n");
/* stampa dati */
for (i = 1; i <= m; i++) {
printf ("%d ", i);
for (j = 1; j <= n; j++) {
allinea_elemento (p[i][j]); /* inserisco gli spazi per l'allineamento */
printf (PRINT, p[i][j]); /* stampo l'elemento in causa */
}
/* interlinea */
printf ("\n");
printf ("|");
for (k = 1; k <= n; k++) {
printf ("---------|");
}
printf ("\n");
}
}
/*
* funzione: stampa_base
* ---------------------
* questa funzione stampa la soluzione contenuta in B.
* USO: stampa_base ().
*/
void stampa_base (void) {
int i;
printf ("\n----------- BASE ATTUALE: -----------\n");
printf("\nB%d = {", ++num_base);
for (i = 1; i <= vincoli; i++) { /* B={...} */
printf(i > 1 ? ", %d" : "%d", B[i]);
}
printf("}; ");
printf("N%d = {", num_base);
for (i = 1; i <= (esamina_B () ? variabili+vincoli : variabili); i++) { /* N={...} */
printf(i > 1 ? ", %d" : "%d", N[i]);
}
printf("};\n");
printf("\nCon XB%d:\n\n", num_base);
for (i = 1; i <= vincoli; i++) {
printf("x%d = %.2f\n", B[i], X[B[i]]);
}
printf("\nE con N%d = 0..\n", num_base);
}
/*
* funzione: calcola_Z0
* --------------------
* questa funzione calcola per la base considerata il valore di Z0.
* USO: calcola_Z0 ().
*/
void calcola_Z0 () {
int zm, zn; /* dimensioni fittizie di Z0 */
elemento_t **Z_temp; /* puntatore temporaneo per la cancellazione */
Z0 = moltiplica_matrici (&zm, &zn, Cb, 1, vincoli, Ab_inv, vincoli, vincoli);
Z_temp = Z0; /* per liberare la memoria */
Z0 = moltiplica_matrici (NULL, NULL, Z0, zm, zn, b, vincoli, 1);
cancella_matrice (Z_temp, zm);
}
/*
* funzione: calcola_Zj
* -----------------------
* questa funzione calcola per la base considerata il valore di Zj per j appartenente ad N
* USO: elemento_t = calcola_Zj (j); dove j č l'indice in N considerato al momento del calcolo.
*/
elemento_t calcola_Zj (int j) {
elemento_t **Zj, **aj, **Z_temp;
int zm, zn; /* dimensioni fittizie di Zj */
int *n_col;
/* n_col per passare j a estrai_colonne */
n_col = malloc (1 * sizeof (int)); n_col -= 1;
n_col[1] = j;
aj = estrai_colonne (A, vincoli, (variabili+vincoli+vincoli), 1, n_col);
Zj = moltiplica_matrici (&zm, &zn, Cb, 1, vincoli, Ab_inv, vincoli, vincoli);
Z_temp = Zj; /* per liberare la memoria */
Zj = moltiplica_matrici (NULL, NULL, Zj, zm, zn, aj, vincoli, 1);
cancella_matrice (Z_temp, zm);
cancella_matrice (aj, vincoli);
return (Zj[1][1]);
}
/*
* funzione: calcola_ZjCj
* -----------------------
* questa funzione calcola per la base considerata i valori di Zj-Cj e li inserisce nel
* vettore ZjCj.
* USO: calcola_ZjCj (vettore_costi, dim_N), dove vettore č il vettore dei costi e dim_N
* č il num di vbl fuori base.
*/
void calcola_ZjCj (elemento_t ** vettore_costi, int dim_N) {
int i;
for (i = 1; i <= dim_N; i++) {
ZjCj[i] = ((calcola_Zj (N[i])) - vettore_costi[1][N[i]]);
}
}
/*
* funzione: esamina_ZjCj
* ----------------------
* questa funzione esamina il vettore ZjCj e restituisce 0 se la soluzione considerata č ottima
* ma c'č combinazione lineare, -1 se č ottima assoluta, altrimenti l'indice della vbl
* che deve entrare in base (da N a B).
* USO: test = esamina_ZjCj (elemento_t *vettore, int dim).
*/
int esamina_ZjCj (elemento_t *vettore, int dimensione) {
int i, indice;
elemento_t max = -1;
for (i = 1; i <= dimensione; i++) {
if ((vettore[i] >= 0) && (vettore[i] > max)) {
max = vettore[i];
indice = i;
}
}
if (max <= 0)
return (max); /* se tutti gli elementi sono <= 0, la soluzione č ottima */
if (max > 0)
return (indice); /* se almeno uno č > 0 mi restituisce l'indice */
}
/*
* funzione: esamina_B
* -------------------
* questa funzione verifica se nella soluzione attuale ci sono variabili artificiali
* e restituisce 1 altrimenti 0.
* USO: verifica = esamina_B ();
*/
int esamina_B () {
int i, j;
for (i = 1; i <= vincoli; i++) {
for (j = 1; j <= vincoli; j++) {
if (B[i] == variabili+vincoli+j)
return (1);
}
}
return (0);
}
/*
* funzione: calcola_Yk
* --------------------
* questa funzione calcola i valori per il vettore Yx, e restituisce la posizione del minimo
* di questi non negativo e con denominatore non zero, altrimenti -1 se non ci sono rapporti
* ammissibili.
* USO: valore = calcola_yk (int max_ZjCj); dove max_ZjCj č l'indice della vbl entrante.
*/
int calcola_Yk (int max_ZjCj) {
int i, j = 1;
int posizione = -1;
elemento_t rapporto_min = 0;
elemento_t **aj; /* colonna Jesima da considerare */
elemento_t **Yk_temp; /* conservo i valori per l'eventuale regola di BLANT */
elemento_t **b_segnato; /* vettore b_segnato per il calcolo dei rapporti */
int *n_col;
int n_rapp_min = 0; /* numero dei rapporti minimi uguali per regola di BLANT */
int indice_j = 0; /* colonna Jesima della matrice A */
n_col = malloc (1 * sizeof (int)); n_col -= 1;
n_col[1] = max_ZjCj;
aj = estrai_colonne (A, vincoli, (variabili+vincoli+vincoli), 1, n_col);
Yk = moltiplica_matrici (NULL, NULL, Ab_inv, vincoli, vincoli, aj, vincoli, 1);
n_col[1] = 1;
Yk_temp = estrai_colonne (Yk, vincoli, 1, 1, n_col);
/* inizializzo b_segnato con i valori X */
b_segnato = dammi_matrice (vincoli, 1);
for (i = 1; i <= vincoli; i++) {
b_segnato[i][j] = X[B[i]];
}
while(1) {
/* calcola rapporti ammissibili */
for (i = 1; i <= vincoli; i++) {
if ((Yk_temp[i][j] > 0) && (b_segnato[i][j] >= 0) ) {
Yk[i][j] = b_segnato[i][j] / Yk_temp[i][j];
rapporto_min = Yk[i][j];
posizione = i;
}
else
Yk[i][j] = -1;
}
/* esamina valori per trovare il minimo */
for (i = 1; i <= vincoli; i++) {
if ((Yk[i][j] >= 0) && (Yk[i][j] <= rapporto_min)) {
rapporto_min = Yk[i][j];
posizione = i;
}
}
if (posizione == -1) {
break;
} else { /* controllo se il rapporto minimo č l'unico */
n_rapp_min++;
for (i = 1; i <= vincoli; i++) {
if (i == posizione) continue;
if (Yk[i][j] == rapporto_min) n_rapp_min++;
}
}
if (n_rapp_min < 2) { /* se il rapporto minimo č unico esco */
break;
} else { /* altrimenti sostituisco b_segnato con la prima delle colonne J e cosi via */
n_col[1] = N[++indice_j];
cancella_matrice (b_segnato, vincoli); /* libero la memoria */
b_segnato = estrai_colonne (A, vincoli, (variabili+vincoli+vincoli), 1, n_col);
n_rapp_min = 0;
rapporto_min = 0;
posizione = -1;
}
}
cancella_matrice (Yk_temp, vincoli);
cancella_matrice (b_segnato, vincoli);
cancella_matrice (aj, vincoli);
return (posizione);
}
/*
* funzione: scrivi_soluzioni
* --------------------------
* questa funzione calcola i valori delle vbl in base e le scrive nel vettore X.
* USO: scrivi_soluzioni ().
*/
void scrivi_soluzioni (void) {
int i;
elemento_t **soluzioni;
/* calcolo matrice inversa per la base considerata anche se per B1 č l'identica */
cancella_matrice (Ab_inv, vincoli); /* libero la memoria */
Ab_inv = inversa ((estrai_colonne(A, vincoli, (variabili+vincoli+vincoli), vincoli, B)), vincoli);
soluzioni = moltiplica_matrici (NULL, NULL, Ab_inv, vincoli, vincoli, b, vincoli, 1);
for (i = 1; i <= variabili+vincoli; i++) {
X[N[i]] = 0;
}
for (i = 1; i <= vincoli; i++) {
X[B[i]] = soluzioni[i][1];
}
}
/*
* funzione: aggiusta_N
* --------------------
* questa funzione riordina il vettore N quando tutte le vbl artificiali sono uscite
* dalla base.
* USO: aggiusta_N ();
*/
void aggiusta_N (void) {
int i, j, swap;
for (i = 1; i < variabili+vincoli; i++) {
if (N[i] <= variabili+vincoli) continue;
for (j = i+1; j <= variabili+vincoli; j++) {
if ((N[j] <= variabili+vincoli) && N[i] > variabili+vincoli) {
swap = N[i];
N[i] = N[j] ;
N[j] = swap;
}
}
}
}
/*
* funzione: inizializza
* ---------------------
* questa funzione, inizializza tutti i dati del problema, attraverso l'input dell'utente.
* USO: inizializza ().
*
* ATTENZIONE: CON LA PRIMA BASE, LE COLONNE SONO n+m; ma quando le vbl artificiali sono uscite
* va considerato n e quindi per gli indici in base (m)per quelli fuori base n-m.
*/
void inizializza (void) {
int i, j;
int tipo_vincolo;
/* input principale per dimensioni del problema */
printf("\nDimensioni del problema:\n\n");
printf("\tvincoli = ");
scanf("%d", &vincoli);
printf("\tvariabili = ");
scanf("%d", &variabili);
/* ------- VETTORE COSTI C ------- */
printf("\nCosti unitari \"C\":\n\n");
C = dammi_matrice (1, variabili+vincoli);
C1 = dammi_matrice (1, variabili+vincoli+vincoli); /* vettore ausiliario */
/* inserisco i valori per il vettore ausiliario C1 */
for (i = 1; i <= variabili+vincoli+vincoli; i++) {
C1[1][i] = 0;
if (i > variabili+vincoli) C1[1][i] = 1;
}
/* dati dell'utente per il vettore C */
inserisci_elementi (C, 1, variabili);
/* completo il vettore C per il simplesso */
for (i = 1; i <= vincoli; i++) {
C[1][variabili+i] = 0;
}
printf("\nQuesti sono i costi unitari per il SIMPLESSO:\n");
stampa_matrice (C, 1, variabili+vincoli);
/* stampa vettore ausiliario C1 per le due fasi */
printf("\nQuesti sono i costi unitari per le DUE FASI:\n");
stampa_matrice (C1, 1, variabili+vincoli+vincoli);
/* ------- VETTORE b ------- */
printf("\nTermini noti \"b\":\n\n");
b = dammi_matrice (vincoli, 1);
/* dati dell'utente */
inserisci_elementi (b, vincoli, 1);
printf("\nQuesti sono i termini noti \"b\":\n");
stampa_matrice (b, vincoli, 1);
/* ------- MATRICE DEI VINCOLI A ------- */
A = dammi_matrice (vincoli, variabili+vincoli+vincoli);
/* inserisco i valori per le m variabili artificiali delle due fasi */
for (i = 1; i <= vincoli; i++) {
for (j = 1; j <= vincoli; j++) {
A[i][variabili+vincoli+j] = 0;
if ( i == j) A[i][variabili+vincoli+j] = 1;
}
}
/* determino il tipo di vincolo per ogni riga ed associo le vbl ausiliarie del simplesso */
printf("\nInserisci tipologia vincoli (>= o <=):\n\n");
for (i = 1; i <= vincoli; i++) {
tipo_vincolo = vincolo ();
for (j = 1; j <= vincoli; j++) {
A[i][variabili+j] = 0;
if (j == i) A[i][variabili+j] = (tipo_vincolo == 1) ? 1 : -1;
}
}
/* dati dell'utente */
printf("\nMatrice dei vincoli \"A\":\n\n");
inserisci_elementi (A, vincoli, variabili);
printf("\nQuesta č la matrice dei vincoli per il SIMPLESSO:\n");
stampa_matrice (A, vincoli, variabili+vincoli);
printf("\nQuesta č la matrice dei vincoli per le DUE FASI:.\n");
stampa_matrice (A, vincoli, variabili+vincoli+vincoli);
/* ------- ALTRE VARIABILI ------- */
/* inizializzazione vettori degli indici in base e fuori base */
B = malloc (vincoli * sizeof (int)); B -= 1; /* sposto a sx il puntatore */
N = malloc ((variabili+vincoli) * sizeof (int)); N -= 1; /* sposto a sx il puntatore */
/* alloco spazio per Zj-Cj */
ZjCj = malloc ((variabili+vincoli) * sizeof (elemento_t)); ZjCj -= 1;
/* indici prima base */
for (i = 1; i <= vincoli; i++) {
B[i] = variabili+vincoli+i;
}
/* indici prima fuori base */
for (i = 1; i <= variabili+vincoli; i++) {
N[i] = i;
}
/* inizializzo vettore soluzioni */
X = malloc ((variabili+vincoli+vincoli) * sizeof (elemento_t)); X -= 1; /* sposto il punt. a sx */
scrivi_soluzioni ();
}
int main (void) {
int i, j; /* contatori */
int ZjCj_test; /* test su Zj-Cj (indice variabile entrante) */
int Yk_test; /* test su Yk (indice variabile uscente) */
int swap_base; /* variabile per swap base */
aiuto (); /* mando le istruzioni a video */
inizializza (); /* inizializzo i dati globali */
while (1) {
(num_base != 0) && printf("\n-------------------------------------\n");
(num_base != 0) && printf("\nPremi [I N V I O] per continuare.....\n");
getchar();
/* base attuale */
stampa_base ();
/* Test di ottimalitā */
printf("\nTestiamo l'ottimalitā della base XB%d:\n\n", num_base);
if (esamina_B ()) { /* vbl artificiali in base */
cancella_matrice (Cb, 1); /* libero la memoria */
Cb = estrai_colonne (C1, 1, variabili+vincoli+vincoli, vincoli, B);
calcola_Z0 (Cb);
printf("p0 = %.2f\n", Z0[1][1]);
/* calcola e stampa Zj-Cj */
calcola_ZjCj (C1, variabili+vincoli);
printf("\nMAX Zj-Cj (per 1 <= j <= N) = ");
for (i = 1; i <= variabili+vincoli; i++) {
printf(i > 1 ? ", %.2f" : "{%.2f", ZjCj[i]);
}
printf("}\n");
/* test */
ZjCj_test = esamina_ZjCj (ZjCj, variabili+vincoli);
if ((ZjCj_test == -1) || (ZjCj_test == 0)) {
printf("\t*** IL PROBLEMA INIZIALE NON HA SOLUZIONI!!! ***\n");
printf("\t*** OPPURE LA MATRICE NON E' A RANGO MASSIMO (Xart= 0) ***\n");
printf("\t*** CONTROLLA I VALORI DELLE VBL ARTIFICIALI IN BASE ***\n");
break;
}else { /* cambio la base */
swap_base = N[ZjCj_test];
Yk_test = calcola_Yk (swap_base);
if(Yk_test < 0) {
printf("\n\t*** NON HO VARIABILI USCENTI... ***\n");
printf("\n\t*** IL PROBLEMA INIZIALE NON HA SOLUZIONI!!! ***\n");
break;
}
/* stampa Yk */
printf("\nMIN+ b/Yk ................. = ");
for (i = 1; i <= vincoli; i++) {
printf(i > 1 ? ", %.2f" : "{%.2f", Yk[i][1]);
}
printf("}\n");
N[ZjCj_test] = B[Yk_test];
B[Yk_test] = swap_base;
scrivi_soluzioni ();
printf("\nEntra.: X%d; Esce.: X%d\n", swap_base, N[ZjCj_test]);
if (!esamina_B ()) {
aggiusta_N ();
printf("\n\t*** TUTTE LE VBL ARTIFICIALI SONO USCITE DALLA BASE ***\n");
printf("\t*** INIZIAMO LA SOLUZIONE DEL PROBLEMA ORIGINARIO.. ***\n");
}
}
}
else { /* vbl artificiali tutte fuori base */
cancella_matrice (Cb, 1); /* libero la memoria */
Cb = estrai_colonne (C, 1, variabili+vincoli, vincoli, B);
calcola_Z0 (Cb);
printf("Z0 = %.2f\n", Z0[1][1]);
/* calcola e stampa Zj-Cj */
calcola_ZjCj (C, variabili);
printf("\nMAX Zj-Cj (per 1 <= j <= N) = ");
for (i = 1; i <= variabili; i++) {
printf(i > 1 ? ", %.2f" : "{%.2f", ZjCj[i]);
}
printf("}\n");
/* test */
ZjCj_test = esamina_ZjCj (ZjCj, variabili);
if (ZjCj_test == 0) {
printf("\n\t*** SOLUZIONE OTTIMA CON POSSIBILE COMBINAZIONE LINEARE!!! ***\n");
break;
}
else if (ZjCj_test == -1) {
printf("\n\t*** SOLUZIONE OTTIMA ASSOLUTA!!! ***\n");
break;
}
else { /* cambio la base */
swap_base = N[ZjCj_test];
Yk_test = calcola_Yk (swap_base);
if(Yk_test < 0) {
printf("\n\t*** L'OTTIMO DEL PROBLEMA CRESCE ALL'INFINITO!!! ***\n");
break;
}
/* stampa Yk */
printf("\nMIN+ b/Yk ................. = ");
for (i = 1; i <= vincoli; i++) {
printf(i > 1 ? ", %.2f" : "{%.2f", Yk[i][1]);
}
printf("}\n");
N[ZjCj_test] = B[Yk_test];
B[Yk_test] = swap_base;
scrivi_soluzioni ();
printf("\nEntra.: X%d; Esce.: X%d\n", swap_base, N[ZjCj_test]);
}
}
}
}
Powered by Alfonso PRISCO