https://github.com/davidar/aspi
Answer Set Programming, Interactively
https://github.com/davidar/aspi
Last synced: 11 months ago
JSON representation
Answer Set Programming, Interactively
- Host: GitHub
- URL: https://github.com/davidar/aspi
- Owner: davidar
- Created: 2019-08-23T12:09:05.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2021-03-22T06:43:04.000Z (about 5 years ago)
- Last Synced: 2025-04-28T13:08:56.042Z (about 1 year ago)
- Language: Python
- Size: 630 KB
- Stars: 7
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# aspi
*[Answer Set Programming](https://en.wikipedia.org/wiki/Answer_set_programming), Interactively*
[](https://gitpod.io/#https://github.com/davidar/aspi)
This project started as an interactive shell for [clingo](https://github.com/potassco/clingo), and is gradually morphing into an experimental programming language based on [Lambda Dependency-Based Compositional Semantics](https://arxiv.org/abs/1309.4408) (λdcs). It supports a variety of declarative programming paradigms in a cohesive manner:
- [Functional programming](https://en.wikipedia.org/wiki/Functional_programming)
```
fib[0]: 0.
fib[1]: 1.
fib[N 2..45]: fib[N-1] + fib[N-2].
```
- [Relational programming](http://matt.might.net/articles/microkanren/)
```
pythag(A n2, B n2, C n2): (A**2) = ((B**2) + (C**2)).
```
- [Constraint programming](https://en.wikipedia.org/wiki/Constraint_programming)
```
triple(A,B,C): pythag(A,B,C), ((A+B)+C) = 96?
```
- [Zebra puzzle solver](test/zebra.log)
- [Logic programming](https://en.wikipedia.org/wiki/Logic_programming)
```
mine: block ~red ~supports.pyramid.
in.box mine?
```
- [Definite clause grammars](https://en.wikipedia.org/wiki/Definite_clause_grammar)
```
#macro words[A,B]: concatenate[A, " ", B].
sentence[s(N,V)]: words[noun_phrase.N, verb_phrase.V].
noun_phrase[np(D,N)]: words[det D, noun N].
verb_phrase[vp(V,N)]: words[verb V, noun_phrase.N].
det: "a" | "the".
noun: "bat" | "cat".
verb: "eats".
parse.S: sentence'.S.
```
```
>>> parse."the bat eats a cat"?
that: s(np("the","bat"),vp("eats",np("a","cat"))).
```
- [Predicating type specifiers](https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node47.html)
```
collatz[N even n3]: N / 2.
collatz[N odd n3]: (3*N) + 1.
say[N multiple.100 100..900]: concatenate[say[N/100], " hundred"].
```
- [Automated planning](https://en.wikipedia.org/wiki/Automated_planning_and_scheduling)
- [Tower of Hanoi solver](test/hanoi.log)
- [SHRDLU-inspired dialogue](test/shrdlu.log)
The language is still unstable and lacking much documentation yet, but there are several example programs in this repo, e.g. [solutions to Project Euler-like problems](test/euler/).
## Syntax
λdcs can be used to write logic programs in a concise, [pointfree](https://wiki.haskell.org/Pointfree) manner. Below are a number of examples comparing how λdcs expressions translate to standard logic programs, as well as monadic functional programs.
λdcsASP logic programHaskell
Unary predicate
```
seattle?
```
```prolog
what(A) :- seattle(A).
```
```haskell
[Seattle]
```
Join binary to unary predicate
```
place_of_birth.seattle?
```
```prolog
what(B) :- place_of_birth(B,A), seattle(A).
```
```haskell
placeOfBirth =<< [Seattle]
```
Reverse operator
```
place_of_birth'.john?
```
```prolog
what(B) :- place_of_birth(A,B), john(A).
```
```haskell
inv placeOfBirth =<< [John]
```
Join chain
```
children.place_of_birth.seattle?
```
```prolog
what(C) :- children(C,B),
place_of_birth(B,A),
seattle(A).
```
```haskell
children =<< placeOfBirth =<< [Seattle]
```
Intersection
```
profession.scientist place_of_birth.seattle?
```
```prolog
what(C) :- profession(C,A), scientist(A),
place_of_birth(C,B), seattle(B).
```
```haskell
[ x | x <- profession =<< [Scientist]
, x' <- placeOfBirth =<< [Seattle]
, x == x' ]
```
Union
```
oregon | washington | type.canadian_province?
```
```prolog
what(C) :- disjunction(C).
disjunction(B) :- oregon(B).
disjunction(B) :- washington(B).
disjunction(B) :- type(B,A),
canadian_province(A).
```
```haskell
[Oregon] <|> [Washington]
<|> (type' =<< [CanadianProvince])
```
Negation
```
type.us_state ~border.california?
```
```prolog
what(D) :- type(D,A), us_state(A),
not negation(D).
negation(C) :- border(C,B), california(B).
```
```haskell
(type' =<< [USState]) \\ (border =<< [California])
```
Aggregation
```
count{type.us_state}?
```
```prolog
what(C) :- C = #count { B : type(B,A),
us_state(A) }.
```
```haskell
[length . nub $ type' =<< [USState]]
```
μ abstraction
```
X children.influenced.X?
```
```prolog
what(B) :- B = MuX, children(B,A),
influenced(A,MuX).
```
```haskell
[ x | x <- universe
, x' <- children =<< influenced =<< [x]
, x == x' ]
```
λ abstraction
```
number_of_children.X: count{children'.X}.
```
```prolog
number_of_children(B,MuX) :-
B = #count { A : children(MuX,A) }.
```
```haskell
numberOfChildren x =
[length . nub $ inv children =<< [x]]
```
The Haskell code above uses the following definitions:
```haskell
universe :: (Bounded a, Enum a) => [a]
universe = [minBound .. maxBound]
inv :: (Bounded a, Enum a, Eq b) => (a -> [b]) -> b -> [a]
inv f y = [ x | x <- universe, y' <- f x, y == y' ]
```