# Represent Accounting Equation Using SWI-Prolog

**URL:** <https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465>\
**Category:** Help!\
**Tags:** swish\
**Created:** [November 10, 2019, 5:03pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465 "2019-11-10T17:03:29Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![CharlesHoffmanCPA](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/charleshoffmancpa/32/698_2.png) [@CharlesHoffmanCPA](https://swi-prolog.discourse.group/u/CharlesHoffmanCPA)\
**Post date:** [November 12, 2019, 5:21pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/42 "2019-11-12T17:21:16Z")

</div>

Regarding…

> I’ve implemented accounting systems (not using Prolog) and can assure you that Prolog (or Datalog) would be a fine way of adding business rules to databases.

This is good information.

What are your thoughts on [Answer Set Programming](http://www.kr.tuwien.ac.at/staff/tkren/pub/2009/rw2009-asp.pdf)?

---

<div class="post-metadata">

**Author:** ![CharlesHoffmanCPA](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/charleshoffmancpa/32/698_2.png) [@CharlesHoffmanCPA](https://swi-prolog.discourse.group/u/CharlesHoffmanCPA)\
**Post date:** [November 12, 2019, 5:48pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/43 "2019-11-12T17:48:37Z")

</div>

The conformance suite is public domain, free for anyone to use.

So I have a proposal that might help you meet your needs. This example, [Common Elements of Financial Statements](http://xbrlsite.azurewebsites.net/2019/Core/master-elements/), is small but very comprehensive example. It is also well documented.

What I could do is create a new conformance suite for you that would help you achieve what is is that you want to achieve. In my view, it would be really great to be able to convert XBRL into SWI-Prolog. In fact, what would be REALLY useful would be to import XBRL into SWI-Prolog directly (not sure if I am explaining this precisely).

I have created this informally defined logical model of a business report, [Open Source Framework for Implementing XBRL-based Digital Financial Reporting](http://xbrlsite.azurewebsites.net/2019/Framework/FrameworkEntitiesSummary.html). Those would be the preferable terms to use.

Also, of use might be my “standard” [explanation of a logical system terms](http://xbrl.squarespace.com/journal/2019/11/1/explanation-of-a-financial-report-logical-system-in-simple-t.html).

The objective of all this is to be able to explain the logic of a business report (note that a financial report is a specialization of the more general business report).

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [November 12, 2019, 5:54pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/44 "2019-11-12T17:54:19Z")

</div>

> [@CharlesHoffmanCPA](#):
>
> What are your thoughts on [Answer Set Programming](http://www.kr.tuwien.ac.at/staff/tkren/pub/2009/rw2009-asp.pdf)?

Answer Set Programming (ASP) is the opposite end of the spectrum from Datalog. 😉

A step back from ASP is constraint solving (there are a number of such solvers within SWI-Prolog). These are very powerful and can be quite efficient. But debugging constraint solvers can be difficult – the constraint solver says “no” but doesn’t give a hint as to why because there are an infinite number of ways that the constraints can’t be solved. (As an experiment, one of our PhD interns tried using a boolean satisfiability solver to infer Python datatypes; even trivial programs ended up with millions of constraints, which were impossible to debug.)

So, if you use constraints – and I think that they’re a great way of doing certain things – you need to think about how the constraint solver would explain failures. If the constraints can be thought of an extension to how Prolog computes a solution (e.g., using [freeze/2](https://www.swi-prolog.org/pldoc/doc_for?object=freeze/2) to delay goals until sufficiently instantiated), they are fairly easy to use; more sophisticated constraints can be a challenge.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 12, 2019, 5:54pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/45 "2019-11-12T17:54:24Z")

</div>

Thanks.

Let me do the basic conformance items first to get my feet in the water and better understand the accounting terms then we can expand on it from there. I don’t want to bite off more than I can chew.

Also and I noted to another programmer many years ago when she could not understand that I did not learn about debits and credits in school is that I have a BS and not a BA. In other words the STEM stuff is more of my knowledge and this accounting problem will help to expand my knowledge. 😀

---

<div class="post-metadata">

**Author:** ![CharlesHoffmanCPA](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/charleshoffmancpa/32/698_2.png) [@CharlesHoffmanCPA](https://swi-prolog.discourse.group/u/CharlesHoffmanCPA)\
**Post date:** [November 12, 2019, 5:54pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/46 "2019-11-12T17:54:38Z")

</div>

Peter, what is your view of OWL as contrast to Prolog/Datalog? One of the reasons OMG is interested in SBRM is so that they can get XBRL converted to RDF/OWL. Both XBRL processors and OWL/RDF have limitations in terms of their capabilities to process the logic of a financial report. With XBRL, you have to add some specific things and I know what those are. With OWL/RDF; you also have to use SHACL ([Shapes Constraint Language](https://www.w3.org/TR/shacl/)) . I will know exactly how much you need to use SHACL within a couple of days most likely. What would be really good to understand is what Prolog/Datalog might be missing.

---

<div class="post-metadata">

**Author:** ![CharlesHoffmanCPA](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/charleshoffmancpa/32/698_2.png) [@CharlesHoffmanCPA](https://swi-prolog.discourse.group/u/CharlesHoffmanCPA)\
**Post date:** [November 12, 2019, 5:59pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/47 "2019-11-12T17:59:10Z")

</div>

You might be interested in this; here is information that [explains double-entry accounting in terms of mathematics](http://xbrl.squarespace.com/journal/2019/11/4/the-mathematics-of-double-entry-bookkeeping.html). Double-entry accounting is basic freshman algebra.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [November 12, 2019, 6:37pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/48 "2019-11-12T18:37:32Z")

</div>

> [@CharlesHoffmanCPA](#):
>
> what is your view of OWL as contrast to Prolog/Datalog

Notations such as OWL (or “Semantic Web” or “RDF” or …) are more constrained than Datalog or Prolog. In return, computations over OWL ontologies can be more efficient because of the restrictions.

In the “old days”, there was a lot of work with systems such as KL-ONE, which turned out to have almost intractable problems with defining concepts such as “is-a” versus “has-attribute” (e.g., you might define a class of “red object” but what about objects that have an attribute “color=red”?). These problems endure, but are often swept under the rug by proponents of simple ontological representation systems.

It’s been many years since I’ve worked on this; and I don’t consider myself very competent in it. You might want read [http://www.jfsowa.com/](http://www.jfsowa.com/) or ask a question on [http://gnowledge.org/pipermail/cg/](http://gnowledge.org/pipermail/cg/) or [Redirecting to Google Groups](https://groups.google.com/forum/#!forum/ontolog-forum) – people such as John Sowa or Harry Delugach (and many others whose names I don’t remember off-hand) know far more about this than I ever will.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 12, 2019, 9:21pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/50 "2019-11-12T21:21:07Z")

</div>

Here is the some proof of concept code that reads the sample XBLR data and checks that the formula

> Assets = Liabilities + Equity

is true.

I originally tried to read the data with the SGML parser but it expected end tags instead of tags that ended with `/>` which was causing more problems than it was worth. As this is the first time I have used either the SGML or XML parser with SWI-Prolog, probably something I need to learn, I could not find an option for allowing tags ending with `/>`.

Note: Click triangle below to expand section.

> **Proof of concept code**
>
> ```prolog
> xbrl(Xbrl,Assets,Liabilities,Equity) :-
> Xbrl = element(xbrl,_,Elements),
> elements(Elements,Assets,Liabilities,Equity), !.
> 
> elements([],0,0,0).
> elements([element('ae:Assets',_,Value_list)|Elements],Assets,Liabilities,Equity) :-
> Value_list = [Value_atom],
> atom_number(Value_atom,Value),
> elements(Elements,Assets0,Liabilities,Equity),
> Assets is Assets0 + Value.
> elements([element('ae:Liabilities',_,Value_list)|Elements],Assets,Liabilities,Equity) :-
> Value_list = [Value_atom],
> atom_number(Value_atom,Value),
> elements(Elements,Assets,Liabilities0,Equity),
> Liabilities is Liabilities0 + Value.
> elements([element('ae:Equity',_,Value_list)|Elements],Assets,Liabilities,Equity) :-
> Value_list = [Value_atom],
> atom_number(Value_atom,Value),
> elements(Elements,Assets,Liabilities,Equity0),
> Equity is Equity0 + Value.
> elements([_|T],Assets,Liabilities,Equity) :-
> elements(T,Assets,Liabilities,Equity).
> 
> does_balance_sheet_balance(Assets,Liabilities,Equity) :-
> Assets is Liabilities + Equity.
> 
> :- begin_tests(xblr).
> 
> test(01) :-
> Xblr_string =
> "<!-- Created by Charles Hoffman, CPA: 2019-11-02 -->\n\c
> <xbrl xmlns=\"http://www.xbrl.org/2003/instance\" xmlns:xbrll=\"http://www.xbrl.org/2003/linkbase\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:iso4217=\"http://www.xbrl.org/2003/iso4217\" xmlns:xbrldi=\"http://xbrl.org/2006/xbrldi\" xmlns:xbrldt=\"http://xbrl.org/2005/xbrldt\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:ae=\"http://www.xbrlsite.com/financialreporting/ae\" xsi:schemaLocation=\"http://xbrl.org/2006/xbrldi http://www.xbrl.org/2006/xbrldi-2006.xsd\">\n\c
> <xbrll:schemaRef xlink:href=\"ae.xsd\" xlink:type=\"simple\" xlink:arcrole=\"http://www.xbrl.org/2003/linkbase\"/>\n\c
> <xbrll:linkbaseRef xlink:type=\"simple\" xlink:arcrole=\"http://www.w3.org/1999/xlink/properties/linkbase\" xlink:href=\"ae-formula.xml\"/>\n\c
> <context id=\"I-2020\">\n\c
> <entity>\n\c
> <identifier scheme=\"http://standards.iso.org/iso/17442\">GH259400TOMPUOLS65II</identifier>\n\c
> </entity>\n\c
> <period>\n\c
> <instant>2020-12-31</instant>\n\c
> </period>\n\c
> </context>\n\c
> <unit id=\"U-Monetary\">\n\c
> <measure>iso4217:USD</measure>\n\c
> </unit>\n\c
> <ae:Assets contextRef=\"I-2020\" unitRef=\"U-Monetary\" decimals=\"INF\">5000</ae:Assets>\n\c
> <ae:Liabilities contextRef=\"I-2020\" unitRef=\"U-Monetary\" decimals=\"INF\">1000</ae:Liabilities>\n\c
> <ae:Equity contextRef=\"I-2020\" unitRef=\"U-Monetary\" decimals=\"INF\">4000</ae:Equity>\n\c
> </xbrl>",
> open_string(Xblr_string,Stream),
> load_xml(Stream,[Xbrl],[]),
> xbrl(Xbrl,Assets,Liabilities,Equity),
> does_balance_sheet_balance(Assets,Liabilities,Equity).
> 
> :- end_tests(xblr).
> 
> ```
> 
> Example run.
> 
> You will need to change to the appropriate directory on your system.
> 
> ```prolog
> ?- working_directory(_,'c:/users/eric/documents/Projects/Prolog/xbrl').
> true.
> 
> ?- consult("xbrl.pl").
> true.
> 
> ?- run_tests.
> % PL-Unit: xblr . done
> % test passed
> true.
> 
> ```

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 12, 2019, 9:24pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/51 "2019-11-12T21:24:50Z")

</div>

I took a detailed look at some of the files in [XBRL-based Digital Financial Reporting Conformance Suite Tests](http://xbrlsite.azurewebsites.net/2019/Prototype/conformance-suite/Production/index.xml) and while I could identify the values, it was not simple Assets, Liabilities and Equity as I expected so I didn’t know what kind of rules to write for it or how to view it to make sense. I did see the dates you noted earlier for the range checks you needed. 😀

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [November 13, 2019, 7:41am UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/57 "2019-11-13T07:41:54Z")

</div>

> [@EricGT](#):
>
> I originally tried to read the data with the SGML parser but it expected end tags instead of tags that ended with `/>` which was causing more problems than it was worth. As this is the first time I have used either the SGML or XML parser with SWI-Prolog, probably something I need to learn, I could not find an option for allowing tags ending with `/>`

There are zillion of options. But, e.g., `<img .../>` is not legal SGML AFAIK. Most likely that means the format is XML. If I recall well, HTML5 mode also allows for this. Not sure though. Given the right options it can parse almost any SGML/XML/HTML document, sometimes with warnings. Note that using simple DCGs or other simple pattern matching is quite likely to go wrong at some point. There are a lot of legal different serializations for the same document in all these dialects.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [November 13, 2019, 11:25am UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/58 "2019-11-13T11:25:15Z")

</div>

It works perfectly fine, without warnings:

```prolog
$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.15-10-g6718ecfeb)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- load_xml('instance.xml', T, []).
T = [element(xbrl, [xmlns='http://www.xbrl.org/2003/instance', 'xmlns:xbrll'='http://www.xbrl.org/2003/linkbase', 'xmlns:xlink'='http://www.w3.org/1999/xlink', 'xmlns:iso4217'='http://www.xbrl.org/2003/iso4217', 'xmlns:xbrldi'='http://xbrl.org/2006/xbrldi', 'xmlns:xbrldt'='http://xbrl.org/2005/xbrldt', ... = ...|...], ['\n\n ', element('xbrll:schemaRef', ['xlink:href'='ae.xsd', 'xlink:type'=simple, 'xlink:arcrole'='http://www.xbrl.org/2003/linkbase'], []), '\n\n ', element('xbrll:linkbaseRef', ['xlink:type'=simple, ... = ...|...], []), '\n\n ', element(context, [...], [...|...]), '\n\n '|...])].

```

`instance.xml` is the XML file linked, [found exactly here](http://xbrlsite.azurewebsites.net/2019/Core/master-ae/instance.xml).

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 13, 2019, 11:58am UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/59 "2019-11-13T11:58:51Z")

</div>

Here is some more details on the reading of [instance.xml](http://xbrlsite.azurewebsites.net/2019/Core/master-ae/instance.xml) .

In reading the documentation for package [SWI-Prolog SGML/XML parser](https://www.swi-prolog.org/pldoc/doc_for?object=section(%27packages/sgml.html%27)) it notes in section [10 Unsupported SGML features](https://www.swi-prolog.org/pldoc/man?section=sgml-unsupported)

_SHORTTAG_  
The SGML SHORTTAG syntax is only partially implemented. Currently, `<tag/content/` is a valid abbreviation for `<tag>content</tag>` , which can also be written as `<tag>content</>` . Empty start tags ( `<>` ), unclosed start tags ( `<a<b</verb>` ) and unclosed end tags ( `<verb></a<b` ) are not supported.

This is not a show stopper as I have shown with the [proof of concept code](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/50) and as Jan notes there are other ways that can be more beneficial to deal with this.

The reason I am not exploring them in more detail at present is that I would like to see the code related to the validity rules and then other business concepts that might be implemented before optimizing the code. As this code has not been written yet, that is the next logical step. The rule of thumb “Premature optimization is the root of all evil” applies at this time.

To make the issue with the end tags more apparent, when I was writing the code I made use of [print\_term/2](https://www.swi-prolog.org/pldoc/doc_for?object=prolog_pretty_print%3Aprint_term/2) but removed them in the presented version.

The output is presented here for closer inspection.

> **Use of load\_sgml/3 and print\_term/2**
>
> ```prolog
> ?- load_sgml('instance.xml',Xbrl,[]),print_term(Xbrl,[]).
> Warning: SGML2PL(sgml): instance.xml:19: Inserted omitted end-tag for "xbrll:linkbaseref"
> Warning: SGML2PL(sgml): instance.xml:19: Inserted omitted end-tag for "xbrll:schemaref"
> [ element(xbrl,
> [ xmlns = 'http://www.xbrl.org/2003/instance',
> 'xmlns:xbrll' = 'http://www.xbrl.org/2003/linkbase',
> 'xmlns:xlink' = 'http://www.w3.org/1999/xlink',
> 'xmlns:iso4217' = 'http://www.xbrl.org/2003/iso4217',
> 'xmlns:xbrldi' = 'http://xbrl.org/2006/xbrldi',
> 'xmlns:xbrldt' = 'http://xbrl.org/2005/xbrldt',
> 'xmlns:xsi' = 'http://www.w3.org/2001/XMLSchema-instance',
> 'xmlns:ae' = 'http://www.xbrlsite.com/financialreporting/ae',
> 'xsi:schemalocation' = 'http://xbrl.org/2006/xbrldi http://www.xbrl.org/2006/xbrldi-2006.xsd'
> ],
> [ element('xbrll:schemaref',
> [ 'xlink:href' = 'ae.xsd',
> 'xlink:type' = simple,
> 'xlink:arcrole' = 'http://www.xbrl.org/2003/linkbase'
> ],
> [ '>\n',
> element('xbrll:linkbaseref',
> [ 'xlink:type' = simple,
> 'xlink:arcrole' = 'http://www.w3.org/1999/xlink/properties/linkbase',
> 'xlink:href' = 'ae-formula.xml'
> ],
> [ '>\n',
> element(context,
> [id='I-2020'],
> [ element(entity,
> [],
> [ element(identifier,
> [ scheme = 'http://standards.iso.org/iso/17442'
> ],
> [ 'GH259400TOMPUOLS65II'
> ])
> ]),
> element(period,
> [],
> [ element(instant,
> [],
> [ '2020-12-31'
> ])
> ])
> ]),
> element(unit,
> [id='U-Monetary'],
> [ element(measure,
> [],
> ['iso4217:USD'])
> ]),
> element('ae:assets',
> [ contextref = 'I-2020',
> unitref = 'U-Monetary',
> decimals = 'INF'
> ],
> ['5000']),
> element('ae:liabilities',
> [ contextref = 'I-2020',
> unitref = 'U-Monetary',
> decimals = 'INF'
> ],
> ['1000']),
> element('ae:equity',
> [ contextref = 'I-2020',
> unitref = 'U-Monetary',
> decimals = 'INF'
> ],
> ['4000'])
> ])
> ])
> ])
> ]
> Xbrl = [element(xbrl, [xmlns='http://www.xbrl.org/2003/instance', 'xmlns:xbrll'='http://www.xbrl.org/2003/linkbase', 'xmlns:xlink'='http://www.w3.org/1999/xlink', 'xmlns:iso4217'='http://www.xbrl.org/2003/iso4217', 'xmlns:xbrldi'='http://xbrl.org/2006/xbrldi', 'xmlns:xbrldt'='http://xbrl.org/2005/xbrldt', ... = ...|...], [element('xbrll:schemaref', ['xlink:href'='ae.xsd', 'xlink:type'=simple, 'xlink:arcrole'='http://www.xbrl.org/2003/linkbase'], ['>\n', element('xbrll:linkbaseref', ['xlink:type'=simple, ... = ...|...], ['>\n', element(..., ..., ...)|...])])])].
> 
> ```

> **Use of load\_xml/3 and print\_term/2**
>
> ```prolog
> ?- load_xml('instance.xml',Xbrl,[]),print_term(Xbrl,[]).
> [ element(xbrl,
> [ xmlns = 'http://www.xbrl.org/2003/instance',
> 'xmlns:xbrll' = 'http://www.xbrl.org/2003/linkbase',
> 'xmlns:xlink' = 'http://www.w3.org/1999/xlink',
> 'xmlns:iso4217' = 'http://www.xbrl.org/2003/iso4217',
> 'xmlns:xbrldi' = 'http://xbrl.org/2006/xbrldi',
> 'xmlns:xbrldt' = 'http://xbrl.org/2005/xbrldt',
> 'xmlns:xsi' = 'http://www.w3.org/2001/XMLSchema-instance',
> 'xmlns:ae' = 'http://www.xbrlsite.com/financialreporting/ae',
> 'xsi:schemaLocation' = 'http://xbrl.org/2006/xbrldi http://www.xbrl.org/2006/xbrldi-2006.xsd'
> ],
> [ '\n',
> element('xbrll:schemaRef',
> [ 'xlink:href' = 'ae.xsd',
> 'xlink:type' = simple,
> 'xlink:arcrole' = 'http://www.xbrl.org/2003/linkbase'
> ],
> []),
> '\n',
> element('xbrll:linkbaseRef',
> [ 'xlink:type' = simple,
> 'xlink:arcrole' = 'http://www.w3.org/1999/xlink/properties/linkbase',
> 'xlink:href' = 'ae-formula.xml'
> ],
> []),
> '\n',
> element(context,
> [id='I-2020'],
> [ '\n',
> element(entity,
> [],
> [ '\n',
> element(identifier,
> [ scheme = 'http://standards.iso.org/iso/17442'
> ],
> ['GH259400TOMPUOLS65II']),
> '\n'
> ]),
> '\n',
> element(period,
> [],
> ['\n',element(instant,[],['2020-12-31']),'\n']),
> '\n'
> ]),
> '\n',
> element(unit,
> [id='U-Monetary'],
> ['\n',element(measure,[],['iso4217:USD']),'\n']),
> '\n',
> element('ae:Assets',
> [contextRef='I-2020',unitRef='U-Monetary',decimals='INF'],
> ['5000']),
> '\n',
> element('ae:Liabilities',
> [contextRef='I-2020',unitRef='U-Monetary',decimals='INF'],
> ['1000']),
> '\n',
> element('ae:Equity',
> [contextRef='I-2020',unitRef='U-Monetary',decimals='INF'],
> ['4000']),
> '\n'
> ])
> ]
> Xbrl = [element(xbrl, [xmlns='http://www.xbrl.org/2003/instance', 'xmlns:xbrll'='http://www.xbrl.org/2003/linkbase', 'xmlns:xlink'='http://www.w3.org/1999/xlink', 'xmlns:iso4217'='http://www.xbrl.org/2003/iso4217', 'xmlns:xbrldi'='http://xbrl.org/2006/xbrldi', 'xmlns:xbrldt'='http://xbrl.org/2005/xbrldt', ... = ...|...], ['\n', element('xbrll:schemaRef', ['xlink:href'='ae.xsd', 'xlink:type'=simple, 'xlink:arcrole'='http://www.xbrl.org/2003/linkbase'], []), '\n', element('xbrll:linkbaseRef', ['xlink:type'=simple, ... = ...|...], []), '\n', element(context, [...], [...|...]), '\n'|...])].
> 
> ```

As is evident with `load_xml/3` as used the tag endings are resulting in `\n`, however these are not disrupting the hierarchy for parsing the data structure.

On the other hand `load_sgml/3` as used the tag endings are resulting in `\n`, and these are disrupting the hierarchy for parsing the data structure.

Using `load_html/3` as suggested by Jan seems to not suffer from the end tag issue.

> **Use of load\_html/3 and print\_term/2**
>
> ```prolog
> ?- load_html('instance.xml',Xbrl,[]),print_term(Xbrl,[]).
> [ element(xbrl,
> [ xmlns = 'http://www.xbrl.org/2003/instance',
> 'xmlns:xbrll' = 'http://www.xbrl.org/2003/linkbase',
> 'xmlns:xlink' = 'http://www.w3.org/1999/xlink',
> 'xmlns:iso4217' = 'http://www.xbrl.org/2003/iso4217',
> 'xmlns:xbrldi' = 'http://xbrl.org/2006/xbrldi',
> 'xmlns:xbrldt' = 'http://xbrl.org/2005/xbrldt',
> 'xmlns:xsi' = 'http://www.w3.org/2001/XMLSchema-instance',
> 'xmlns:ae' = 'http://www.xbrlsite.com/financialreporting/ae',
> 'xsi:schemalocation' = 'http://xbrl.org/2006/xbrldi http://www.xbrl.org/2006/xbrldi-2006.xsd'
> ],
> [ element('xbrll:schemaref',
> [ 'xlink:href' = 'ae.xsd',
> 'xlink:type' = simple,
> 'xlink:arcrole' = 'http://www.xbrl.org/2003/linkbase'
> ],
> []),
> element('xbrll:linkbaseref',
> [ 'xlink:type' = simple,
> 'xlink:arcrole' = 'http://www.w3.org/1999/xlink/properties/linkbase',
> 'xlink:href' = 'ae-formula.xml'
> ],
> []),
> element(context,
> [id='I-2020'],
> [ element(entity,
> [],
> [ element(identifier,
> [ scheme = 'http://standards.iso.org/iso/17442'
> ],
> ['GH259400TOMPUOLS65II'])
> ]),
> element(period,
> [],
> [element(instant,[],['2020-12-31'])])
> ]),,
> element(unit,
> [id='U-Monetary'],
> [element(measure,[],['iso4217:USD'])]),
> element('ae:assets',
> [contextref='I-2020',unitref='U-Monetary',decimals='INF'],
> ['5000']),
> element('ae:liabilities',
> [contextref='I-2020',unitref='U-Monetary',decimals='INF'],
> ['1000']),
> element('ae:equity',
> [contextref='I-2020',unitref='U-Monetary',decimals='INF'],
> ['4000'])
> ])
> ]
> Xbrl = [element(xbrl, [xmlns='http://www.xbrl.org/2003/instance', 'xmlns:xbrll'='http://www.xbrl.org/2003/linkbase', 'xmlns:xlink'='http://www.w3.org/1999/xlink', 'xmlns:iso4217'='http://www.xbrl.org/2003/iso4217', 'xmlns:xbrldi'='http://xbrl.org/2006/xbrldi', 'xmlns:xbrldt'='http://xbrl.org/2005/xbrldt', ... = ...|...], [element('xbrll:schemaref', ['xlink:href'='ae.xsd', 'xlink:type'=simple, 'xlink:arcrole'='http://www.xbrl.org/2003/linkbase'], []), element('xbrll:linkbaseref', ['xlink:type'=simple, 'xlink:arcrole'='http://www.w3.org/1999/xlink/properties/linkbase', 'xlink:href'='ae-formula.xml'], []), element(context, [id='I-2020'], [element(entity, [], [element(..., ..., ...)]), element(period, [], [...])]), element(unit, [id='U-Monetary'], [element(measure, [], [...])]), element('ae:assets', [... = ...|...], ['5000']), element('ae:liabilities', [...|...], [...]), element(..., ..., ...)])].
> 
> ```

Again, I do not see any of this as a show stopper, just a learning exercise.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [November 13, 2019, 12:18pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/60 "2019-11-13T12:18:23Z")

</div>

Although I understand this is not your current priority, I think it is wise to point at features of the SGML/HTML/XML parser.

As @Boris shows, the document is XML. `<x/>` is XML and not valid SGML. White space is by default all part of the document in XML, unless the `xml:space` attribute says otherwise. SWI-Prolog’s XML parser however can be told to process the document otherwise. See [https://www.swi-prolog.org/pldoc/man?section=xml-whitespace](https://www.swi-prolog.org/pldoc/man?section=xml-whitespace)

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [November 13, 2019, 12:26pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/61 "2019-11-13T12:26:15Z")

</div>

> [@jan](#):
>
> As @Boris shows, the document is XML. `<x/>` is XML and not valid SGML. White space is by default all part of the document in XML, unless the `xml:space` attribute says otherwise. SWI-Prolog’s XML parser however can be told to process the document otherwise. See [SWI-Prolog -- Handling white-space](https://www.swi-prolog.org/pldoc/man?section=xml-whitespace)

Thanks Jan.

With `load_xml/3` and using the option `space(remove)` the XML loads without the end tag issue.

> **Use of load\_xml/3 and option space(remove) with print\_term/2**
>
> ```prolog
> ?- load_xml('instance.xml',Xbrl,[space(remove)]),print_term(Xbrl,[]).
> [ element(xbrl,
> [ xmlns = 'http://www.xbrl.org/2003/instance',
> 'xmlns:xbrll' = 'http://www.xbrl.org/2003/linkbase',
> 'xmlns:xlink' = 'http://www.w3.org/1999/xlink',
> 'xmlns:iso4217' = 'http://www.xbrl.org/2003/iso4217',
> 'xmlns:xbrldi' = 'http://xbrl.org/2006/xbrldi',
> 'xmlns:xbrldt' = 'http://xbrl.org/2005/xbrldt',
> 'xmlns:xsi' = 'http://www.w3.org/2001/XMLSchema-instance',
> 'xmlns:ae' = 'http://www.xbrlsite.com/financialreporting/ae',
> 'xsi:schemaLocation' = 'http://xbrl.org/2006/xbrldi http://www.xbrl.org/2006/xbrldi-2006.xsd'
> ],
> [ element('xbrll:schemaRef',
> [ 'xlink:href' = 'ae.xsd',
> 'xlink:type' = simple,
> 'xlink:arcrole' = 'http://www.xbrl.org/2003/linkbase'
> ],
> []),
> element('xbrll:linkbaseRef',
> [ 'xlink:type' = simple,
> 'xlink:arcrole' = 'http://www.w3.org/1999/xlink/properties/linkbase',
> 'xlink:href' = 'ae-formula.xml'
> ],
> []),
> element(context,
> [id='I-2020'],
> [ element(entity,
> [],
> [ element(identifier,
> [ scheme = 'http://standards.iso.org/iso/17442'
> ],
> ['GH259400TOMPUOLS65II'])
> ]),
> element(period,
> [],
> [element(instant,[],['2020-12-31'])])
> ]),
> element(unit,
> [id='U-Monetary'],
> [element(measure,[],['iso4217:USD'])]),
> element('ae:Assets',
> [contextRef='I-2020',unitRef='U-Monetary',decimals='INF'],
> ['5000']),
> element('ae:Liabilities',
> [contextRef='I-2020',unitRef='U-Monetary',decimals='INF'],
> ['1000']),
> element('ae:Equity',
> [contextRef='I-2020',unitRef='U-Monetary',decimals='INF'],
> ['4000'])
> ])
> ]
> Xbrl = [element(xbrl, [xmlns='http://www.xbrl.org/2003/instance', 'xmlns:xbrll'='http://www.xbrl.org/2003/linkbase', 'xmlns:xlink'='http://www.w3.org/1999/xlink', 'xmlns:iso4217'='http://www.xbrl.org/2003/iso4217', 'xmlns:xbrldi'='http://xbrl.org/2006/xbrldi', 'xmlns:xbrldt'='http://xbrl.org/2005/xbrldt', ... = ...|...], [element('xbrll:schemaRef', ['xlink:href'='ae.xsd', 'xlink:type'=simple, 'xlink:arcrole'='http://www.xbrl.org/2003/linkbase'], []), element('xbrll:linkbaseRef', ['xlink:type'=simple, 'xlink:arcrole'='http://www.w3.org/1999/xlink/properties/linkbase', 'xlink:href'='ae-formula.xml'], []), element(context, [id='I-2020'], [element(entity, [], [element(..., ..., ...)]), element(period, [], [...])]), element(unit, [id='U-Monetary'], [element(measure, [], [...])]), element('ae:Assets', [... = ...|...], ['5000']), element('ae:Liabilities', [...|...], [...]), element(..., ..., ...)])].
> 
> ```

---

<div class="post-metadata">

**Author:** ![rla](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/rla/32/6863_2.png) [@rla](https://swi-prolog.discourse.group/u/rla)\
**Post date:** [November 14, 2019, 7:33pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/63 "2019-11-14T19:33:10Z")

</div>

XBRL is interesting but I’m not sure what does correct usage mean here. I can imagine consistent usage with the consistency being defined between different types of reports: balance sheet, profit, and cash flow. Besides this, there are tons of other types of reports, like gov taxes, employment expenses etc. Of course, all of them have to be consistent with those 3 main reports and each other. Correctness, on the other hand, would mean XBRL’s true representation of entity’s business transactions, which is likely a non-automatable task. In Estonia, we file annuals electronically, and filing an XBRL file is one of the options. I have not used it but I have used the form-based entry. It has extensive validation between the reports but I don’t know how it’s been implemented.

I have built two accounting systems in Prolog. One of them I use every day for doing daily accounting for my Estonian company. Prolog is perfect for this. The system itself is very simple and includes both the API interface (frontend is a trivial SPA) and “logic” in 300 lines of code. It uses a simple journaled database to record grouped credit/debit lines. The way how entries are recorded guaratees that the accounting equation is always satisfied. Account balances and cash flows are calculated with the most basic aggregation. Prolog is fast enough, no tabling is neccessary. It’s been audited and found be a good system. XBRL is a very complicated file format and adding support for generating reports in it takes way more effort than just using the simple form-based entry of the gov registry and filling it with the aggregated values from my own system.

---

<div class="post-metadata">

**Author:** ![CharlesHoffmanCPA](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/charleshoffmancpa/32/698_2.png) [@CharlesHoffmanCPA](https://swi-prolog.discourse.group/u/CharlesHoffmanCPA)\
**Post date:** [November 14, 2019, 9:57pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/65 "2019-11-14T21:57:50Z")

</div>

In my view, the focus should not be the XBRL syntax; rather, the focus should be on the fact that because the information is “digitized” and machine-readable, then automation of accounting, reporting, auditing, and analysis tasks are possible. You may be interested in these two documents:

[General Ledger Trial Balance to External Financial Report](http://xbrlsite.azurewebsites.net/2018/RoboticFinance/TrialBalanceToReport.pdf)

[Accounting in the Fourth Industrial Revolution](http://xbrlsite.azurewebsites.net/2019/Library/AccountingInFourthIndustrialRevolution.pdf)

So, a couple of questions about your Prolog accounting system. Would it be possible to modify the accounting system to (a) add an XBRL concept to the accounting system as a property of each account in the chart of accounts, (b) add a transaction grouping code (which is an XBRL concept) to each journal entry, and © try and output the XBRL instance from the journal entries and an XBRL taxonomy. Basically, [this XBRL instance](http://xbrlsite.azurewebsites.net/2019/Core/core-trialbalance/).

For the back of your mind, OMG (Object Management Group) is creating what they call the [Standard Business Report Model (SBRM)](http://xbrlsite.azurewebsites.net/2019/Prototype/sbrm/Home.html) which makes the question of syntax rather moot. Use whatever syntax you might want, or use the syntax that a regulator REQUIRES you to use.

I know someone who might be very interested in your Prolog accounting system, particularly if it could leverage logic articulated within an XBRL taxonomy to manage and monitor transaction entry and output a financial report.

I used to teach accounting information systems. I have a very basic accounting system that I created in Microsoft Access. The interface is adequate, but because I am not a very good programmer I did not take the time to get the “innards” of the system working. You seem to have the “innards” and with a few modifications I suspect you can get your system to do what I have been trying to do. If you are interested, I would love to put your pieces and my pieces together. [Here is a prototype transaction entry form that I created](http://xbrlsite-app.azurewebsites.net/MatrixOfPossibleTransactions/GeneralJournalTransactionEntry.aspx).

If you are interested, I can give you a lot more information on this topic.

---

<div class="post-metadata">

**Author:** ![rla](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/rla/32/6863_2.png) [@rla](https://swi-prolog.discourse.group/u/rla)\
**Post date:** [November 14, 2019, 10:08pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/66 "2019-11-14T22:08:43Z")

</div>

I’m not sure if the response was meant for me. Out of these 300 lines, most are for handling API requests. The code is here: [https://github.com/rla/expenses/blob/93bde49da7f4ebab9384d7e9917437b030b65f08/api.pl](https://github.com/rla/expenses/blob/93bde49da7f4ebab9384d7e9917437b030b65f08/api.pl)

There could be some opportunities for caching but I never saw any perf issues, even over multiple years and thousands of entries per year. Endpoints just take tens of milliseconds to execute. I think it’s mostly thanks to SWI’s automatic indexing which makes docstore (the underlying database) very fast. It’s written long time ago in “dict processing” style before tabling was available and tabling would be difficult to employ with this style I think.

---

<div class="post-metadata">

**Author:** ![CharlesHoffmanCPA](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/charleshoffmancpa/32/698_2.png) [@CharlesHoffmanCPA](https://swi-prolog.discourse.group/u/CharlesHoffmanCPA)\
**Post date:** [November 14, 2019, 10:28pm UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/67 "2019-11-14T22:28:30Z")

</div>

Yeah, I cannot do anything with the prolog code; I would need to rely on someone else to actually build what I am talking about. I am a certified public accountant, not a programmer.

Also, here is something else that can help you and others think about this. Imagine taking a financial report, breaking it apart logically so that it is 100% machine readable. THAT is what XBRL does. Imagine that you wanted to leverage the fact that now computers can probe the report using automated processes (i.e. there was NO WAY to do this before financial statements where created using XBRL. So, say you take the XBRL, feed it to some sort of reasoner (i.e. prolog is a reasoner) and then you reasoned about the facts in the financial report. THAT is incredibly useful in two ways. First, if you use logical reasoning to MAKE SURE the report was put together in the first place. That checks the logical structure, mechanics of the report, mathematics, some other things, etc. That is what [Auditing XBRL-based Financial Reports](http://xbrl.squarespace.com/journal/2019/10/17/auditing-xbrl-based-financial-reports.html) discusses. Then, you might even want to get into auditing the information in the report and accounting system. THAT is what companies like [MindBridge and AI assisted Audits are all about](http://xbrl.squarespace.com/journal/2019/6/12/ai-assisted-audits-are-here.html).

Check this out. [Grant Reporting Efficiency and Agreements Transparency Act](http://xbrl.squarespace.com/journal/2019/10/23/grant-reporting-efficiency-and-agreements-transparency-act-o.html). That will require 320,000 not-for-profit organizations to report against U.S. Federal Government grants using machine-readable form as opposed to what amounts to “e-paper”. This sort of thing is happening all across the world. This is a multi-billion dollar opportunity globally.

No joke.

---

<div class="post-metadata">

**Author:** ![rla](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/rla/32/6863_2.png) [@rla](https://swi-prolog.discourse.group/u/rla)\
**Post date:** [November 15, 2019, 12:31am UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/68 "2019-11-15T00:31:30Z")

</div>

It’s never too late to learn programming 🙂

Anyway, the app could be modified to accept extra data on the account records which name the account and specify the type of account (asset, etc.). Types are currently hardcoded. If the XBRL concept is represented using a string, then that could be easily added as a text field.

Each entry contains a list of lines, each with credit and debit side (account references), the amount in cents, and the date. Base currency of EUR is hardcoded but the original amount in the original currency can also be entered. One entry has multiple lines because it’s very convenient to group certain entries together, for example, receiving a foreign currency invoice, doing conversion, paying the invoice, recording reverse vat charge, and copy/paste this as a whole for every month for recurring expenses. This speeds up data entry and solving inconsistencies later.

So an example entry data is (for the invoice case):

```prolog
entry{
  '$id':'8dd8e9e5-be68-41c7-addb-9878a07c342a',
  title:"Linode invoice 11854109"
  items:[
    item{
      amount:1000,
      credit:'076a3de0-d5cb-454c-aa9b-fad22e0086ae',
      currency:usd,
      date:1541030400,
      debit:'4332dd24-b20d-4f6e-a148-64d7db04e119',
      eur_amount:878,
      title:"Invoice amount"
    },
    item{
      amount:1000,
      credit:'355bac91-8098-4caa-a703-42a4a13868ed',
      currency:usd,
      date:1541116800,
      debit:'076a3de0-d5cb-454c-aa9b-fad22e0086ae',
      eur_amount:878,
      title:"Invoice paid"
    },
    item{
      amount:15,
      credit:'355bac91-8098-4caa-a703-42a4a13868ed',
      currency:eur,
      date:1541116800,
      debit:'574f6fda-cd6e-449d-aaa2-c86d04ce7254',
      eur_amount:15,
      title:"USD/EUR conversion result including transfer fee"
    },
    item{
      amount:176,
      credit:'7ab3a21c-150d-412a-abb7-aa5b59aacd5e',
      currency:eur,
      date:1541116400,
      debit:'4332dd24-b20d-4f6e-a148-64d7db04e119',
      eur_amount:176,
      title:"VAT referse charge"
    }
  ]
}.

```

and this is how it’s represented in the user interface [https://ibb.co/Wgtp3s9](https://ibb.co/Wgtp3s9)

Any report could be calculated from this data at any point of time (not just the latest) including reporting intervals. The system could be easily modified to have entry of “transaction grouping code” for each item although from purely human-readable analytic view, I can imagine an alternative solution by just using separate accounts of same type, like income “Sales from EU”, “Sales from US”, etc. to make them display separated under aggregate reports, for example, when it’s required to report sales income from different regions.

The data itself is accessible through the database query system. For example, this entry was obtained using query `ds_col_get(entry, '8dd8e9e5-be68-41c7-addb-9878a07c342a', E)`. It uses [https://www.swi-prolog.org/pack/list?p=docstore](https://www.swi-prolog.org/pack/list?p=docstore)

---

<div class="post-metadata">

**Author:** ![CharlesHoffmanCPA](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/charleshoffmancpa/32/698_2.png) [@CharlesHoffmanCPA](https://swi-prolog.discourse.group/u/CharlesHoffmanCPA)\
**Post date:** [November 15, 2019, 2:22am UTC](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465/69 "2019-11-15T02:22:17Z")

</div>

That is a very nice interface. So imagine your accounting system, but you do NOT hard code the accounts in the system. You specify the accounts using XBRL. Basically, the information in XBRL serves somewhat like the chart of accounts plus the metadata of a report writer.

The transaction grouping codes are not in the chart of accounts. They represent the ROLL FORWARDS of each real (balance sheet) account.

[Previous page](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465.md?page=2)

[Next page](https://swi-prolog.discourse.group/t/represent-accounting-equation-using-swi-prolog/1465.md?page=4)
