taxes.txt

来自「prolog开发工具」· 文本 代码 · 共 518 行 · 第 1/2 页

TXT
518
字号
 sum_lines(1040,['6a','6b','6c'],X).

The income calculations on form 1040 show how calculations 
from different forms are tied together.  In this case data is 
drawn in from schedules B and C.

line(1040,7,'wages salaries etc',X) :-
 wages(X).
line(1040,8,'interest income',X) :-
 getl(b,3,X).
line(1040,13,'business profit or loss',X) :-
 getl(c,31,X).
line(1040,22,'total income',X) :-
 sum_lines(1040,[7,8,13], X).

The following rules from the adjusted income section of 1040 
and the medical deductions for schedule A, show how straight 
forwardly Prolog represents some confusing intertwined tax 
code.  The rule is, you can deduct the minimum of either: 25% 
of your health insurance, or your income from a business from 
taxable income.  However, if you take a deduction on line 
1040 - 25, then you must not include that amount in schedule 
A.

line(1040,25,'health insurance',X) :-
 health_insurance(A),
 B is integer( 0.25 * A + 0.5 ),
 getl(c,31,C),
 minimum([B,C],X).
line(1040,30,'adjusted gross income',X) :-
 line_dif(1040,22,25,X).

line(a,2,'medical fees',X) :-
  medical_fees(A),
  getl(1040,25,B),
  X is A - B.
line(a,3,'7.5% of income',X) :-
  getl(1040,31,A),
  X is integer(0.075 * A + 0.5).
line(a,4,'total medical',X) :-
  line_dif(a,2,3,X).

Here is the code that calls schedule A to get itemized 
deductions, calculates the appropriate standard deduction, 
and makes the right decision on which to use for the tax 
form.

line(1040,'33a','itemized deductions',X) :- 
  getl(a,26,X).
line(1040,'33b','standard deduction',2540) :- 
  status(single).
line(1040,'33b','standard deduction',3760) :- 
  status(married_joint).
line(1040,'33b','standard deduction',1880) :- 
  status(married_separate).
line(1040,34,'less itemized deductions',X) :-
  getl(1040,'33a',A),
  getl(1040,'33b',B),
  A > B,
  line_dif(1040,31,'33a',X), !.
line(1040,34,'less standard deductions',X) :-
  line_dif(1040,31,'33b',X).

The tax computation is done by another predicate which knows 
how to build tax tables.  It breaks income into a step 
function in $50 increments and uses the formulas for the 
midpoints of the steps.  An excerpt is included here:

line(1040,37,'tax computation',X) :-
 getl(1040,36,A),
 compute_tax(A,X).

compute_tax(A,Tax) :-    % adjust for tax table calc
 B is integer(A / 50),
 C is B * 50 + 25,
 comput_tax(C,Tax).

comput_tax(A,Tax) :-
 status(single),
 rate_single(A,T), !,
 Tax is integer(T + 0.5).

rate_single(A,T) :-
 A =< 1800,
 T is 0.11 * A.
rate_single(A,T) :-
 A =< 16800,
 T is 198 + 0.15 * (A - 1800).

Some forms require tabular information to be filled in on the 
form.  So far, the tax program does not handle this case.  To 
include it, certain lines have as their value a Prolog data 
structure of the form table(TableName).  TableName is the 
name of a predicate in the data section which will write the 
required table.  The report predicate calls TableName when 
it encounters this type of value.

For example, on schedule B - 2, you must list all of the 
banks you earned interest from.  The clause for line B-2 has 
as its value table(int_inc_tab).  This means there is a 
predicate int_inc_tab in the database which displays the 
banks and interest.

line(b,2,'interest accounts',table(int_inc_tab)).
line(b,3,'total interest income',X) :-
 getl(b,2,_),
 interest_income(X).

The report predicate is modified to call a predicate 
process to deal with the Value.  If  Value is a structure 
of the form table(T), then the predicate T is called.  
Otherwise the Value is printed as before.

report(Form) :-
 nl,
 write('----- '),write(Form),write(' -----'),nl,nl,
 lin(Form,Line,Desc,Value),
 process(Line,Desc,Value),
 fail.
report(_).

process(Line,Desc,table(T)) :-
 write(Line),
 tabto(5),write(Desc),nl,
 T, !.
