#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char reseni_t;
/** Struktura predstavujici jednu klausuli */
struct klausule_s {
unsigned short promennych;
signed short promenne[];
};
/** Struktura predstavujici reseny problem - jednu instanci logicke formule a vahy*/
struct problem_s {
unsigned short promennych;
unsigned short klausuli;
unsigned short klausuli_nacteno;
unsigned short prvni_reseni;
unsigned short *vaha;
struct klausule_s *klausule[];
};
/** Konstruktor
* @param promennych - pocet literalu (literaly jsou reprezentovany cisly 1,2,..pocet literalu)
* @param klausuli - pocet klausuli
* @param prvni_reseni - pokud je nenulovy, vrati se prvni nalezene reseni
* */
struct problem_s *problem_new(int promennych, int klausuli, int prvni_reseni)
{
struct problem_s *problem = (struct problem_s *)malloc(sizeof(struct problem_s) +
klausuli * sizeof(struct klausule_s*));
if( problem != NULL ){
problem->vaha = (unsigned short *)malloc(sizeof(short) * (promennych + 1));
if( problem->vaha == NULL ){
free(problem);
return NULL;
}
problem->promennych = promennych;
problem->klausuli = klausuli;
problem->klausuli_nacteno = 0;
problem->prvni_reseni = prvni_reseni ? 1 : 0;
while( promennych-- )
problem->vaha[promennych + 1] = 1;//1 + (int) ((float)max_vaha * (rand()/(RAND_MAX + 1.0)));
}
return problem;
}
/** Destruktor */
void problem_znic(struct problem_s *problem)
{
int i;
for( i = 0; i < problem->klausuli_nacteno; i++) free( problem->klausule[i] );
free( problem->vaha );
free( problem );
}
/** Prida klausuli do formule reseneho problemu, predpoklada konjunktivní normální formu
* @param problem - problem, do ktereho se pridava klausule
* @param promennych - pocet literalu formule
* @param promenne - pole literalu, kazdy literalu, pro negovanou hodnotu je cislo literalu zaporne
* */
void problem_pridej_klausuli(struct problem_s *problem, int promennych, signed short promenne[])
{
struct klausule_s *klausule;
if( problem->klausuli_nacteno == problem->klausuli ){
fprintf(stderr, "Vsechny klauzule uz byly nacteny\n");
} else if ( (klausule = (struct klausule_s *)malloc( sizeof(struct klausule_s)
+ sizeof(signed short) * promennych ) ) == NULL ){
fprintf(stderr, "Dosla pamet\n");
} else {
problem->klausule[problem->klausuli_nacteno++] = klausule;
klausule->promennych = promennych;
while( promennych-- ){
if( promenne[ promennych ] > problem->promennych || promenne[ promennych ] < -problem->promennych){
fprintf(stderr, "Neexistujici promenna\n");
klausule->promenne[ promennych ] = 0;
} else {
klausule->promenne[ promennych ] = promenne[ promennych ];
}
}
}
}
/** Vypise formuli problemu na stdout */
void problem_vypis(struct problem_s *problem)
{
int i, j;
for(i = 0; i < problem->klausuli; i++){
if( problem->klausule[i]->promennych == 0 ) continue;
printf("(");
printf("%d", problem->klausule[i]->promenne[0]);
for( j = 1; j < problem->klausule[i]->promennych; j++ )
printf("%+d", problem->klausule[i]->promenne[j]);
printf(")");
}
printf("\n");
}
/** Otestuje, zda je klausule splnena
* @param klausule - testovana klausule
* @param reseni - ohodnoceni promennych
* @return 1 kdyz je splnena, 0 jinak
*/
int klausule_je_splnena(const struct klausule_s *klausule, const reseni_t *reseni)
{
int j;
for( j = 0; j < klausule->promennych; j++ )
if( klausule->promenne[j] > 0 ){
if( reseni[ klausule->promenne[j] ] ){
return 1;
}
} else if ( ! reseni[ - klausule->promenne[j] ] ){
return 1;
}
return 0;
}
/** Urci pocet splnenych klausuli
* @param problem - problem s dotazovanou formuli
* @param reseni - ohodnoceni promennych
* @return pocet splnenych klauzuli
* */
int problem_splneno_klausuli(const struct problem_s *problem, const reseni_t *reseni)
{
int i, sum = 0;
for( i = 0; i < problem->klausuli; i++ )
if( klausule_je_splnena( problem->klausule[i], reseni ) ) sum++;
return sum;
}
/** Urci pocet splnenych klausuli a aktualizuje vyskyt
* @param problem - problem s dotazovanou formuli
* @param reseni - ohodnoceni promennych
* @param vyskyt - v pripade ze je i-ta formule splnena, zapise do vyskyt[i] krok
* @param krok - zapisovana hodnota
* @return pocet splnenych klauzuli
* */
int problem_splneno_aktualizuj_vyskyt(const struct problem_s *problem, const reseni_t *reseni, int *vyskyt, int krok)
{
int i, sum = 0;
for( i = 0; i < problem->klausuli; i++ )
if( klausule_je_splnena( problem->klausule[i], reseni ) ){
sum++;
vyskyt[i] = krok;
break;
}
return sum;
}
/** Nahodne ohodnoti promenne
* @param problem - problem k jehoz formuli je ohodnoceni generovano
* @param reseni - sem zapise ohodnoceni
* @param pravdepodobnost_jednicky - pravdepodobnost nastaveni promenne na 1
*/
void problem_nahodne_ohodnoceni(const struct problem_s *problem, reseni_t *reseni, float pravdepodobnost_jednicky)
{
int i;
for( i = 0; i <= problem->promennych; i++ )
if( rand() < pravdepodobnost_jednicky*RAND_MAX ) reseni[i] = 1;
else reseni[i] = 0;
}
/** Spocita vahu ohodnoceni
* @param problem - problem s dotazovanou formuli
* @param reseni - ohodnoceni promennych
* @return vahu ohodnoceni
*/
int problem_vaha(const struct problem_s *problem, const reseni_t *reseni)
{
int i, sum = 0;
for( i = 1; i <= problem->promennych; i++ )
if( reseni[i] ) sum += problem->vaha[i];
return sum;
}
/** Vytvori novy vektor promennych (alokuje pamet) */
reseni_t* problem_vektor_reseni(const struct problem_s *problem)
{
return (reseni_t*)malloc( sizeof(reseni_t)*(problem->promennych+1) );
}
/** Zkopiruje ohodnoceni */
void problem_kopiruj_reseni(const struct problem_s *problem, reseni_t *cil, const reseni_t *zdroj)
{
memcpy(cil, zdroj, sizeof(reseni_t)*(problem->promennych + 1) );
}