1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2% Bousi-Prolog to Prolog (TPL) translator 3 4:- module(translator, [ 5 translate_program/4, % +InputProgram, +InputOntology, 6 % +OutputFile, +StateFile 7 translate_query/4 % +String, -Query, -Bindings, -Degree 8 ]). 9 10:- use_module(parser). 11:- use_module(evaluator). 12:- use_module(flags). 13:- use_module(utilities). 14 15:- use_module(library(lists)). 16 17%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 19:- set_prolog_flag(double_quotes, codes). 20 21 22%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23% Translation of Bousi-Prolog files 24%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
If the compilation of the program or the ontology causes an error, this predicate will fail and won't generate anything.
39translate_program(InputProgram, InputOntology, OutputFile, StateFile) :-
40 % Parses the specified program and ontology files and gets all the
41 % directives, rules and equations that are defined in them
42 parser:parse_program(InputProgram, InputOntology, Directives, Rules,
43 Equations, LingTerms, Messages),
44 !,
45 % Builds a list with the text of the messages returned by parser
46 Template = [_File, _Line, _Column, Text, _Type],
47 findall(Text, member(Template, Messages), TextMessages),
48 % Checks if parser generated any error
49 (member([_, _, _, _, error], Messages) ->
50 % Shows errors and warnings and then stops translation
51 forall(member(Message, TextMessages), (write(Message), nl)),
52 fail
53 ;
54 % Warnings aren't shown here because they'll be shown when
55 % loading the TPL file
56 true
57 ),
58 % List of t-norms for the different relations
59 build_t_norms(Directives,TNorms),
60 % Adds the linguistic terms to the list of fuzzy subsets found in
61 % source code
62 add_linguistic_terms(LingTerms, AddedSubsets),
63 % Computes the closure of each fuzzy relation
64 expand_equations([sim, gEqThan, lEqThan, frel1, frel2, frel3],
65 Equations, ExpEquations1),
66 % Converts the fuzzy sets into a list of equations of the binary fuzzy relation sim
67 translate_fuzzy_sets([], ExpEquations2),
68 append(ExpEquations1, ExpEquations2, ExpEquations),
69 build_block_equations(ExpEquations, ExpBlockEquations),
70 % Expands the list of rules using the proximity/similarity relation
71 utilities:simplify_filename(InputProgram, ProgramPrefix),
72 expand_rules(Rules, ExpRules, ProgramPrefix, ExpEquations),
73 % Writes TPL code to output file
74 telling(CurrentOutput),
75 tell(OutputFile),
76 writeq((:- style_check([-singleton, -discontiguous]))), write('.'), nl,
77 (Messages == [] ->
78 true
79 ;
80 % Writes warnings in TPL file to show them each time the file is loaded
81 create_writes(TextMessages, Writes),
82 writeq((:- initialization(Writes))), write('.'), nl
83 ),
84 utilities:write_lines(Directives, '', '.'), nl,
85 utilities:write_lines(TNorms, '', '.'), nl,
86 (AddedSubsets == [] ->
87 true
88 ;
89 % Adds new fuzzy_set/2 directives to define the linguistic terms
90 % built with the '#' operator found in the BPL code
91 write_fuzzy_set_directives(AddedSubsets)
92 ),
93% (\+ flags:get_bpl_flag(weak_unification('a3')) ->
94 utilities:write_lines(ExpEquations, '', '.'), nl,
95% ;
96 utilities:write_lines(ExpBlockEquations, '', '.'),
97% ),
98 nl,
99 utilities:write_lines(ExpRules, '', '.'), nl,
100 told,
101 tell(CurrentOutput),
102 tell(StateFile),
103 current_bpl_flags(Flags),
104% writef('%w.\n%w.\n', [':- dynamic tpl_flags/1', flags:tpl_flags(Flags)]),
105% writef('%w.\n', [tpl_flags(Flags)]),
106 writef('%w.\n%w.\n', [':- multifile tpl_flags/1', tpl_flags(Flags)]),
107 told.
t_norm(Relation,TNorm)
representing the t-norm for each Relation.
If no directive is available for a given relation,
its default t-norm is used instead.
These terms are added to the tpl program, so that
they define the predicate t_norm/2. 120build_t_norms(Directives,TNorms) :-
121 findall(t_norm(Relation,Type),
122 (member(fuzzy_rel(Relation,Properties),Directives),
123 member(transitive(Type),Properties)
124 ),
125 FTNorms
126 ),
127 (member(t_norm('~',_Type),FTNorms) -> % '~' must be present in any BPL-program
128 TNorms=FTNorms
129 ;
130 flags:default_t_norm('~',Type),
131 TNorms=[t_norm('~',Type)|FTNorms]
132 ).
141create_writes([], true). 142 143create_writes([Message|MoreMessages], Writes) :- 144 SingleWrite = (write(Message), nl), 145 create_writes(MoreMessages, MoreWrites), 146 (MoreWrites == true -> 147 Writes = SingleWrite 148 ; 149 Writes = (SingleWrite, MoreWrites) 150 ).
directive(fuzzy_set, Item)
.' in current
output stream for each Item in Subsets list.159write_fuzzy_set_directives([]). 160 161write_fuzzy_set_directives([Subset|MoreSubsets]) :- 162 writeq((:- directive(fuzzy_set, Subset))), write('.'), nl, 163 write_fuzzy_set_directives(MoreSubsets). 164 165 166 167%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 168% Translation of Bousi-Prolog queries 169%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
If the translation of the query causes an error, this predicate will fail.
187translate_query(String, Query, Bindings, Degree) :- 188 % Parses the specified query to get an executable term 189 flags:get_bpl_flag(program_prefix(ProgramPrefix)), 190 parser:parse_query(ProgramPrefix, String, ParsedQuery, LingTerms, Messages), 191 % Builds a list with the text of the error messages returned by parser 192 Template = [_File, _Line, _Column, Text, error], 193 findall(Text, member(Template, Messages), TextMessages), 194 % Checks if parser generated any error 195 (TextMessages \== [] -> 196 % Shows errors and then stops translation 197 forall(member(Message, TextMessages), (write(Message), nl)), 198 fail 199 ; 200 true 201 ), 202 % Converts the executable term into a string and then reads it 203 % to get the list of variable bindings 204 swritef(QueryString, '%w.', [ParsedQuery]), 205 catch(( 206 atom_to_term(QueryString, QueryTerm, AllBindings) 207 % (catcher) 208 ), _Exception, ( 209 fail 210 )), 211 % Removes bindings of unimportant variables (those starting with '_') 212 findall((VarName = Var), 213 (member((VarName = Var), AllBindings), atom_chars(VarName, ['_'|_Chars])), 214 UnimportantBindings), 215 subtract(AllBindings, UnimportantBindings, Bindings), 216 % Adds the linguistic terms found in the query to the current 217 % list of fuzzy subsets 218 add_linguistic_terms(LingTerms, AddedSubsets), 219 (AddedSubsets == [] -> 220 % All of the subsets were already on the list, no further 221 % translation is needed 222 true 223 ; 224 % New subsets were found, so new proximity/similarity equations 225 % must be computed and asserted into the SWI-Prolog database 226 translate_fuzzy_sets(AddedSubsets, Equations), 227% evaluator:add_sim_equations(Equations) 228 evaluator:update_sim_equations(Equations, Updated), 229 bplShell:reload_on_extra_equations(Equations, Updated) 230 ), 231 % Adds the computation of the approximation degree to the query 232 QueryTerm = [RealQuery, DegreeVars], 233% QueryAux = (RealQuery, min_degree(DegreeVars, Degree)), 234 QueryAux = (RealQuery, degree_composition(DegreeVars, Degree)), 235 % Translates assert/1 and retract/1 predicates 236 evaluator:get_sim_equations(CurrentEquations), 237 translate_asserts_retracts(QueryAux, Query, ProgramPrefix, CurrentEquations). 238 239 240 241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 242% Expansion of rules 243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
For example, given ProgramPrefix = 'prog', the same rule as in
the example of the 'parser' module, [(prog_a(X, DG)
:-
prog_b(X, D1)
, prog_c(D2)
, true), [D1, D2]], and the equations
[sim(a, p, 0.5)
, sim(X, X, 1)
], this predicate will return the
following set of rules:
prog_a(A1, DG)
:- unify_arguments_a1[[A1, X, DA1]]),
prog_b(X, D1)
, prog_c(D2)
, true,
min_degree([D1, D2, DA1], DG)
.
prog_p(A1, DG)
:- over_lambdacut(0.5)
,
prog_b(X, D1)
, prog_c(D2)
, true,
min_degree([D1, D2, DA1, 0.5], DG)
.
278expand_rules([], [], _ProgramPrefix, _Equations). 279 280expand_rules([[Rule, HeadConstraintBlockVars, BodyConstraintBlockVars, DegreeVars]|MoreRules], ExpandedRules, ProgramPrefix, Equations) :- 281 (Rule = (Head :- Body) -> 282 % Removes the program prefix from the rule's head 283 functor(Head, FunctorWithPrefix, _Arity), 284 atom_chars(ProgramPrefix, PrefixChars), 285 atom_chars(FunctorWithPrefix, FunctorWithPrefixChars), 286 append(PrefixChars, ['_'], PrefixChars2), 287 append(PrefixChars2, FunctorChars, FunctorWithPrefixChars), 288 atom_chars(Functor, FunctorChars), 289 % Translates the assert/1 and retract/1 predicates of the rule's body 290 (Body \== true -> 291 translate_asserts_retracts(Body, NewBody, ProgramPrefix, Equations) 292 ; 293 NewBody = true 294 ), 295 % Extracts all the symbols that are similar to this rule's head 296 findall([Sim, Degree], member(sim(Functor, Sim, Degree), Equations), List), 297 % Expands this rule using the resulting list 298 expand_rule(List, (Head :- NewBody), HeadConstraintBlockVars, BodyConstraintBlockVars, DegreeVars, ProgramPrefix, ExpandedRules1) 299 ; 300 % Rules that aren't clauses don't need expansion 301 % (note that facts must have 'true' as their body) 302 ExpandedRules1 = [Rule] 303 ), 304 % Expands the remaining rules 305 expand_rules(MoreRules, ExpandedRules2, ProgramPrefix, Equations), 306 append(ExpandedRules1, ExpandedRules2, ExpandedRules). 307 308 309expand_rule([], _Clause, _HeadConstraintBlockVars, _BodyConstraintBlockVars, _RuleDegreeVars, _ProgramPrefix, []). 310 311expand_rule([[Symbol, Degree]|MoreSimDegrees], Clause, HeadConstraintBlockVars, BodyConstraintBlockVars, RuleDegreeVars, ProgramPrefix, [ExpClause|MoreExpClauses]) :- 312 Clause = (Head :- Body), 313 % Creates the lists of variables and approximation degrees that 314 % will be used in the weak unifications of each rule's argument 315 Head =.. [_HeadFunctor|HeadArgsWithCtrsAndDegree], 316 length(HeadArgsWithCtrsAndDegree, ExtendedRuleArity), 317 actual_rule_arity(ExtendedRuleArity,RuleArity), 318 length(HeadArgs, RuleArity), 319 length(HeadVars, RuleArity), 320 length(HeadDegrees, RuleArity), 321 append(HeadArgs, CtrsAndDegreeVar, HeadArgsWithCtrsAndDegree), 322 append(_HeadCtrs,[HeadDegreeVar],CtrsAndDegreeVar), 323% init_ctr_store(HeadFunctor,Cin), 324 create_unification_problems(HeadVars, HeadArgs, HeadCin, HeadCout, HeadDegrees, UnificationProblems), 325 % Links head and body block constraints variables through the 326 % unification problems 327 link_rule_block_constraint_variables(HeadConstraintBlockVars, BodyConstraintBlockVars, HeadCin, HeadCout), 328 % Builds the new rule's head with the symbol that is similar to the 329 % original functor and the variables of the HeadVars list 330 append(HeadVars, CtrsAndDegreeVar, NewHeadArgsWithCtrsAndDegree), 331 concat_atom([ProgramPrefix, '_', Symbol], SymbolWithPrefix), 332 NewHead =.. [SymbolWithPrefix|NewHeadArgsWithCtrsAndDegree], 333 build_unify_arguments_goal(UnificationProblems,UnifyArgsGoal), 334 (Degree < 1 -> 335 % Builds the new rule's body with a check of the lambda-cut value 336 % (if needed), 337 % the weak unification of the arguments, the original body and the 338 % computation of the approximation degree 339 append(RuleDegreeVars, HeadDegrees, DegreeVarsAux), 340 append(DegreeVarsAux, [Degree], DegreeVars), 341 build_pre_over_lambda_cut_goal(Degree, PreOverLCGoal), 342 build_degree_composition_goal(DegreeVars, HeadDegreeVar, TNormGoal), 343 build_post_over_lambda_cut_goal(HeadDegreeVar, PostOverLCGoal), 344 utilities:append_goals_list([ 345 PreOverLCGoal, 346 UnifyArgsGoal, 347 Body, 348 TNormGoal, 349 PostOverLCGoal], 350 NewBody) 351 ; 352 % Builds the new rule's body with the weak unification of the 353 % arguments, the original body and the computation of the 354 % approximation degree 355 append(RuleDegreeVars, HeadDegrees, DegreeVars), 356 build_degree_composition_goal(DegreeVars, HeadDegreeVar, TNormGoal), 357 build_post_over_lambda_cut_goal(HeadDegreeVar, PostOverLCGoal), 358 utilities:append_goals_list([ 359 UnifyArgsGoal, 360 Body, 361 TNormGoal, 362 PostOverLCGoal], 363 NewBody) 364 ), 365 (NewBody==true -> 366 ExpClause = (NewHead) 367 ; 368 ExpClause = (NewHead :- NewBody) 369 ), 370 % Scans the remaining symbols 371 expand_rule(MoreSimDegrees, Clause, HeadConstraintBlockVars, BodyConstraintBlockVars, RuleDegreeVars, ProgramPrefix, 372 MoreExpClauses).
381build_unify_arguments_goal([], true) :- 382 !. 383 384build_unify_arguments_goal(UnificationProblems, UnifyArgsGoal) :- 385 flags:get_bpl_flag(weak_unification(Algorithm)), 386 atom_concat('unify_arguments_', Algorithm, GoalName), 387 UnifyArgsGoal =.. [GoalName, UnificationProblems]. 388% unify_arguments_a1(UnificationProblems)
400build_pre_over_lambda_cut_goal(_Degree, true) :- 401 flags:get_bpl_flag(filtering(true)), 402% flags:get_bpl_flag(fuzzy_logic(min)), 403 !. 404 405build_pre_over_lambda_cut_goal(Degree, over_lambdacut(Degree)).
build_degree_composition_goal([], 1, true)
:-
!.
416% build_degree_composition_goal([D], D, true) :- 417% !. 418 419build_degree_composition_goal(DegreeVars, HeadDegreeVar, degree_composition(DegreeVars, HeadDegreeVar)).
429build_post_over_lambda_cut_goal(_Degree, true) :- 430 flags:get_bpl_flag(fuzzy_logic(min)), 431 !. 432 433build_post_over_lambda_cut_goal(Degree, over_lambdacut(Degree)).
446link_rule_block_constraint_variables(HeadConstraintBlockVars, BodyConstraintBlockVars, HeadCin, HeadCout) :- 447 HeadConstraintBlockVars = [HeadCin|_], % Cin of head with Cin of unification problems 448 BodyConstraintBlockVars = [HeadCout|_], % Cout of unification problems with Cin of body 449 !, 450 append(_,[HCout],BodyConstraintBlockVars), % Cout of body with 451 append(_,[HCout],HeadConstraintBlockVars). % Cout of head 452 453% Nothing to do if the body has no constraint block variables (e.g., calls to built-ins) 454link_rule_block_constraint_variables(_HeadConstraintBlockVars, _BodyConstraintBlockVars, _HeadCin, _HeadCout).
For example, given Vars = [X, Y], Args = [a, b] and Degrees = [D1, D2], for 'a1' this predicate will return: Problems = [[X, a, D1], [Y, b, D2]], while for 'a2' and 'a3': Problems = [[X, a, Cin, C1, D1], [Y, b, C1, Cout, D2]]. where Cin and Cout are unbound variables.
477create_unification_problems(Vars, Args, _Cin, _Cout, Degrees, Goals) :- 478 flags:get_bpl_flag(weak_unification('a1')), 479 !, 480 create_unification_a1_problems(Vars, Args, Degrees, Goals). 481create_unification_problems(Vars, Args, Cin, Cout, Degrees, Goals) :- 482 create_unification_a2_a3_problems(Vars, Args, Cin, Cout, Degrees, Goals). 483 484create_unification_a1_problems([], [], [], []). 485create_unification_a1_problems([Var|MoreVars], [Arg|MoreArgs], [Degree|MoreDegrees], 486 [[Var, Arg, Degree]|MoreGoals]) :- 487 create_unification_a1_problems(MoreVars, MoreArgs, MoreDegrees, MoreGoals). 488 489create_unification_a2_a3_problems([], [], Cin, Cin, [], []). 490create_unification_a2_a3_problems([Var|MoreVars], [Arg|MoreArgs], Cin, Cout, [Degree|MoreDegrees], 491 [[Var, Arg, Cin, Cin1, Degree]|MoreGoals]) :- 492 create_unification_a2_a3_problems(MoreVars, MoreArgs, Cin1, Cout, MoreDegrees, MoreGoals). 493 494 495 496% %% link_block_constraints_variables(?LeftConstraintBlockVars, ?RightConstraintBlockVars) 497% % 498% % Links two lists of block constraints: the last variable of the left 499% % list with the first variable of the right list. 500% % 501 502% link_block_constraints_variables(LeftConstraintBlockVars, RightConstraintBlockVars) :- 503% flags:get_bpl_flag(weak_unification('a3')), 504% !, 505% append(_,[Cout],LeftConstraintBlockVars), 506% RightConstraintBlockVars=[Cout|_]. 507 508% link_block_constraints_variables(_LeftConstraintBlockVars, _RightConstraintBlockVars).
523actual_rule_arity(RuleArity, ActualRuleArity) :- 524 flags:get_bpl_flag(weak_unification('a1')), 525 !, 526 ActualRuleArity is RuleArity - 1. % The last argument is the approximation degree 527 528actual_rule_arity(RuleArity, ActualRuleArity) :- 529 ActualRuleArity is RuleArity - 3. % The last three arguments are: the input and output block constraint stores, and the approximation degree
537expanded_rule_arity(RuleArity, ExpandedRuleArity) :- 538 flags:get_bpl_flag(weak_unification('a1')), 539 !, 540 ExpandedRuleArity is RuleArity + 1. % The last argument is the approximation degree 541 542expanded_rule_arity(RuleArity, ExpandedRuleArity) :- 543 ExpandedRuleArity is RuleArity + 3. % The last three arguments are: the input and output block constraint stores, and the approximation degree 544 545 546 547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 548% Expansion of equations 549%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562expand_equations([], _Equations, []) :- 563 !. 564 565expand_equations([EqPrefix|MorePrefixes], Equations, ExpandedEquations) :- 566 % Calls this predicate recursively for each prefix 567 expand_equations(EqPrefix, Equations, ExpandedEquations1), 568 expand_equations(MorePrefixes, Equations, ExpandedEquations2), 569 append(ExpandedEquations1, ExpandedEquations2, ExpandedEquations). 570 571expand_equations(EqPrefix, Equations, ExpandedEquations) :- 572 % Extract "EqPrefix(_, _, _)" equations from list 573 atom(EqPrefix), 574 utilities:extract_terms(EqPrefix, 3, Equations, SubEquations), 575 % Computes the reflexive, transitive, and/or symmetric closure 576 flags:get_bpl_flag(relation_properties(EqPrefix, ClosureProperties)), 577 utilities:closure_properties(ClosureProperties, Closure, TNorm), 578 flags:get_bpl_flag(lambda_cut(LambdaCut)), 579 foreign:ext_closure(SubEquations, Closure, TNorm, EqPrefix, LambdaCut, 580 ExpandedEquations). 581 582 583 584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 585% Translation of assertions and retractions 586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
assert(prog_a(g, D))
" would be translated into:
"(assert((prog_a(A1, D)
:- unify_arguments_a1[[A1, g, D1]]),
true,
min_degree([D1], D)
),
assert((prog_b(A1, D)
:- over_lambdacut(0.5)
,
unify_arguments_a1[[A1, g, D1]]),
true,
min_degree([D1], D)
))"
606translate_asserts_retracts(Clause, TranslatedClause, ProgramPrefix, Equations) :-
607 % Program prefix and list of equations are saved in dynamic
608 % predicates because they're needed by the scanners called
609 % by process_term/6
610 assert(program_prefix(ProgramPrefix)),
611 assert(equations(Equations)),
612 utilities:process_term(Clause, TranslatedClause,
613 [translator:assert_translator_scanner,
614 translator:retract_translator_scanner],
615 [], _, _),
616 retract(program_prefix(ProgramPrefix)),
617 retract(equations(Equations)).
631assert_translator_scanner(Term, Asserts, _, _) :- 632 nonvar(Term), 633 Term = assert(Fact), 634 program_prefix(ProgramPrefix), 635 equations(Equations), 636 % Expands the asserted fact and creates a conjunction of 637 % assert/1 predicates with each of the returned rules 638 expand_rules([[Fact :- true, [_,_], [], []]], RulesToAssert, ProgramPrefix, Equations), 639 create_conjunction(RulesToAssert, assert, Asserts). 640 641assert_translator_scanner(Term, Term, _, _). 642 % If term isn't assert/1, it's copied as is
656retract_translator_scanner(Term, Retracts, _, _) :- 657 nonvar(Term), 658 Term = retract(Fact), 659 program_prefix(ProgramPrefix), 660 equations(Equations), 661 % Expands the retracted fact and creates a conjunction of 662 % retract/1 predicates with each of the returned rules 663 expand_rules([[Fact :- true, [_,_], [], []]], RulesToRetract, ProgramPrefix, Equations), 664 create_conjunction(RulesToRetract, retract, Retracts). 665 666retract_translator_scanner(Term, Term, _, _). 667 % If term isn't retract/1, it's copied as is
For example, given Terms = [a, b, c] and Atom = 'write', this
predicate will return Conjunction = [write(a)
, write(b)
,
write(c)
].
680create_conjunction([], _Atom, true). 681 682create_conjunction([Item|MoreItems], Atom, Terms) :- 683 SingleTerm =.. [Atom, Item], 684 create_conjunction(MoreItems, Atom, MoreTerms), 685 (MoreTerms == true -> 686 Terms = SingleTerm 687 ; 688 Terms = (SingleTerm, MoreTerms) 689 ). 690 691 692 693%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 694% Predicates for handling linguistic terms 695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714translate_fuzzy_sets([], Equations) :- 715 !, 716 findall([DomainName, Subsets], 717 flags:get_bpl_flag(fuzzy_subsets(DomainName, Subsets)), AllFuzzySets), 718 translate_fuzzy_sets_aux(AllFuzzySets, Equations). 719 720translate_fuzzy_sets(FuzzySets, Equations) :- 721 translate_fuzzy_sets_aux(FuzzySets, Equations). 722 723translate_fuzzy_sets_aux([], []). 724 725translate_fuzzy_sets_aux([[Domain, SubsetList]|MoreFuzzySets], Equations) :- 726 % Gets the domain definition and its current subsets 727 flags:get_bpl_flag(fuzzy_domain(Domain, [Min, Max, Unit])), 728 flags:get_bpl_flag(fuzzy_subsets(Domain, FullSubsetList)), 729 % Translates the subsets into a binary fuzzy relation 730 foreign:ext_translate_fuzzysets([Domain, Min, Max, Unit], FullSubsetList, 731 SubsetList, sim, DomainEquations), 732 % Scans the remaining fuzzy subsets 733 translate_fuzzy_sets_aux(MoreFuzzySets, MoreEquations), 734 append(DomainEquations, MoreEquations, Equations).
Linguistic terms built with the '#' operator can be defined in two ways:
754add_linguistic_terms(LingTerms, AddedSubsets) :-
755 linguistic_terms_to_fuzzy_subsets(LingTerms, Subsets),
756 add_fuzzy_subsets(Subsets, AddedSubsets).
769linguistic_terms_to_fuzzy_subsets([], []). 770 771linguistic_terms_to_fuzzy_subsets([[domain, DomainName, SubsetDefinition]|MoreLingTerms], Subsets) :- 772 % Ensures that the specified domain exists 773 flags:get_bpl_flag(fuzzy_domain(DomainName, [_Min, _Max, _Unit])), !, 774 % Converts the remaining linguistic terms 775 linguistic_terms_to_fuzzy_subsets(MoreLingTerms, MoreSubsets), 776 append([[DomainName, [SubsetDefinition]]], MoreSubsets, Subsets). 777 778linguistic_terms_to_fuzzy_subsets([[subset, SubsetName, SubsetDefinition]|MoreLingTerms], Subsets) :- 779 % Looks for the domain in which a subset called SubsetName is declared 780 flags:get_bpl_flag(fuzzy_subsets(DomainName, DomainSubsets)), 781 member(WantedSubset, DomainSubsets), 782 WantedSubset =.. [SubsetName|_Value], 783 % Calls the previous rule replacing subset/SubsetName with domain/DomainName 784 linguistic_terms_to_fuzzy_subsets([[domain, DomainName, SubsetDefinition]], NewSubset), 785 % Converts the remaining linguistic terms 786 linguistic_terms_to_fuzzy_subsets(MoreLingTerms, MoreSubsets), 787 append(NewSubset, MoreSubsets, Subsets). 788 789linguistic_terms_to_fuzzy_subsets([_BadLingTerm|MoreLingTerms], Subsets) :- 790 % This rule is only executed if a linguistic term has an unknown 791 % syntax or doesn't belong to any existing domain or fuzzy set 792 linguistic_terms_to_fuzzy_subsets(MoreLingTerms, Subsets).
804add_fuzzy_subsets([], []). 805 806add_fuzzy_subsets([[Domain, [SubsetDefinition]]|MoreSubsets], AddedSubsets) :- 807 % Checks if this subset is already defined 808 flags:get_bpl_flag(fuzzy_subsets(Domain, DomainSubsets)), 809 (member(SubsetDefinition, DomainSubsets) -> 810 % Subset is alredy defined 811 true, 812 Added = [] 813 ; 814 % Adds the new subset to the lists of subsets of the domain 815 append(DomainSubsets, [SubsetDefinition], NewDomainSubsets), 816 Added = [[Domain, [SubsetDefinition]]], 817 % Updates the fuzzy subsets of the domain 818 flags:remove_bpl_flag(fuzzy_subsets(Domain, DomainSubsets)), 819 flags:add_bpl_flag(fuzzy_subsets(Domain, NewDomainSubsets)) 820 ), 821 % Adds the remaining fuzzy subsets 822 add_fuzzy_subsets(MoreSubsets, MoreAdded), 823 append(Added, MoreAdded, AddedSubsets). 824 825 826 827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 828% Auxiliary dynamic predicates 829%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
839:- dynamic program_prefix/1.
849:- dynamic equations/1.