process(Line,Desc,Amount) :-
 write(Line),
 tabto(5),write(Desc),
 tabto(45),write(Amount),nl.

Next let's look at the data portion of the program.  On the 
fantasy form we saw how simple data such as wages and 
withheld are stored in the data section.  Let's look now at 
the messy case of interest income.    With the Prolog 
database, the data need not just contain data, but can 
contain rules as well.

Besides having to provide a table, interest income is further 
complicated in Taxachusetts by the necessity of having to 
distinguish between interest from Massachusetts banks and 
non-Massachusetts banks.  However, the tax form program is 
unaware of the underlying complexity and simply goes to the 
database for int_inc_tab and interest_income.  It does not 
know if these are simple facts, or more complex rules.

% ----- data for schedule b -----

interest_income(Z) :-
 mass_interest_income(X),
 non_mass_interest_inc(Y),
 Z is X + Y.

int_inc_tab :-
 get_int_inc(Account,Amount),
 tabto(5),write(Account),write(':'),
 tabto(40),write(Amount),nl,
 fail.
int_inc_tab.

%   ---

mass_interest_income(X) :-
 bagof(A,T^int_inc(T,A),L),
 list_sum(L,X).

non_mass_interest_inc(X) :-
 bagof(A,T^non_mass_int_inc(T,A),L),
 list_sum(L,X).

get_int_inc(Acc,Am) :- int_inc(Acc,Am).
get_int_inc(Acc,Am) :- non_mass_int_inc(Acc,Am).

int_inc('first bank',186).
int_inc('second bank',170).
int_inc('wife''s checking',79) :- 
  status(married_joint).
int_inc('wife''s savings',721) :- 
  status(married_joint).
 
non_mass_int_inc('other bank',812) :-  
  status(married_joint).

The bagof predicate is used to assemble the separate clauses 
into a list.  It is a built-in predicate of Prolog which 
was used for this program, but most Prolog's have a similar 
predicate, usually findall.  (If not, Programming in Prolog 
by Clocksin & Mellish has the code for writing your own.)

Notice how even the data can have rules associated with it.  
Some of the int_inc clauses will be included only if the 
filing status is married_joint.

It is useful in the data section to distinguish between those 
predicates which are required by the tax form predicates, and 
those which support other data predicates.  This way there 
are no errors when the data is replaced since it is clear 
which data predicates need to have a value.

The data section is especially useful for keeping track of 
business expenses.  Again the data contains the rules for the 
specific case.  In my case I use 1/7 of my apartment for my 
home business.   This figure is built into the rules which 
calculate the utility expense which winds up as a line item 
on schedule C.  For next year I simply need to plug in the 
new values for the electric bills.  This data could also have 
been saved in the separate clause format used for interest 
income if preferred.

utils(XX) :-
 phone(A),
 gas_total(B),
 elec_total(C),
 oil_total(D),
 X is A + (B + C + D) / 7,
 XX is integer(X + 0.5).

elec_total(X) :-
 elec(L),
 list_sum(L,X).

elec([30,59,42,22,34,30,40,34]).


Conclusions

Prolog's use of logic to express programming constructs is 
exceptionally well suited to financial applications.  This is 
due to the fact that financial applications are made up of 
rules for relating data.  This is exactly the paradigm that 
Prolog uses.

In the case of a tax program, the advantage is even more 
significant.  The tax law is made up of many logical (this 
could be debated) rules.  The rules are represented almost 
verbatim in Prolog code.

One issue that must always be raised is performance.  It 
seems as if this year I had one of everything the IRS cares 
about.  As a result my program had to deal with seven 
different forms.  The tax computation on a 
Macintosh SE was under two seconds.

There is an opportunity to utilize Prolog for developing 
intelligent financial applications.  In particular a 
commercial tax program might also include various rules which 
give advice above and beyond the IRS rules.  That is, it 
would become an integrated tax program and expert system.

In addition, the straight forward rule syntax of Prolog makes 
for code which is very easy to modify from year to year.  The 
proliferation of Prolog's on various machines makes the code 
reasonably easy to port from machine to machine.  In short, 
the vendor working with Prolog has a tremendous advantage 
over vendor's working with more conventional languages.




⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?