/* A converter for transforming the problem format XCSP 2.1 into B-Prolog */ /* by Neng-Fa Zhou, Last updated, January 2, 2008. */ %:-set_prolog_flag(gc_threshold,20000). :-op(1050,xfy,':'). % needed for version B-Prolog 7.4 and up main:- get_main_args(L), process_args(L,BaseName), xcsp2pl(BaseName). process_args([],_InFile):-true : format("usage: convert FileName",[]),halt. process_args([BaseName|_],BaseName1):-true : BaseName1=BaseName. convert(File):- xcsp2pl(File). xcsp2pl(File):- %File is a base name cputime(ConvStart), writeln(user,'c converting'(File)), atom_codes(File,MainString), append(MainString,".xml",InFileString), atom_codes(InFile,InFileString), append(MainString,".pl",OutFileString), atom_codes(OutFile,OutFileString), (exists(InFile)->true;format("File not found:~w~n",[InFile]),halt), see(InFile), tell(OutFile), process_xcsp_xml, seen,told, cputime(ConvEnd), ConvTime is ConvEnd-ConvStart, format("c Converted in ~w ms~n",[ConvTime]). process_xcsp_xml:- writeln('csp(Vs):-'), read_next_key_token(Token), process_sections(Token,_Preds), writeln('true.'). process_sections(Token,_Preds):-var(Token) : true. % end-of-file process_sections(presentation,Preds):-true : b_NEXT_TOKEN_ff(_,Token), skip_presentation(Token), read_next_key_token(KeyToken), process_sections(KeyToken,Preds). process_sections(domain,Preds):-true : not(not(process_domain)), read_next_key_token(KeyToken), process_sections(KeyToken,Preds). process_sections(variable,Preds):-true : process_variables([],Preds). process_sections(relation,Preds):-true : not(not(process_relation)), read_next_key_token(KeyToken), process_sections(KeyToken,Preds). process_sections(predicate,Preds):-true : process_predicate(Preds), read_next_key_token(KeyToken), process_sections(KeyToken,Preds). process_sections(constraint,Preds):-true : closetail(Preds), not(not(process_constraint(Preds))), read_next_key_token(KeyToken), process_sections(KeyToken,Preds). skip_presentation(' true; skip_presentation(Token)). skip_presentation('/>'):-true : true. skip_presentation(_):-true : b_NEXT_TOKEN_ff(_,Token), skip_presentation(Token). process_variables(Vars,Preds):- process_variable(Var), Vars1=[Var|Vars], read_next_key_token(KeyToken), (KeyToken==variable-> process_variables(Vars1,Preds); reverse(Vars1,Vars2), format("Vs=[~@],~n",[output_vars(Vars2)]), process_sections(KeyToken,Preds)). %%%% process_domain:- b_NEXT_TOKEN_ff(_,AName), % name process_attrs(AName,Attrs,NextToken), assoc_member(name,NameCodes,Attrs), format("D~s=[",[NameCodes]), process_dom_items(NextToken,_IsFirst), skip1(domain). process_dom_items('-',IsFirst):-true : b_NEXT_TOKEN_ff(_,Token), % must be an int Token1 is -Token, process_dom_items(Token1,IsFirst). process_dom_items('+',IsFirst):-true : b_NEXT_TOKEN_ff(_,Token), % must be an int process_dom_items(Token,IsFirst). process_dom_items('..-',IsFirst):-true : b_NEXT_TOKEN_ff(_,Token), % must be an int Token1 is -Token, writename(' .. '), writename(Token1), b_NEXT_TOKEN_ff(_,NToken), process_dom_items(NToken,IsFirst). process_dom_items('..+',IsFirst):-true : b_NEXT_TOKEN_ff(_,Token), % must be an int writename(' .. '), writename(Token), b_NEXT_TOKEN_ff(_,NToken), process_dom_items(NToken,IsFirst). process_dom_items('..',IsFirst):-true : b_NEXT_TOKEN_ff(_,Token), % must be an int writename(' .. '), writename(Token), b_NEXT_TOKEN_ff(_,NToken), process_dom_items(NToken,IsFirst). process_dom_items(Elm,IsFirst):-integer(Elm) : (var(IsFirst)->IsFirst=0;write(',')), writename(Elm), b_NEXT_TOKEN_ff(_,NToken), process_dom_items(NToken,IsFirst). process_dom_items(_Token,_IsFirst):-true : writename(']'),writename(','),nl. %%%% process_variable(Var):- b_NEXT_TOKEN_ff(_,AName), process_attrs(AName,Attrs,_NextToken), assoc_member(name,VNameCodes,Attrs), assoc_member(domain,DNameCodes,Attrs), atom_codes(Var,VNameCodes), format("V~s :: D~s,~n",[VNameCodes,DNameCodes]). %%%% process_relation:- b_NEXT_TOKEN_ff(_,AName), process_attrs(AName,Attrs,NextToken1), assoc_member(name,RNameCodes,Attrs), assoc_member(arity,ArityCodes,Attrs), assoc_member(semantics,Semantics,Attrs), (Semantics=="supports"->Type=sr;Type=cr), format("~w(R~s,~s,[",[Type,RNameCodes,ArityCodes]), process_tuples(NextToken1,NextToken2,_), writeln(']),'), (NextToken2='/>'-> (b_NEXT_TOKEN_ff(_,'true;true); skip1(relation)). % handle empty relation % % nonempty 12 12 process_tuples('-',NToken,IsFirstTuple):-true : b_NEXT_TOKEN_ff(_,Token1), % must be an integer Token2 is -Token1, process_tuples(Token2,NToken,IsFirstTuple). process_tuples('+',NToken,IsFirstTuple):-true : b_NEXT_TOKEN_ff(_,Token1), % must be an integer process_tuples(Token1,NToken,IsFirstTuple). process_tuples(Token,NToken,IsFirstTuple):-integer(Token) : (var(IsFirstTuple)->IsFirstTuple=0;writename(',')), process_tuple(Token,Token1,_), process_tuples(Token1,NToken,IsFirstTuple). process_tuples('|',NToken,IsFirstTuple):-true : b_NEXT_TOKEN_ff(_,Token), process_tuples(Token,NToken,IsFirstTuple). process_tuples(Token,NToken,_IsFirstTuple):-NToken=Token. process_tuple('-',NToken,IsFirstElm):-true : b_NEXT_TOKEN_ff(_,Token1), % must be an integer Token2 is -Token1, process_tuple(Token2,NToken,IsFirstElm). process_tuple('+',NToken,IsFirstElm):-true : b_NEXT_TOKEN_ff(_,Token1), % must be an integer process_tuple(Token1,NToken,IsFirstElm). process_tuple(Token,NToken,IsFirstElm):-integer(Token) : (var(IsFirstElm)->writename('t('),IsFirstElm=0;writename(',')), writename(Token), b_NEXT_TOKEN_ff(_,Token1), process_tuple(Token1,NToken,IsFirstElm). process_tuple(Token,NToken,_IsFirstElm):-true : NToken=Token, writename(')'). %%%% process_constraint(Preds):- b_NEXT_TOKEN_ff(_,AName), process_attrs(AName,Attrs,NextToken), assoc_member(scope,Scope,Attrs), assoc_member(reference,RefCodes,Attrs), process_constraint(RefCodes,Scope,Preds,NextToken). process_constraint("global:allDifferent",Scope,_Preds,NextToken):-true : tokenize(Scope,ActualArgs), format("call_all_distinct([~@]),~n",[output_vars(ActualArgs)]), (NextToken=='/>'->true;skip1(constraint)). process_constraint("global:alldifferent",Scope,Preds,NextToken):-true : process_constraint("global:allDifferent",Scope,Preds,NextToken). process_constraint("global:cumulative",_Scope,_Preds,_):-true : 'skip_until>'(_,PToken), % process_cumulative_params(PToken,Os,Ds,Es,Hs,Limit), format("call_cumulative([~@],[~@],[~@],[~@],~w),~n",[output_args(Os),output_args(Ds),output_args(Es),output_args(Hs),Limit]), skip1(constraint). process_constraint("global:element",_Scope,_Preds,_):-true : 'skip_until>'(_,IToken), % I read_int_or_id(IToken,I), b_NEXT_TOKEN_ff(_,PToken), % process_element_params(PToken,As), % [A1,...,An] b_NEXT_TOKEN_ff(_,VToken), % V read_int_or_id(VToken,V), format("call_element(~@,[~@],~@),~n",[output_arg(I),output_args(As),output_arg(V)]), skip1(constraint). process_constraint("global:weightedSum",_Scope,_Preds,_):-true : 'skip_until>'(_,PToken), % process_sum_params(PToken,Coes,Vs,Rel,Rhs), format("call_weightedSum([~@],[~@],~w,~w),~n",[output_args(Coes),output_args(Vs),Rel,Rhs]), skip1(constraint). process_constraint("global:weightedsum",_Scope,_Preds,_):-true : 'skip_until>'(_,PToken), % process_sum_params(PToken,Coes,Vs,Rel,Rhs), format("call_weightedSum([~@],[~@],~w,~w),~n",[output_args(Coes),output_args(Vs),Rel,Rhs]), skip1(constraint). process_constraint(RefCodes,Scope,Preds,_):- true ? % predicate, must exist member(pred(RefCodes,FormalArgs,Body),Preds),!, tokenize(Scope,ScopeVars), writename('constr_scope(['),output_vars(ScopeVars),writename(']),'),nl, b_NEXT_TOKEN_ff(_,_), % 'skip_until>'(_,PToken), % process_actual_params(PToken,ActualArgs), copy_term((FormalArgs,Body),(FormalArgsCp,BodyCp)), ActualArgs=FormalArgsCp, output_constrs(BodyCp), skip1(constraint). process_constraint(RefCodes,Scope,_Preds,NextToken):-true : % extension tokenize(Scope,ActualArgs), format("ec(R~s,~@),~n",[RefCodes,output_vars_tuple(ActualArgs)]), (NextToken=='/>'->true;skip1(constraint)). process_actual_params(' process_cumulative_param(Token,A):-true : read_int_or_id(Token,A). process_element_params('[',As):-true : b_NEXT_TOKEN_ff(_,Token), process_element_params(Token,As). process_element_params(']',As):-true : As=[]. process_element_params(AToken,As):-true : As=[A|As1], read_int_or_id(AToken,A), b_NEXT_TOKEN_ff(_,NToken), process_element_params(NToken,As1). process_sum_params('[',Coes,Vs,Rel,Rhs):-true : b_NEXT_TOKEN_ff(_,Token), process_sum_params(Token,Coes,Vs,Rel,Rhs). process_sum_params(']',Coes,Vs,Rel,Rhs):-true : Coes=[],Vs=[], b_NEXT_TOKEN_ff(_,_), %< b_NEXT_TOKEN_ff(_,Rel), b_NEXT_TOKEN_ff(_,_), %/> b_NEXT_TOKEN_ff(_,RhsToken), read_int_or_id(RhsToken,Rhs). process_sum_params('{',Coes,Vs,Rel,Rhs):-true : Coes=[Coe|Coes1], Vs=[V|Vs1], b_NEXT_TOKEN_ff(_,CoeToken), read_int_or_id(CoeToken,Coe), b_NEXT_TOKEN_ff(_,V), b_NEXT_TOKEN_ff(_,_), % } b_NEXT_TOKEN_ff(_,Token), process_sum_params(Token,Coes1,Vs1,Rel,Rhs). %%%% process_predicate(Preds):- b_NEXT_TOKEN_ff(_,AName), process_attrs(AName,Attrs,_NextToken), assoc_member(name,PNameCodes,Attrs), 'skip_until>'(_,PToken), % process_formal_params(PToken,PredArgs,ArgsTab), skip2(expression,'>'), skip1(functional), 'skip_until>'(Type,EToken), read_expression_tokens(Type,EToken,ETokens), process_expression(ETokens,Constr,ArgsTab), attach(pred(PNameCodes,PredArgs,Constr),Preds), skip2(predicate,'>'). process_formal_params('Constr2). process_bool_exp([eq,'('|Tokens],TokensR,Constr,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Constr=(Exp1 #= Exp2). process_bool_exp([ne,'('|Tokens],TokensR,Constr,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Constr=(Exp1 #\= Exp2). process_bool_exp([ge,'('|Tokens],TokensR,Constr,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Constr=(Exp1 #>= Exp2). process_bool_exp([gt,'('|Tokens],TokensR,Constr,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Constr=(Exp1 #> Exp2). process_bool_exp([le,'('|Tokens],TokensR,Constr,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Constr=(Exp1 #=< Exp2). process_bool_exp([lt,'('|Tokens],TokensR,Constr,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Constr=(Exp1 #< Exp2). process_int_exp([neg,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[')'|TokensR], Exp=(-Exp1). process_int_exp([abs,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[')'|TokensR], Exp=abs(Exp1). process_int_exp([add,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Exp=(Exp1+Exp2). process_int_exp([sub,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Exp=(Exp1-Exp2). process_int_exp([mul,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Exp=(Exp1*Exp2). process_int_exp([div,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Exp=(Exp1//Exp2). process_int_exp([mod,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Exp=(Exp1 mod Exp2). process_int_exp([pow,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Exp=(Exp1 ** Exp2). process_int_exp([min,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Exp=min(Exp1,Exp2). process_int_exp([max,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_int_exp(Tokens,Tokens1,Exp1,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp2,ArgsTab), Tokens3=[')'|TokensR], Exp=max(Exp1,Exp2). process_int_exp([if,'('|Tokens],TokensR,Exp,ArgsTab):-true : process_bool_exp(Tokens,Tokens1,Cond,ArgsTab), Tokens1=[','|Tokens2], process_int_exp(Tokens2,Tokens3,Exp1,ArgsTab), Tokens3=[','|Tokens4], process_int_exp(Tokens4,Tokens5,Exp2,ArgsTab), Tokens5=[')'|TokensR], Exp=if(Cond,Exp1,Exp2). process_int_exp(['-',Token|Tokens],TokensR,Exp,_ArgsTab):-integer(Token) : Exp is -Token, Tokens=TokensR. process_int_exp(['+',Token|Tokens],TokensR,Exp,_ArgsTab):-integer(Token) : Exp is Token, Tokens=TokensR. process_int_exp([Token|Tokens],TokensR,Exp,_ArgsTab):-integer(Token) : Exp=Token, Tokens=TokensR. process_int_exp([Token|Tokens],TokensR,Exp,ArgsTab):-true : Tokens=TokensR, member(arg(Token,Exp),ArgsTab),!. %%%% process_attrs('>',Attrs,NextToken):-true : Attrs=[],b_NEXT_TOKEN_ff(_,NextToken). process_attrs('>+',Attrs,NextToken):-true : Attrs=[],NextToken='+'. process_attrs('>-',Attrs,NextToken):-true : Attrs=[],NextToken='-'. process_attrs('/>',Attrs,NextToken):-true : Attrs=[],NextToken='/>'. process_attrs(AName,Attrs,NextToken):-true : b_NEXT_TOKEN_ff(_,_), % = b_NEXT_TOKEN_ff(_,Val), (atom(Val)->atom_codes(Val,Value); integer(Val)->number_codes(Val,Value); Value=Val), Attrs=[AName=Value|Attrs1], b_NEXT_TOKEN_ff(_,AName1), process_attrs(AName1,Attrs1,NextToken). %%%% 'skip_until>'(Type,Token):- b_NEXT_TOKEN_ff(_,Token1), 'skip_until>'(Token1,Type,Token). 'skip_until>'('>',Type,Token):-true : b_NEXT_TOKEN_ff(Type,Token). 'skip_until>'('>+',Type,Token):-true : Type=4,Token='+'. 'skip_until>'('>-',Type,Token):-true : Type=4,Token='-'. 'skip_until>'(_,Type,Token):-true : b_NEXT_TOKEN_ff(_Type1,Token1), 'skip_until>'(Token1,Type,Token). skip1(Token):- b_NEXT_TOKEN_ff(_,CurToken), skip1(Token,CurToken). skip1(Token,Token):-true : true. skip1(Token,_):-true : b_NEXT_TOKEN_ff(_,CurToken), skip1(Token,CurToken). skip2(Token1,Token2):- b_NEXT_TOKEN_ff(_,CurToken), skip2(Token1,Token2,CurToken). skip2(Token1,Token2,Token1):-true : b_NEXT_TOKEN_ff(_,CurToken), (CurToken==Token2 -> true; skip2(Token1,Token2,CurToken)). skip2(Token1,Token2,_):-true : b_NEXT_TOKEN_ff(_,CurToken), skip2(Token1,Token2,CurToken). read_next_key_token(KeyToken):- b_NEXT_TOKEN_ff(_, Token), (key_token(Token)-> KeyToken=Token; read_next_key_token(KeyToken)). read_int_or_id('+',Val):-true : b_NEXT_TOKEN_ff(_, Val). % integer read_int_or_id('-',Val):-true : b_NEXT_TOKEN_ff(_, Val1), Val is -Val1. read_int_or_id(Token,Val):-true : Val=Token. key_token(EndOfFile):-var(EndOfFile) : true. key_token(domain):-true : true. key_token(variable):-true : true. key_token(relation):-true : true. key_token(predicate):-true : true. key_token(constraint):-true : true. key_token(presentation):-true : true. %%%% tokenize([],Tokens):-true : Tokens=[]. tokenize([Code|Codes],Tokens):-true ? is_space(Code),!, tokenize(Codes,Tokens). tokenize([Code|Codes],Tokens):-true ? is_delimeter(Code),!, char_code(Token,Code), Tokens=[Token|TokensR], tokenize(Codes,TokensR). tokenize([Code|Codes],Tokens):-true : extract_token(Codes,Name,CodesR), name(Token,[Code|Name]), Tokens=[Token|TokensR], tokenize(CodesR,TokensR). extract_token([],Name,CodesR):-true : Name=[],CodesR=[]. extract_token([Code|Codes],Name,CodesR):-true ? is_space(Code),!, Name=[], CodesR=Codes. extract_token(Codes,Name,CodesR):-Codes=[Code|_] ? is_delimeter(Code),!, Name=[], CodesR=Codes. extract_token([Code|Codes],Name,CodesR):-true : Name=[Code|NameR], extract_token(Codes,NameR,CodesR). :-mode is_space(+). is_space(0' ). is_space(9). % tab is_space(10). is_space(13). :-mode is_delimeter(+). is_delimeter(0'(). is_delimeter(0')). is_delimeter(0',). is_delimeter(0'.). is_delimeter(0'|). output_vars([]):-true : true. output_vars([V|Vs]):-true : (V=='_$dummy'->writename('_');writename('V'),writename(V)), (Vs==[]->true; writename(','), output_vars(Vs)). output_vars_tuple(Tuple):-true : writename('t('), output_vars_tuple_rest(Tuple). output_vars_tuple_rest([V]):-true : writename('V'),writename(V),writename(')'). output_vars_tuple_rest([V|Vs]):-true : writename('V'),writename(V),writename(','), output_vars_tuple_rest(Vs). output_constrs([]):-true : true. output_constrs([Constr|Constrs]):- write(Constr),writename(','),nl, output_constrs(Constrs). output_args([]):-true : true. output_args([V|Vs]):-true : output_arg(V), (Vs==[]->true; writename(','), output_args(Vs)). output_arg('_$dummy'):-true : writename('_'). output_arg(Arg):-integer(Arg) : writename(Arg). output_arg(Arg):-true : writename('V'),writename(Arg). %%%%% assoc_member(AName,AVal,[AName=AVal1|_]):-true : AVal=AVal1. assoc_member(AName,AVal,[_|L]):-true : assoc_member(AName,AVal,L).