% rationals, .... % this is less than the least efficient implementation % rationals_division/3, rationals_add_list/2, % rationals_addition/3, rationals_cutoff/2, rationals_is_rat/2. % rationals_hyphened_product_sum_list/4, rationals_multiplication/3. % Should have two version for the operations, % one with and one without simlification, % agrregates calling the not simplifying operation. rationals_division( NomNom/NomDnm, DnmNom/DnmDnm, Simplified ) :- long_int_times( NomNom, DnmDnm, ResNom ), long_int_times( NomDnm, DnmNom, ResDnm ). % ResNom is NomNom * DnmDnm, % ResDnm is NomDnm * DnmNom, rationals_simplify( ResNom/ResDnm, Simplified ). rationals_multiplication( Nom1/Dnm1, Nom2/Dnm2, Simplified ) :- long_int_times( Nom1, Dnm1, ResNom ), long_int_times( NomNom, DnmDnm, ResNom ), % ResNom is Nom1 * Nom2, % ResDnm is Dnm1 * Dnm2, % ( (\+integer(ResNom);\+integer(ResDnm)) -> % then we have an overflow % Goal = rationals_multiplication( Nom1/Dnm1, Nom2/Dnm2, Simplified ), % throw( pfd(rats(int_overflow(ResNom,ResDnm),Goal)) ) % ; % true % ), % !, rationals_simplify( ResNom/ResDnm, Simplified ). % rationals_multiplication_wo( Nom1/Dnm1, Nom2/Dnm2, Simplified ) :- % ResNom is Nom1 * Nom2, % % ResDnm is Dnm1 * Dnm2, % ( (\+integer(ResNom);\+integer(ResDnm)) -> % % then we have an overflow % trace, % ( ResNom < ResDnm -> % CrDnm is integer(ResDnm/ResNom), % Simplified = 1 / CrDnm % ; % CrNom is integer(ResNom/ResDnm), % Simplified = CrNom / 1 % ) % ; % rationals_simplify( ResNom/ResDnm, Simplified ) % ), % !. rationals_addition( LNom/LDnm, RNom/RDnm, Simplified ) :- rationals_lcd_factors( LDnm, RDnm, ResDnm, LFctr, RFctr ), long_int_times( LNom, LFctr, Prd1 ), long_int_times( RNom, RFctr, Prd2 ), long_int_plus( Prd1, Prd2, ResNom ), % ResNom is LNom * LFctr + RNom * RFctr, rationals_simplify( ResNom/ResDnm, Simplified ). % maybe there is something simpler in this case. rationals_subtraction( LNom/LDnm, RNom/RDnm, Simplified ) :- rationals_lcd_factors( LDnm, RDnm, ResDnm, LFctr, RFctr ), long_int_times( LNom, LFctr, Prd1 ), long_int_times( RNom, RFctr, Prd2 ), long_int_minus( Prd1, Prd2, ResNom ), % ResNom is LNom * LFctr - RNom * RFctr. rationals_simplify( ResNom/ResDnm, Simplified ). % rationals_sign_normalise( ResNom, ResDnm, Quotient ). rationals_sign_normalise( Nom, Dnm, Quotient ) :- ( Dnm < 0 -> ( Nom < 0 -> AbsNom is abs(Nom), AbsDnm is abs(Dnm), Quotient = AbsNom / AbsDnm ; AbsDnm is abs(Dnm), Quotient = ( - Nom / AbsDnm ) ) ; Quotient = Nom / Dnm ). rationals_subtract_this_list( [], _This, [] ). rationals_subtract_this_list( [H|T], This, [SH|ST] ) :- rationals_subtraction( H, This, SH ), rationals_subtract_this_list( T, This, ST ). rationals_all_multiply_list( [], _Nom/_Dnm, [] ). rationals_all_multiply_list( [H|T], Multi, [MTH|MsTT] ) :- rationals_multiplication( H, Multi, MTH ), rationals_all_multiply_list( T, Multi, MsTT ). % rationals_add_list( [], 0/1 ). % double check that this is ok rationals_add_list( [H], H ) :- !. rationals_add_list( [H|T], Res ) :- rationals_add_list( T, H, Res ). rationals_add_list( [], Ans, Ans ). % rationals_simplify( Ans, Simplified ). rationals_add_list( [H|T], Acc, Res ) :- rationals_addition( H, Rat, Acc, NewAcc ), rationals_add_list( T, NewAcc, Res ). rationals_multiply_list( List, Result ) :- rationals_multiply_list( List, 1/1, Result ). rationals_multiply_list( [], Acc, Acc ). rationals_multiply_list( [H|T], Acc, Res ) :- rationals_multiplication( Acc, H, NewAcc ), rationals_multiply_list( T, NewAcc, Res ). rationals_lcd_factors( NatOne, NatTwo, LCD, OneFact, TwoFact ) :- gcd( NatOne, NatTwo, GCD ), OneFact is NatTwo // GCD, TwoFact is NatOne // GCD, LCD is OneFact * TwoFact * GCD. rationals_hyphened_product_sum_list( HList, LList, RList, PrSum ) :- rationals_hyphened_product_sum_list_1( HList, 0/1, LList, RList, PrSum ). rationals_hyphened_product_sum_list_1( [LH-RH|T], Acc, [LH|LT], [RH|RT], PS ) :- rationals_multiplication( LH, RH, Product ), rationals_addition( Product, Acc, NewAcc ), rationals_hyphened_product_sum_list_1( T, NewAcc, LT, RT, PS ). rationals_hyphened_product_sum_list_1( [], Res, [], [], Res ). rationals_cutoff( excl(Numb1), Numb2 ) :- !, rationals_cutoff_1( Numb1, Numb2, excl ). rationals_cutoff( incl(Numb1), Numb2 ) :- !, rationals_cutoff_1( Numb1, Numb2, incl ). rationals_cutoff( Numb1, Numb2 ) :- rationals_cutoff_1( Numb1, Numb2, incl ). rationals_cutoff_1( MayRat1, MayRat2, ExInCl ) :- rationals_is_rat( MayRat1, Nom1/Den1 ), rationals_is_rat( MayRat2, Nom2/Den2 ), FactNom is Nom1 * Den2, FactDen is Den1 * Nom2, ( FactNom > FactDen -> true ; rationals_cutoff_eq( ExInCl, FactNom, FactDen ) ). rationals_cutoff_eq( incl, Fact, Fact ). rationals_is_rat( Var, Var ) :- var(Var),!. rationals_is_rat( Nom/Den, Nom/Den ) :- !. rationals_is_rat( 0, 0/1 ) :- !. rationals_is_rat( 1, 1/1 ). rationals_simplify( Nom/Dnm, SNom/SDnm ) :- gcd( Nom, Dnm, Gcd ), SNom is Nom // Gcd, SDnm is Dnm // Gcd. % rationals_iinv( Nom/Dnm, 1/Dnm % rationals_abs_list % assume negative Rats have sign at the Nominator. % no Rat is allowed with negative signs on both the % Nominator and Denominator. % rationals_abs_list( [], [] ). rationals_abs_list( [Nom/Dnm|T], [AbsH|AbsT] ) :- ( Nom < 0 -> AbsNom is abs(Nom), AbsH = AbsNom / Dnm ; ( Nom = 0 -> write( error(division_by_zero,rationals_abs_list/2) ), nl, abort ; AbsH = Nom / Dnm ) ), rationals_abs_list( T, AbsT ). rationals_integer_to( Int, Int/1 ). rationals_invert_approx_list( [], [] ). rationals_invert_approx_list( [Nom/Dnm|T], [NNm/1|NT] ) :- ( Nom > 0 -> NNm is integer( (Dnm / Nom) ) ; ( Nom = 0 -> Error = division_by_zero_while_inverting, Clause= rationals_invert_approx_list( [Nom/Dnm|T], [NNm/1|NT] ), throw( pfd(rats(Error,Clause)) ) ; NNm is - integer( Dnm / Dnm ) ) ), rationals_invert_approx_list( T, NT ). rationals_invert_list( [], [] ). rationals_invert_list( [Nom/Dnm|T], [NNm/NDm|NT] ) :- ( Nom > 0 -> NNm = Dnm, NDm = Nom ; ( Nom = 0 -> write( error(division_by_zero,rationals_invert_list/2) ), nl, abort ; NNm = - Dnm, NDm = Nom ) ), rationals_invert_list( T, NT ). gcd( M, N, C ) :- ( N =:= 0 -> C is M ; NewN is M mod N, gcd( N, NewN, C ) ). % probability_measure_constraint( Constr, MethPrbs, ConstrProb, Measrs ) :- rationals_to_probabilities( Rats, Probs ) :- rationals_add_list( Rats, Sum ), rationals_invert_list( [Sum], [MUs] ), rationals_all_multiply_list( Rats, MUs, Probs ). measure_constraint( MethPrbs, ConstrProb, Measrs ) :- rationals_all_multiply_list( MethPrbs, ConstrProb, Measrs ). is_only_rational( Rat, Goal, ArgNo ) :- ( var(Rat) -> print_message( error, domain_error(Goal,ArgNo,ratinal-(IntP/IntQ),Rat) ) ; (Rat = _Nmn/_Dnm -> true ; print_message( error, domain_error(Goal,ArgNo,ratinal-(IntP/IntQ),Rat) ) ) ). rationals_is_wo( Nom/Dnm, Nom/Dnm ) :- !. rationals_is_wo( Float, Rat ) :- ( Float > 1 -> Rat = Integer, % then we have an overflow trace, ( ResNom < ResDnm -> CrDnm is integer(ResDnm/ResNom), Simplified = 1 / CrDnm ; CrNom is integer(ResNom/ResDnm), Simplified = CrNom / 1 ) ;