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