;*-------------------------------------------------------------------------- ;* Fuzzy Econo-Dynamics - N Firme, Comp/Max/Master-Strategy - v5 ;*-------------------------------------------------------------------------- ;* ;* Implementeaza un sistem economic format din doua sau mai multe ;* firme concurente ce isi modifica pretul de vanzare al produsului ;* functie de beneficiu si pretul concurentei (Strategia Comp) sau ;* numai in functie de pretul concurentei (Strategia Max). ;*__________________________________________________________________________ ;* ;* Beneficiul depinde neliniar de pret: la pret prea scazut, acesta ;* scade (diferenta pret-cheltuieli mica sau negativa). De asemenea, la ;* pret prea mare, beneficiul scade - in primul rand daca concurenta are ;* un pret mai mic, dar chiar si la preturi egale, dar mari, deoarece sunt ;* mai putini cumparatori pe piata. ;* ;* Dinamica apare deoarece modificarea pretului (care este reactia ;* firmei, politica firmei fata de beneficiul avut la momentul respectiv) ;* este lenta (cu intarziere). De asemenea, concurenta raspunde cu intarziere ;* la reactia firmei. ;*__________________________________________________________________________ ;* ;* Fisierul cu datele de intrare "Ec_dyn.in" trebuie sa contina pentru ;* toate cele N firme numele acestora, pretul initial al produsului, precum ;* si strategia pe care aceasta o foloseste. Pentru strategie se pot folosi ;* simbolurile 'comp' si 'max' (implicit se foloseste 'comp'). Dupa introducerea ;* acestor date se va specifica si matricea M cu intarzierile reactiilor firmelor. ;* Programul creaza fisierul "Ec_dyn.out" cu datele de iesire, preturile ;* si profiturile celor N firme, pentru prelucrari statistice ulterioare. ;* V9->V10 Optiune suplimentara de fluctuatie a pretului (valoarea poate ramane aceiasi), ;* optiune absolut necesara pentru stabilitatea sistemului (in absenta acesteia ;* sistemul economic nu poate atinge niciodata un punct de echilibru) ;* V10->V11 Sunt introduse mai multe firme pe piata (nu doar doua ca in modelul initial) ;* Intarzierile cu care o firma afla preturile celorlalte firme sunt citite ;* dintr-un fisier text sub forma unei matrici ;* V11->NV1 Fluctuatia pretului nu mai este realizata doar cu prag fix (variabil in ;* variante anterioare), ci poate fi calculata si fuzzy. Tipul de increment este ;* acelasi pentru toate firmele de pe piata ;* NV2 - s-a adaugat o noua strategie max-benefit (de maximizare a profitului) ;* NV3 - posibilitatea asocierii pentru fiecare firma a unui tip de increment (fuzzy/fix) ;* NV4 - posibilitatea gruparii firmelor pe tipuri de functii de apartenenta ;* - s-au definit 2 seturi de functii de apartenenta pentru pret, respectiv beneficiu ;* - introducerea datelor despre o firma in fisierul "Ec_dyn.in" va respecta formatul ;* nume_firma pret_initial strategie(max/comp) tip_fa(1/2...) ;* ... tip_incr(fix/fuzzy) val_incr (daca este fix) ;* Implicit: - tip increment = fuzzy; valoare implicita increment fix = 0.1 ;* - tip functii de apartenenta = 1 ;* - tip strategie = comp ;* NV5 Introducerea unei noi strategii (Master) pentru a studia evolutia sistemului ;* economic pe grupuri de influenta (o firma decide modificarile de pret pentru o ;* grupare de firme "slave" - subordonate) ;* NV6 Modificari conceptuale calcul beneficiu intarziat - se aplica intarzierea firmei ;* curente F1 si nu a concurentei F2 (pe care firma nu o poate cunoaste) ;* Benef_actual_F1 = f(pret_actual_firma_F1, pret_intarziat_concurenta_F2) ;* Benef_intarziat_F2 = f(pret_intarziat_concurenta_F2, pret_actual_firma_F1) ;============================================================================ ; CONSTRUCTII GENERALE ;============================================================================ (defmethod + (?a) (return ?a) ) (deftemplate pret1 ; preturile au aceeasi structura pentru ambele firme 1. 25. USD ((scazut ( 3 1) (10 0)) (mediu ( 5 0) (8 1) (21 0)) ; suprapunere ne-perfecta cu urmatoarea f.a. (ridicat (10 0) (25 1))) ) (deftemplate beneficiu1 ; firmele considerate de acceeasi pondere, ; deci beneficiile cu aceeasi structura -25. 65. USD ((foarte_scazut (-25 1) (25 0)) (scazut (15 0) (25 1) (35 0)) (mediu (25 0) (43 1) (45 0)) (ridicat (35 0) (55 1) (60 0)) (foarte_ridicat (45 0) (65 1))) ) (deftemplate pret2 ; preturile au aceeasi structura pentru ambele firme 1. 25. USD ((scazut ( 5 1) (10 0)) (mediu ( 5 0) (10 1) (15 0)) (ridicat (10 0) (15 1))) ) (deftemplate beneficiu2 ; firmele considerate de acceeasi pondere, ; deci beneficiile cu aceeasi structura -25. 65. USD ((foarte_scazut (-25 1) (25 0)) (scazut (15 0) (25 1) (35 0)) (mediu (25 0) (35 1) (45 0)) (ridicat (35 0) (45 1) (55 0)) (foarte_ridicat (45 0) (65 1))) ) (deftemplate informatii1 (slot id) (slot pret (type FUZZY-VALUE pret1)) ) (deftemplate informatii2 (slot id) (slot pret (type FUZZY-VALUE pret2)) ) (deftemplate firma (slot nume) (multislot lista_preturi) (slot strategie) (slot tip_fa) (slot tip_incr) (slot val_incr) (multislot firme_concurente) (slot nfc) ) (deftemplate grup (slot master) (multislot slave) (multislot procent) ) (defglobal ?*stepc* = 0 ; variabila ce contorizeaza numarul de pasi ?*stept* = 100 ; numarul total de pasi ) ;============================================================================ ; ; REGULI FUZZY DE CALCUL BENEFICIU ; ;============================================================================ (defrule beneficiu_pret_firma_scazut_pret_concurenta_scazut (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret scazut)) ; firma #1 are pret scazut (informatii2 (id ?f1) (pret scazut)) ) (or (informatii1 (id ?f2) (pret scazut)) ; firma #2 are pret scazut (informatii2 (id ?f2) (pret scazut)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " mediu)")) ) (defrule beneficiu_pret_firma_scazut_pret_concurenta_mediu (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret scazut)) (informatii2 (id ?f1) (pret scazut)) ) (or (informatii1 (id ?f2) (pret mediu)) (informatii2 (id ?f2) (pret mediu)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " more-or-less mediu)")) ) (defrule beneficiu_pret_firma_scazut_pret_concurenta_ridicat (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret scazut)) (informatii2 (id ?f1) (pret scazut)) ) (or (informatii1 (id ?f2) (pret ridicat)) (informatii2 (id ?f2) (pret ridicat)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " foarte_ridicat)")) ) (defrule beneficiu_pret_firma_mediu_pret_concurenta_scazut (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret mediu)) (informatii2 (id ?f1) (pret mediu)) ) (or (informatii1 (id ?f2) (pret scazut)) (informatii2 (id ?f2) (pret scazut)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " scazut)")) ) (defrule beneficiu_pret_firma_mediu_pret_concurenta_mediu (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret mediu)) (informatii2 (id ?f1) (pret mediu)) ) (or (informatii1 (id ?f2) (pret mediu)) (informatii2 (id ?f2) (pret mediu)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " ridicat)")) ) (defrule beneficiu_pret_firma_mediu_pret_concurenta_ridicat (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret mediu)) (informatii2 (id ?f1) (pret mediu)) ) (or (informatii1 (id ?f2) (pret ridicat)) (informatii2 (id ?f2) (pret ridicat)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " somewhat ridicat)")) ) (defrule beneficiu_pret_firma_ridicat_pret_concurenta_scazut (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret ridicat)) (informatii2 (id ?f1) (pret ridicat)) ) (or (informatii1 (id ?f2) (pret scazut)) (informatii2 (id ?f2) (pret scazut)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " foarte_scazut)")) ) (defrule beneficiu_pret_firma_ridicat_pret_concurenta_mediu (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret ridicat)) (informatii2 (id ?f1) (pret ridicat)) ) (or (informatii1 (id ?f2) (pret mediu)) (informatii2 (id ?f2) (pret mediu)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " scazut)")) ) (defrule beneficiu_pret_firma_ridicat_pret_concurenta_ridicat (calcul_beneficiu ? ?f1 ?f2) (or (informatii1 (id ?f1) (pret ridicat)) (informatii2 (id ?f1) (pret ridicat)) ) (or (informatii1 (id ?f2) (pret ridicat)) (informatii2 (id ?f2) (pret ridicat)) ) (firma (nume ?f1) (tip_fa ?fa)) => (assert-string (str-cat "(beneficiu" ?fa " scazut)")) ) ;============================================================================ ; ; REGULI FUZIFICARE / DEFUZIFICARE ; ;============================================================================ ; Regulile de calcul al beneficiului la un pret actual si la pret intarziat ; se vor activa de maxim n*(n-1) ori deorece variabila ?id1 va fi inlocuita ; pe rand cu unul din simbolurile din lista numelor firmelor, iar variabila ; ?id2 va fi una din firmele concurente (defrule startare_calcul_beneficiu_la_pret_actual (declare (salience -2)) (not (valoare_pret ? scade|creste|aceiasi|stop )) ; daca modificarea preturilor s-a efectuat (firma (nume ?id1) (tip_fa ?fa1) ; se selecteaza firma curenta ?id1 (firme_concurente $? ?id2 $?) ; si una din firmele concurente ?id2 (lista_preturi ?vpaf $?)) ; pretul actual al firmei ?vpaf (firma (nume ?id2) (tip_fa ?fa2) (lista_preturi $?l ?vpic $?)) ; pretul intarziat al concurentei ?vpic (or (and (firma (nume ?id1) (strategie ?str &~slave)) (intarziere ?id1 ?id2 ?tau) ) (and (grup (master ?nm) (slave $? ?id1 $?)) ; firma slave are intarzierile si (firma (nume ?nm) (strategie ?str)) ; strategia master-ului (intarziere ?nm ?id2 ?tau) ) ) (test (eq (length$ $?l) ?tau)) => (assert (calcul_beneficiu pret_actual ?id1 ?id2)) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id1") (pret (PI 0 " ?vpaf ")))")) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id2") (pret (PI 0 " ?vpic ")))")) ; (assert-string (str-cat "(informatii" ?fa2 " (id " ?id2") (pret (PI 0 " ?vpic ")))")) (if (eq ?str comp-profit) then (assert (adauga_pret_concurenta ?id1 ?vpic)) ) ) (defrule startare_calcul_beneficiu_la_pret_intarziat (declare (salience -2)) (not (valoare_pret ? scade|creste|aceiasi|stop )) (firma (nume ?id1) (tip_fa ?fa1) (lista_preturi ?vpaf $?) (firme_concurente $? ?id2 $?)) (firma (nume ?id2) (tip_fa ?fa2) (lista_preturi $?l ?vpic $?)) (or (or (firma (nume ?id1) (strategie max-profit) (tip_incr fuzzy)) (firma (nume ?id1) (strategie comp-profit)) ) (and (grup (master ?nm) (slave $? ?id1 $?)) (or (firma (nume ?nm) (strategie max-profit) (tip_incr fuzzy)) (firma (nume ?nm) (strategie comp-profit)) ) ) ) (intarziere ?id1 ?id2 ?tau) ; nu se foloseste conexiunea cea mai rapida (test (eq (length$ $?l) ?tau)) ; adica intarzierea masterului => (assert (calcul_beneficiu pret_intarziat ?id2 ?id1)) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id1 ") (pret (PI 0 " ?vpaf ")))")) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id2 ") (pret (PI 0 " ?vpic ")))")) ; (assert-string (str-cat "(informatii" ?fa2 " (id " ?id2 ") (pret (PI 0 " ?vpic ")))")) ) (defrule startare_evaluare_beneficiu_pret_mai_ridicat (declare (salience -2)) (or (evaluare_beneficiu ?id1) (firma (nume ?id1) (strategie max-profit)) ) (not (valoare_pret ? scade|creste|aceiasi)) (firma (nume ?id1) (tip_fa ?fa1) (lista_preturi ?vp1 $?) (firme_concurente $? ?id2 $?)) (firma (nume ?id2) (tip_fa ?fa2) (lista_preturi $?l ?vp2 $?)) (intarziere ?id1 ?id2 ?tau) (test (eq (length$ $?l) ?tau)) ;;;(and ... (< ?vp1 (get-u-to pret)) ) (or (and (firma (nume ?id1) (tip_incr fuzzy)) (valoare_increment ?id1 ?incr) ) (firma (nume ?id1) (tip_incr fix) (val_incr ?incr)) ) => (if (> (bind ?vp1_next (+ ?vp1 ?incr)) (get-u-to (sym-cat pret ?fa1)) ) then (bind ?vp1_next (get-u-to (sym-cat pret ?fa1)) )) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id1 ") (pret (PI 0 " ?vp1_next ")))")) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id2 ") (pret (PI 0 " ?vp2 ")))")) ; (assert-string (str-cat "(informatii" ?fa2 " (id " ?id2 ") (pret (PI 0 " ?vp2 ")))")) (assert (calcul_beneficiu pret_mai_ridicat ?id1 ?id2) ) ) (defrule startare_evaluare_beneficiu_pret_mai_scazut (declare (salience -2)) (or (evaluare_beneficiu ?id1) (firma (nume ?id1) (strategie max-profit)) ) (not (valoare_pret ? scade|creste|aceiasi)) (firma (nume ?id1) (tip_fa ?fa1) (lista_preturi ?vp1 $?) (firme_concurente $? ?id2 $?)) (firma (nume ?id2) (tip_fa ?fa2) (lista_preturi $?l ?vp2 $?)) (intarziere ?id1 ?id2 ?tau) (test (eq (length$ $?l) ?tau)) ;;;(and ... (> ?vp1 (get-u-from pret)) ) (or (and (firma (nume ?id1) (tip_incr fuzzy)) (valoare_increment ?id1 ?incr) ) (firma (nume ?id1) (tip_incr fix) (val_incr ?incr)) ) => (if (< (bind ?vp1_next (- ?vp1 ?incr)) (get-u-from (sym-cat pret ?fa1)) ) then (bind ?vp1_next (get-u-from (sym-cat pret ?fa1)) )) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id1 ") (pret (PI 0 " ?vp1_next ")))")) (assert-string (str-cat "(informatii" ?fa2 " (id " ?id2 ") (pret (PI 0 " ?vp2 ")))")) (assert (calcul_beneficiu pret_mai_scazut ?id1 ?id2) ) ) (defrule startare_evaluare_beneficiu_slave_pret_mai_ridicat (declare (salience -2)) (grup (master ?nm) (slave $?fs ?id1 $?) (procent $?fp &:(eq(length$ $?fs)(length$ $?fp)) ?p $?)) (or (evaluare_beneficiu ?nm) (firma (nume ?nm) (strategie max-profit)) ) (not (valoare_pret ? scade|creste|aceiasi)) (firma (nume ?id1) (tip_fa ?fa1) (lista_preturi ?vp1 $?) (firme_concurente $? ?id2 $?)) (firma (nume ?id2) (tip_fa ?fa2) (lista_preturi $?l ?vp2 $?)) (intarziere ?nm ?id2 ?tau) (test (eq (length$ $?l) ?tau)) ;;;(and ... (< ?vp1 (get-u-to pret)) ) (or (and (firma (nume ?nm) (tip_incr fuzzy)) (valoare_increment ?nm ?incr) ) (firma (nume ?nm) (tip_incr fix) (val_incr ?incr)) ) => (if (> (bind ?vp1_next (* (+ ?vp1 ?incr) ?p 0.01)) (get-u-to (sym-cat pret ?fa1)) ) then (bind ?vp1_next (get-u-to (sym-cat pret ?fa1)) )) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id1 ") (pret (PI 0 " ?vp1_next ")))")) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id2 ") (pret (PI 0 " ?vp2 ")))")) ; (assert-string (str-cat "(informatii" ?fa2 " (id " ?id2 ") (pret (PI 0 " ?vp2 ")))")) (assert (calcul_beneficiu pret_mai_ridicat ?id1 ?id2) ) ) (defrule startare_evaluare_beneficiu_slave_pret_mai_scazut (declare (salience -2)) (grup (master ?nm) (slave $?fs ?id1 $?) (procent $?fp &:(eq(length$ $?fs)(length$ $?fp)) ?p $?)) (or (evaluare_beneficiu ?nm) (firma (nume ?nm) (strategie max-profit)) ) (not (valoare_pret ? scade|creste|aceiasi)) (firma (nume ?id1) (tip_fa ?fa1) (lista_preturi ?vp1 $?) (firme_concurente $? ?id2 $?)) (firma (nume ?id2) (tip_fa ?fa2) (lista_preturi $?l ?vp2 $?)) (intarziere ?nm ?id2 ?tau) (test (eq (length$ $?l) ?tau)) ;;;(and ... (> ?vp1 (get-u-from pret)) ) (or (and (firma (nume ?nm) (tip_incr fuzzy)) (valoare_increment ?nm ?incr) ) (firma (nume ?nm) (tip_incr fix) (val_incr ?incr)) ) => (if (< (bind ?vp1_next (* (- ?vp1 ?incr) ?p 0.01)) (get-u-from (sym-cat pret ?fa1)) ) then (bind ?vp1_next (get-u-from (sym-cat pret ?fa1)) )) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id1 ") (pret (PI 0 " ?vp1_next ")))")) (assert-string (str-cat "(informatii" ?fa1 " (id " ?id2 ") (pret (PI 0 " ?vp2 ")))")) ; (assert-string (str-cat "(informatii" ?fa2 " (id " ?id2 ") (pret (PI 0 " ?vp2 ")))")) (assert (calcul_beneficiu pret_mai_scazut ?id1 ?id2) ) ) ; Defuzificarea poate fi realizata prin doua metode COG si MAXIMUM ; functie de functia utilizata moment-defuzzify sau maximum-defuzzify (defrule calcul_valori_crisp_beneficiu (declare (salience -1)) ?d <- (calcul_beneficiu ?tip ?id1 ?id2) ; ?d = adresa fapt decizie (or ?b <- (beneficiu1 ?) ; ?b = adresa fapt beneficiu ?b <- (beneficiu2 ?)) (or ?i1 <- (informatii1 (id ?id1)) ; se sterg informatiile ce au servit la ?i1 <- (informatii2 (id ?id1)) ) ; calcularea beneficiului (or ?i2 <- (informatii1 (id ?id2)) ?i2 <- (informatii2 (id ?id2)) ) => (retract ?d ?b ?i1 ?i2) (assert (valoare_beneficiu ?tip ?id1 ?id2 (moment-defuzzify ?b))) ; (assert (valoare_beneficiu ?tip ?id1 ?id2 (maximum-defuzzify ?b))) ) ;============================================================================ ; ; REGULI CITIRE / SCRIERE IN FISIER ; REGULA DE INITIALIZARE LISTE DE PRETURI ; REGULI ACTUALIZARE INFORMATII MASTER ; REGULA DE AFISARE BENEFICII SI PRETURI FIRME ; ;============================================================================ (defrule open_file ; result file (declare (salience 20)) ; max salience 20 => (open "Ec_dyn.in" in "r") (bind $?lista (create$ )) (bind ?error 0) (bind ?nr_firme 0) (while (neq (bind ?line (readline in)) EOF) do ; functia explode$ ia in calcul informatiile pana la caracterul ';' (bind ?line (explode$ ?line)) (if (> (length$ ?line) 0) then (if (eq ?nr_firme 0) then ; nu s-au citit toate firmele (bind ?nume_firma (nth$ 1 ?line)) (bind ?pret_initial (nth$ 2 ?line)) (bind ?strategie (nth$ 3 ?line)) (bind ?tip_fa (nth$ 4 ?line)) (bind ?tip_incr (nth$ 5 ?line)) (if (not (numberp ?nume_firma)) then (if (or (not (symbolp ?tip_incr)) (neq (lowcase ?tip_incr) fix)) then (bind ?tip_incr fuzzy) ; tip implicit increment = fuzzy (bind ?val_incr fuzzy) ; va trebui sa fie calculata else (bind ?val_incr (nth$ 6 ?line)) (if (not (numberp ?val_incr)) then ; valoare implicita increment fix = 0.1 (bind ?val_incr 0.1) ) ) (if (not (numberp ?tip_fa)) then (bind ?tip_fa 1) ) ;tip implicit functii de apartenenta = 1 (if (or (not (symbolp ?strategie)) (neq (lowcase ?strategie) comp max)) then (bind ?strategie comp) ) ; tip implicit strategie (if (numberp ?pret_initial) then (bind $?lista (create$ $?lista ?nume_firma)) (bind ?strategie (sym-cat (lowcase ?strategie) -profit)) (assert (firma (nume ?nume_firma) (strategie ?strategie) (tip_fa ?tip_fa) (tip_incr ?tip_incr) (val_incr ?val_incr)) (pret_initial ?nume_firma ?pret_initial) ) else (bind ?error 1) (break) ) else (bind ?nr_firme (length$ $?lista)) (bind ?firma_curenta 1) (if (< ?nr_firme 2) then (bind ?error 2) (break) ) ) ) (if (neq ?nr_firme 0) then (if (<= ?firma_curenta ?nr_firme) then ;**** matricea intarzierilor **** (bind $?firme_concurente (create$ )) (loop-for-count (?i 1 ?nr_firme) do (if (or (numberp (bind ?v (nth$ ?i ?line))) (eq ?v -)) then (if (neq ?firma_curenta ?i) then (if (neq ?v -) then (assert (intarziere (nth$ ?firma_curenta ?lista) (nth$ ?i ?lista) ?v)) (bind $?firme_concurente (create$ $?firme_concurente (nth$ ?i ?lista))) ) else (assert (preturi_concurenta (nth$ ?firma_curenta ?lista))) ) else (bind ?error 3) (break) ) ) (if (neq ?error 3) then (assert (firme_concurente (nth$ ?firma_curenta ?lista) $?firme_concurente) ) (bind ?firma_curenta (+ ?firma_curenta 1)) else (break) ) else ;**** se citesc gruparile firmelor (conexiuni MASTER-SLAVE) **** (bind $?slave (create$ )) (bind $?procent (create$ )) (if (not (subsetp (create$ (bind ?master (nth$ 1 ?line))) $?lista)) then (bind ?error 4) (break) ) (bind ?i 2) (while (<= ?i (length$ ?line)) (if (not (subsetp (create$ (bind ?firma_slave (nth$ ?i ?line))) $?lista)) then (bind ?error 4) (break) else (bind $?slave (create$ $?slave ?firma_slave)) ) (if (not (numberp (bind ?p (nth$ (+ ?i 1) ?line)) )) then (bind $?procent (create$ $?procent 100)) (bind ?i (+ ?i 1)) else (bind $?procent (create$ $?procent ?p)) (bind ?i (+ ?i 2)) ) ) (if (neq ?error 4) then (assert (grup (master ?master) (slave $?slave) (procent $?procent))) else (break) ) ) ) ) ) (printout t "Fisierul de intrare \"Ec_dyn.in\" ") (switch ?error (case 1 then (printout t "are preturile initiale eronate." t)) (case 2 then (printout t "are un numarul de firme prea mic." t)) (case 3 then (printout t "are intarzierile reactiilor firmelor incorecte." t)) (case 4 then (printout t "are numele firmelor din grupuri incorecte." t)) (default (printout t "a fost citit cu succes." t) (assert (lista_firme ?lista)) ) ) (close in) (open "Ec_dyn.out" d "w") (printout t crlf "Datele de iesire se afla in fisierul \"Ec_dyn.out\"" t t) ; (format d " Pret vs Beneficiu %n %n") ; (format d " P1 vs B1 || P2 vs B2 %n %n") ; (printout t "Introduceti numarul maxim de pasi de calcul(implicit " ?*stepc* "): " t) ; (bind ?n (read)) ; (if (numberp ?n) then (bind ?*stepc* (abs (integer ?n))) ) ) ; Pentru firmele de tip Master-Slave se verifica daca tipul de strategie este corect ; specificat. Firmele slave doar vor transmite informatii la master, nu vor intra in ; procesul inferential (nu se va calcula beneficiu/pret actual pentru acestea). (defrule modifica_informatii_firma_slave (declare (salience 20)) (grup (master ?nm) (slave $?fs ?ns $?) (procent $?fp &:(eq(length$ $?fs)(length$ $?fp)) ?p $?)) ?f1 <- (firma (nume ?ns) (strategie ?str &~slave)) (firma (nume ?nm) (tip_fa ?tm)) (pret_initial ?nm ?vpm) ?f2 <- (pret_initial ?ns ?) => (modify ?f1 (strategie slave) (tip_fa ?tm) (tip_incr -) (val_incr -)) (retract ?f2) (assert (pret_initial ?ns (* ?vpm ?p .01))) ) (defrule verificare_relatii_concurenta_master (declare (salience 20)) (grup (master ?nm) (slave $? ?ns $?)) ?f1 <- (firme_concurente ?nm $?first ?ns $?last) ?f2 <- (intarziere ?nm ?ns ?) => ;**** intre master si slave nu exista intarzieri **** (retract ?f1 ?f2) (assert (firme_concurente ?nm $?first $?last)) ) (defrule verificare_relatii_concurenta_slave (declare (salience 20)) (grup (master ?nm) (slave $? ?ns $?)) (or (and ?f1 <- (firme_concurente ?ns $?first ?nm $?last) ?f2 <- (intarziere ?ns ?nm ?) ) (and (grup (master ?nm) (slave $? ?ns2 &~?ns $?)) ?f1 <- (firme_concurente ?ns $?first ?ns2 $?last) ?f2 <- (intarziere ?ns ?ns2 ?) ) ) => ;**** intre slave si master sau alti slave nu exista intarzieri **** (retract ?f1 ?f2) (assert (firme_concurente ?ns $?first $?last)) ) (defrule adaugare_intarziere_concurenta_master (declare (salience 15)) (grup (master ?nm) (slave $? ?ns $?)) ?f <- (firme_concurente ?nm $?fcm) (firme_concurente ?ns $? ?fcs &:(not(member$ ?fcs $?fcm)) $?) (not (exists (intarziere ?nm ?fcs ?))) ;???? (intarziere ?ns ?fcs &~?nm ?v) => ;???? o firma concurenta pentru un slave dar nu si pentru master NU ar trebui adaugata la lista master ;(retract ?f) (assert (firme_concurente ?nm $?fcm ?fcs)) (assert (intarziere ?nm ?fcs ?v)) ) (defrule gasire_intarzieri_minimale_master (declare (salience 20)) (grup (master ?nm) (slave $?slave)) ?f <- (intarziere ?nm ?fcm ?v) (intarziere ?ns &:(member$ ?ns $?slave) ?fcm ?v1 &:(< ?v1 ?v)) (not (exists (intarziere ?ns2&:(member$ ?ns $?slave) ?fcm ?v2 &:(< ?v2 ?v1)) )) => (retract ?f) (assert (intarziere ?nm ?fcm ?v1)) ) (defrule completare_valori_lista_preturi (declare (salience 10)) ?f1 <- (firma (nume ?nume_firma)) ?f2 <- (firme_concurente ?nume_firma $?fc) (intarziere ? ?nume_firma ?v) (not (exists (intarziere ? ?nume_firma ?v2 &:(> ?v2 ?v)) )) ?f3 <- (pret_initial ?nume_firma ?vp) => (retract ?f2 ?f3) (bind $?lista (create$ ?vp)) (loop-for-count (?i 1 ?v) do (bind $?lista (create$ $?lista ?vp)) ) (modify ?f1 (firme_concurente $?fc) (nfc (length$ $?fc)) (lista_preturi $?lista)) ) (defrule afisare_informatii_1 (declare (salience -10)) (lista_firme ?id $?last) (firma (nume ?id) (lista_preturi ?vpf $?)) ; vpf - valoare curenta pret firma ?f <- (beneficiu_mediu pret_actual ?id ?vbf) => (retract ?f) (format d "%3d %4.2f %6.3f" ?*stepc* ?vpf ?vbf) ; (format t "%3d %3.1f -- %6.3f" ?*stepc* ?vpf ?vbf) (bind ?*stepc* (+ ?*stepc* 1)) (assert (lista_firme_de_afisat $?last)) ) (defrule afisare_informatii_2 ?f1 <- (lista_firme_de_afisat ?id $?last) (firma (nume ?id) (lista_preturi ?vpf $?)) ; vpf - valoare curenta pret firma (or ?f2 <- (beneficiu_mediu pret_actual ?id ?vbf) ?f2 <- (beneficiu_mediu_slave ?id ?vbf) ) => (retract ?f1 ?f2) (format d " %4.2f %6.3f" ?vpf ?vbf) (if (neq (length$ $?last) 0) then (assert (lista_firme_de_afisat $?last)) ; (printout t " |") else ; (printout t t) (format d " %n")) ) (defrule close_file_1 (declare (salience -20)) => (close d) ) (defrule close_file_2 (declare (salience 20)) (firma (nume ?id) (lista_preturi $?)) ?f <- (lista_firme ?id $?) (test (>= ?*stepc* ?*stept*)) ; dupa 100 de pasi se opreste automat => (retract ?f) (assert (valoare_pret toate_firmele stop)) ) ;============================================================================ ; ; REGULI PENTRU CALCULUL BENEFICIULUI MEDIU ; SI A MEDIEI PRETURILOR CONCURENTEI ; ;============================================================================ ; Se goleste lista preturilor practicate de concurenta unei firme ?id pentru ; a fi reactualizata cu preturile calulate in ciclul urmator de functionare. (defrule adaugare_pret_concurenta_in_lista ?f1 <- (adauga_pret_concurenta ?id ?vpic) ?f2 <- (preturi_concurenta ?id $?first) => (retract ?f1 ?f2) (assert (preturi_concurenta ?id $?first ?vpic)) ) (defrule calcul_medie_preturi_concurenta (declare (salience -3)) ?f <- (preturi_concurenta ?id $?vp) (firma (nume ?id) (nfc ?nfc &: (eq ?nfc (length$ $?vp)) )) => (retract ?f) (assert (preturi_concurenta ?id) (medie_preturi_concurenta ?id (/ (+ (expand$ $?vp)) ?nfc)) ) ) (defrule adaugare_beneficiu_firma_in_lista_1 (or ?f <- (valoare_beneficiu ?tip &~pret_intarziat ?id ? ?vb) ?f <- (valoare_beneficiu ?tip &pret_intarziat ? ?id ?vb) ) (not (lista_beneficii ?tip ?id $?)) => (retract ?f) (assert (lista_beneficii ?tip ?id ?vb)) ) (defrule adugare_beneficiu_firma_in_lista_2 (or ?f1 <- (valoare_beneficiu ?tip &~pret_intarziat ?id ? ?vb) ?f1 <- (valoare_beneficiu ?tip &pret_intarziat ? ?id ?vb) ) ?f2 <- (lista_beneficii ?tip ?id $?lvb) => (retract ?f1 ?f2) (assert (lista_beneficii ?tip ?id $?lvb ?vb)) ) (defrule calcul_beneficiu_mediu_firma (declare (salience -3)) ?f <- (lista_beneficii ?tip ?id $?vb) (firma (nume ?id) (nfc ?nfc &: (eq ?nfc (length$ $?vb)) )) => (retract ?f) (assert (beneficiu_mediu ?tip ?id (/ (+ (expand$ $?vb)) ?nfc)) ) ) (defrule adauga_beneficiu_mediu_slave_la_beneficiu_mediu_master ?f1 <- (beneficiu_mediu ?tip ?id1 $?vbm1) ?f2 <- (beneficiu_mediu ?tip ?id2 ?vbm2) (grup (master ?id1) (slave $? ?id2 $?)) => (retract ?f1 ?f2) (if (eq ?tip pret_actual) then (assert (beneficiu_mediu_slave ?id2 ?vbm2)) ) ; necesar la afisare_informatii (assert (beneficiu_mediu ?tip ?id1 $?vbm1 ?vbm2)) ) (defrule adauga_pret_mediu_concurenta_slave_la_pret_mediu_master ?f1 <- (medie_preturi_concurenta ?id1 $?vpm1) ?f2 <- (medie_preturi_concurenta ?id2 ?vpm2) (grup (master ?id1) (slave $? ?id2 $?)) => (retract ?f1 ?f2) (assert (medie_preturi_concurenta ?id1 $?vpm1 ?vpm2)) ) (defrule adauga_pret_master_la_preturi_grup (grup (master ?nm)) (firma (nume ?nm) (lista_preturi ?vp $?)) => (assert (preturi_grup ?nm ?vp)) ) (defrule adauga_pret_slave_la_preturi_grup_1 (declare (salience -1)) (grup (master ?nm) (slave $? ?ns $?)) (firma (nume ?ns) (lista_preturi ?vp $?)) => (assert (adauga_preturi_grup ?nm ?ns ?vp) ) ) (defrule adauga_pret_slave_la_preturi_grup_2 ?f1 <- (preturi_grup ?nm $?v) ?f2 <- (adauga_preturi_grup ?nm ?ns ?vp) => (retract ?f1 ?f2) (assert (preturi_grup ?nm $?v ?vp) ) ) (defrule calcul_medie_preturi_grup (declare (salience -3)) ?f <- (preturi_grup ?nm $?v) => (retract ?f) (assert (medie_preturi_grup ?nm (/ (+ (expand$ $?v)) (length$ $?v)) )) ) ; Este posibil ca masterul sa coordoneze activitatea grupului, fara a avea conexiuni ; cu firme concurente direct (nu prin intermediul firmelor slave). Din acest motiv ; este relevant un test de genul (nr_beneficii_medii = nr_firme_grup = nr_slave + 1) (defrule adjustare_beneficii_mediu_grup_la_numar_slave (declare (salience -4)) (grup (master ?nm)) ?f <- (beneficiu_mediu ?tip ?nm $?v&:(>= (length$ $?v) 2) ) => (retract ?f) (assert (beneficiu_mediu ?tip ?nm (/ (+ (expand$ $?v)) (length$ $?v)) )) ) (defrule adjustare_preturi_medii_concurenta_grup_la_numar_slave (declare (salience -4)) (grup (master ?nm)) ?f <- (medie_preturi_concurenta ?nm $?v&:(>= (length$ $?v) 2) ) => (retract ?f) (assert (medie_preturi_concurenta ?nm (/ (+ (expand$ $?v)) (length$ $?v)) )) ) ;============================================================================ ; ; REGULI PENTRU MODIFICAREA PRETURILOR ; ;============================================================================ ; STRATEGIE: COMP-PROFIT ; Regulile urmatoare compara beneficiul obtinut de firma la pretul actual ; practicat de aceasta, cu beneficiul mediu obtinut de concurenta la pret ; intarziat si se stabilesc modificarile ce vor fi efectuate: ; Daca beneficul firmei este mai mic: ; - se compara pretul actual cu "media" preturilor firmelor concurente si ; daca acesta este mai mare/mic decat aceasta media se realizeaza o ; scadere/crestere a pretului ; Daca beneficul firmei este mai mare: ; - se va evalua beneficiul obtinut daca produsul firmei ar avea un pret ; actual mai mare / mai mic (op. de maximizare) (defrule modificare_pret_daca_beneficiu_mic (declare (salience -7)) (or (and (firma (nume ?id) (strategie comp-profit) (lista_preturi ?vp1 $?)) (not (exists (grup (master ?id)))) ) (and (firma (nume ?id) (strategie comp-profit)) (grup (master ?id)) (medie_preturi_grup ?id ?vp1) ) ) ?f1 <- (medie_preturi_concurenta ?id ?vp2) (beneficiu_mediu pret_actual ?id ?vb1) ?f2 <- (beneficiu_mediu pret_intarziat ?id ?vb2 &:(< ?vb1 ?vb2)) => (retract ?f1 ?f2) (if (<= ?vp1 ?vp2) then (assert (valoare_pret ?id creste)) else (assert (valoare_pret ?id scade)) ) ) (defrule modificare_pret_daca_beneficiu_mare (declare (salience -6)) (firma (nume ?id) (strategie comp-profit)) (beneficiu_mediu pret_actual ?id ?vb1) ?f1 <- (beneficiu_mediu pret_intarziat ?id ?vb2 &:(>= ?vb1 ?vb2)) ?f2 <- (medie_preturi_concurenta ?id ?vp2) => (retract ?f1 ?f2) (assert (evaluare_beneficiu ?id)) ) ;(defrule evaluare_master_implica_evaluare_slave ; s-au modificat regulile de evaluare_beneficii ; (evaluare_beneficiu ?nm) ; (firma (master ?nm) (slave $?slave)) ; => ; (loop-for-count (?i 1 (length$ $?slave)) ; (assert (evaluare_beneficiu (nth$ ?i $?slave))) ;) ) ; Se modifica pretul pentru a obtine un beneficiu mai mare (op. de maximizare ; realizata cu strategia max-profit) (defrule eliminare_fapte_redundante (declare (salience -8)) (or ?f <- (evaluare_beneficiu ?) (and ?f <- (medie_preturi_grup ?id ?) (valoare_pret ?id ?)) ) => (retract ?f ) ) ; STRATEGIE: MAX-PROFIT ; Firma nu mai tine cont de beneficul (preturile) concurentei atunci cand ; isi modifica pretul de vanzare, singurul scop imediat fiind de asi maximiza ; profitul. In functie de valorile beneficiilor obtinute la un pret mai ; ridicat / scazut se ia decizia de a pastra acelasi pret sau de al modifica. ; Regula este aproape identica cu 'modificare_pret_daca_beneficiu_mare'. (defrule modificare_pret_functie_de_beneficiul_maxim (declare (salience -7)) (beneficiu_mediu pret_actual ?id ?vbpa) ?f1 <- (beneficiu_mediu pret_mai_ridicat ?id ?vbpr) ?f2 <- (beneficiu_mediu pret_mai_scazut ?id ?vbps) => (retract ?f1 ?f2) (switch (max ?vbpa ?vbpr ?vbps) (case ?vbps then (assert (valoare_pret ?id scade)) ) (case ?vbpa then (assert (valoare_pret ?id aceiasi)) ) (case ?vbpr then (assert (valoare_pret ?id creste)) ) ) (if (eq ?vbpa ?vbpr ?vbps) then (printout t ?id " actual=ridicat=scazut" t) else (if (eq ?vbpa ?vbpr) then (printout t ?id " actual=ridicat" t) else (if (eq ?vbpa ?vbps) then (printout t ?id " actual=scazut" t) else (if (eq ?vbpr ?vbps) then (printout t ?id " ridicat=scazut" t))))) ) ; Se modifica listele de preturi punand in fata noul pret si eliminand ; ultimul element din lista (pentru a pastra dimensiunile listelor) (defrule valoare_pret_firma_creste (declare (salience -15)) ?f1 <- (firma (nume ?id) (tip_fa ?fa) (lista_preturi ?vp $?lista)) ?f2 <- (valoare_pret ?id creste) (or (and ?f3 <- (valoare_increment ?id ?incr) (firma (nume ?id) (tip_incr ?tip &fuzzy)) ) ?f3 <- (firma (nume ?id) (tip_incr ?tip &fix) (val_incr ?incr)) ) => (retract ?f1 ?f2) (if (eq ?tip fuzzy) then (retract ?f3)) (if (> (bind ?vp_next (+ ?vp ?incr)) (get-u-to (sym-cat pret ?fa)) ) then (bind ?vp_next (get-u-to (sym-cat pret ?fa)) )) (bind ?lista (create$ ?vp_next ?vp $?lista)) (modify ?f1 (lista_preturi (subseq$ $?lista 1 (- (length$ $?lista) 1)))) ) (defrule valoare_pret_firma_scade (declare (salience -15)) ?f1 <- (firma (nume ?id) (tip_fa ?fa) (lista_preturi ?vp $?lista)) ?f2 <- (valoare_pret ?id scade) (or (and ?f3 <- (valoare_increment ?id ?incr) (firma (nume ?id) (tip_incr ?tip &fuzzy)) ) ?f3 <- (firma (nume ?id) (tip_incr ?tip &fix) (val_incr ?incr)) ) => (retract ?f1 ?f2) (if (eq ?tip fuzzy) then (retract ?f3)) (if (< (bind ?vp_next (- ?vp ?incr)) (get-u-from (sym-cat pret ?fa)) ) then (bind ?vp_next (get-u-from (sym-cat pret ?fa)) )) (bind ?lista (create$ ?vp_next ?vp $?lista)) (modify ?f1 (lista_preturi (subseq$ $?lista 1 (- (length$ $?lista) 1)))) ) ; chiar daca lista preturilor ramane aceiasi (are toate valorile identice) ; trebuie modificat faptul (schimbata adresa de fapt) pentru a reactiva regulile (defrule aceiasi_valoare_pret_firma (declare (salience -15)) ?f1 <- (firma (nume ?id) (lista_preturi ?vp $?lista)) ?f2 <- (valoare_pret ?id aceiasi) (or (and ?f3 <- (valoare_increment ?id ?incr) (firma (nume ?id) (tip_incr ?tip &fuzzy)) ) ?f3 <- (firma (nume ?id) (tip_incr ?tip &fix) (val_incr ?incr)) ) => (retract ?f1 ?f2) (if (eq ?tip fuzzy) then (retract ?f3)) (modify ?f1 (lista_preturi ?vp ?vp (subseq$ $?lista 1 (- (length$ $?lista) 1)))) ) (defrule valoare_pret_slave_se_modifica (grup (master ?nm) (slave $?slave)) (valoare_pret ?nm ?tip_modif) => (loop-for-count (?i 1 (length$ $?slave)) (assert (valoare_pret (nth$ ?i $?slave) ?tip_modif)) ) ) (defrule valoare_pret_slave_creste (declare (salience -14)) (grup (master ?nm) (slave $?fs ?id $?) (procent $?fp &:(eq(length$ $?fs)(length$ $?fp)) ?p $?)) (firma (nume ?nm) (lista_preturi ?vp $?)) ?f1 <- (firma (nume ?id) (tip_fa ?fa) (lista_preturi $?lista)) ?f2 <- (valoare_pret ?id creste) (or (and (valoare_increment ?nm ?incr) (firma (nume ?nm) (tip_incr ?tip &fuzzy)) ) (firma (nume ?nm) (tip_incr ?tip &fix) (val_incr ?incr)) ) => (retract ?f1 ?f2) (if (> (bind ?vp_next (* (+ ?vp ?incr) ?p .01)) (get-u-to (sym-cat pret ?fa)) ) then (bind ?vp_next (get-u-to (sym-cat pret ?fa)) )) (bind ?lista (create$ ?vp_next $?lista)) (modify ?f1 (lista_preturi (subseq$ $?lista 1 (- (length$ $?lista) 1)))) ) (defrule valoare_pret_slave_scade (declare (salience -14)) (grup (master ?nm) (slave $?fs ?id $?) (procent $?fp &:(eq(length$ $?fs)(length$ $?fp)) ?p $?)) (firma (nume ?nm) (lista_preturi ?vp $?)) ?f1 <- (firma (nume ?id) (tip_fa ?fa) (lista_preturi $?lista)) ?f2 <- (valoare_pret ?id scade) (or (and (valoare_increment ?nm ?incr) (firma (nume ?nm) (tip_incr ?tip &fuzzy)) ) (firma (nume ?nm) (tip_incr ?tip &fix) (val_incr ?incr)) ) => (retract ?f1 ?f2) (if (< (bind ?vp_next (* (- ?vp ?incr) ?p .01)) (get-u-from (sym-cat pret ?fa)) ) then (bind ?vp_next (get-u-from (sym-cat pret ?fa)) )) (bind ?lista (create$ ?vp_next $?lista)) (modify ?f1 (lista_preturi (subseq$ $?lista 1 (- (length$ $?lista) 1)))) ) ; chiar daca lista preturilor ramane aceiasi (are toate valorile identice) ; trebuie modificat faptul (schimbata adresa de fapt) pentru a reactiva regulile (defrule aceiasi_valoare_pret_slave (declare (salience -14)) (grup (master ?nm) (slave $? ?id $?)) ?f1 <- (firma (nume ?id) (lista_preturi ?vp $?lista)) ?f2 <- (valoare_pret ?id aceiasi) (or (and ?f3 <- (valoare_increment ?nm ?incr) (firma (nume ?nm) (tip_incr ?tip &fuzzy)) ) ?f3 <- (firma (nume ?nm) (tip_incr ?tip &fix) (val_incr ?incr)) ) => (retract ?f1 ?f2) (modify ?f1 (lista_preturi ?vp ?vp (subseq$ $?lista 1 (- (length$ $?lista) 1)))) ) ;============================================================================ ; ; CONSTRUCTII + REGULI FUZZY INCREMENT ; ;============================================================================ (deftemplate dif_profit -90 90 ((large_negative (-40 1) (-15 0)) (negative (-40 0) (-15 1) (0 0)) (zero (-15 0) (0 1) (15 0)) (positive (0 0) (15 1) (40 0)) (large_positive (15 0) (40 1)) ) ) (deftemplate increment 0 2 USD ((mic (0 1) (0.3 0)) (mediu (0.2 0) (0.4 1) (0.7 0)) (mare (0.5 0) (1 1)) ) ) (defrule dif_profit_large_negative (dif_profit large_negative) => (assert (increment mare)) ) (defrule dif_profit_negative (dif_profit negative) => (assert (increment mediu)) ) (defrule dif_profit_zero (dif_profit zero) => (assert (increment mic)) ) (defrule dif_profit_positive (dif_profit positive) => (assert (increment mediu)) ) (defrule dif_profit_large_positive (dif_profit large_positive) => (assert (increment mare)) ) (defrule fuzificare_diferenta_beneficii (declare (salience -5)) (firma (nume ?id) (tip_incr fuzzy)) (beneficiu_mediu pret_actual ?id ?vbmpa) ?f <- (beneficiu_mediu pret_intarziat ?id ?vbmpi) (firma (nume ?id) (strategie ?str)) => (if (eq ?str max-profit) then (retract ?f) ) (if (< (abs(- ?vbmpa ?vbmpi)) 1) then (assert (valoare_increment ?id 0))) !!!!!!! (assert (calcul_increment ?id) (dif_profit (PI 0 (- ?vbmpa ?vbmpi)) )) ) (defrule calcul_valoare_crisp_increment (declare (salience -1)) (firma (nume ?id) (tip_incr fuzzy)) ?f1 <- (increment ?) ?f2 <- (calcul_increment ?id) ?f3 <- (dif_profit ?) => (retract ?f1 ?f2 ?f3) (assert (valoare_increment ?id (moment-defuzzify ?f1))) )