Commit d24cb8c1 authored by Michael Hanus 's avatar Michael Hanus
Browse files

CLP libraries removed (now available in package clp-pakcs)

parent 474723b4
PAKCS: Release Notes
====================
Release notes for PAKCS Version 2.0.0 (October 11, 2017)
Release notes for PAKCS Version 2.0.0 (October 17, 2017)
--------------------------------------------------------
This version has almost the same functionality as version 1.15.0
......@@ -12,10 +12,14 @@ this version contains the following changes:
* `define` command removed (since it was based on a quite restricted parser)
* Free variable mode (option `+free`) removed since it has many restrictions
and is no longer compatible with type classes.
* Some libraries removed since they are available as packages
which can easily be installed via `cpm`:
- `CLP*` (now in package `clp-pakcs`)
Release notes for PAKCS Version 1.15.0 (September 28, 2017)
-----------------------------------------------------------
Release notes for PAKCS Version 1.15.0 (October 11, 2017)
---------------------------------------------------------
Changes to version 1.14.2:
......
......@@ -386,9 +386,6 @@ following term:
\input{lib/AllSolutions}
\input{lib/Assertion}
\input{lib/Char}
\input{lib/CLP.FD}
\input{lib/CLPFD}
\input{lib/CLPR}
\input{lib/Combinatorial}
\input{lib/CPNS}
\input{lib/CSV}
......
-- Curry with arithmetic constraints:
import CLPR
-- Circuit analysis:
data Circuit = Resistor Float
| Series Circuit Circuit
| Parallel Circuit Circuit
cvi (Resistor r) v i = v =:= i *. r
cvi (Series c1 c2) v i =
let v1,v2 free in v=:=v1+.v2 & cvi c1 v1 i & cvi c2 v2 i
cvi (Parallel c1 c2) v i =
let i1,i2 free in i=:=i1+.i2 & cvi c1 v i1 & cvi c2 v i2
-- cvi (Series (Resistor 180.0) (Resistor 470.0)) 5.0 I
-- I = 0.007692307692307693
-- cvi (Series (Series (Resistor R) (Resistor R)) (Resistor R)) V 5.0
-- {V=15.0*R}
-- Curry with arithmetic constraints:
import CLP.R
-- Circuit analysis:
data Circuit = Resistor CFloat
| Series Circuit Circuit
| Parallel Circuit Circuit
cvi :: Circuit -> CFloat -> CFloat -> Bool
cvi (Resistor r) v i = v =:= i * r
cvi (Series c1 c2) v i =
let v1,v2 free in v=:=v1+v2 & cvi c1 v1 i & cvi c2 v2 i
cvi (Parallel c1 c2) v i =
let i1,i2 free in i=:=i1+i2 & cvi c1 v i1 & cvi c2 v i2
-- cvi (Series (Resistor 180.0) (Resistor 470.0)) 5.0 i where i free
-- i = 0.007692307692307693
-- let i free in cvi (Series (Resistor 180) (Resistor 470)) 5 i &> print i
-- 0.007692307692307693
-------------------------------------------------------------------------------------
-- Computing magic series.
-- A series [a_0,a_1,....,a_(n-1)] is called magic iff there are s_i occurrences
-- of i in this series, for all i=1,...,n-1
--
-- Adapted from an example of the TOY(FD) distribution.
import CLPFD
magic :: Int -> [Int]
magic n | take n (generateFD n) =:= l &
constrain l l 0 cs & sum l (=#) n & scalarProduct cs l (=#) n &
labeling [FirstFail] l
= l
where l,cs free
generateFD n | n ># 0 & domain [x] 0 (n-1) = x : generateFD n where x free
constrain [] _ _ [] = True
constrain (x:xs) l i (j:s2) = i=:=j & count i l (=#) x & constrain xs l (i+1) s2
magicfrom :: Int -> [[Int]]
magicfrom n = magic n : magicfrom (n+1)
main = take 3 (magicfrom 7)
--> [[3,2,1,1,0,0,0],[4,2,1,0,1,0,0,0],[5,2,1,0,0,1,0,0,0]]
----------------------------------------------------------------------------
--- Computing magic series.
--- A series [a_0,a_1,....,a_(n-1)] is called magic iff there are
--- a_i occurrences of i in this series, for all i=1,...,n-1
---
--- Adapted from an example of the TOY(FD) distribution.
----------------------------------------------------------------------------
import CLP.FD
-- Compute a magic series of length n:
magic :: Int -> [Int]
magic n =
let vs = take n (domain 0 (n-1)) -- FD variables
is = map fd (take n [0..]) -- FD constants: indices of elements
in solveFD [FirstFail] vs $
constrain vs vs is /\
sum vs Equ (fd n) /\
scalarProduct is vs Equ (fd n)
constrain :: [FDExpr] -> [FDExpr] -> [FDExpr] -> FDConstr
constrain [] _ _ = true
constrain (x:xs) vs (i:is) = count i vs Equ x /\ constrain xs vs is
magicfrom :: Int -> [[Int]]
magicfrom n = magic n : magicfrom (n+1)
main = take 3 (magicfrom 7)
--> [[3,2,1,1,0,0,0],[4,2,1,0,1,0,0,0],[5,2,1,0,0,1,0,0,0]]
-- Curry with arithmetic constraints:
--
-- import the CLPR library:
import CLPR
-- Example:
-- Mortgage relationship between:
-- p: Principal
-- t: Life of loan in months
-- ir: Fixed (but compounded) monthly interest rate
-- r: Monthly repayment
-- b: Outstanding balance at the end
mortgage p t ir r b | t >. 0 & t <=. 1 -- lifetime not more than 1 month?
= b =:= p *. (1 +. t *. ir) -. t *. r
mortgage p t ir r b | t >. 1 -- lifetime more than 1 month?
= mortgage (p *. (1 +. ir) -. r) (t -. 1) ir r b
-- mortgage 100000 180 0.01 r 0 where r free
-- mortgage 100000 time 0.01 1400 0 where time free
-- mortgage h 180 0.01 r b where h,r,b free
-- Curry with arithmetic constraints:
--
-- import the CLPR library:
{-# OPTIONS_CYMAKE -Wno-overlapping #-}
import CLP.R
-- Example:
-- Mortgage relationship between:
-- p: Principal
-- t: Life of loan in months
-- ir: Fixed (but compounded) monthly interest rate
-- r: Monthly repayment
-- b: Outstanding balance at the end
mortgage :: CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> Bool
mortgage p t ir r b | t > 0 & t <= 1 -- lifetime not more than 1 month?
= b =:= p * (1 + t*ir) - t*r
mortgage p t ir r b | t > 1 -- lifetime more than 1 month?
= mortgage (p * (1+ir) - r) (t-1) ir r b
-- mortgage 100000 180 0.01 r 0 where r free
ex1 = let r free in mortgage 100000 180 0.01 r 0 &> show r
-- Compute time to amortize mortage (use ":set +first" here!):
ex2 = let time free in mortgage 100000 time 0.01 1400 0 &> show time
import CLPFD
-- solving the n-queens problem in Curry with FD constraints:
queens options n l =
gen_vars n =:= l &
domain l 1 (length l) &
all_safe l &
labeling options l
all_safe [] = True
all_safe (q:qs) = safe q qs 1 & all_safe qs
safe :: Int -> [Int] -> Int -> Bool
safe _ [] _ = True
safe q (q1:qs) p = no_attack q q1 p & safe q qs (p+#1)
no_attack q1 q2 p = q1 /=# q2 & q1 /=# q2+#p & q1 /=# q2-#p
gen_vars n = if n==0 then [] else var : gen_vars (n-1) where var free
-- queens [] 8 l where l free
-- queens [FirstFail] 16 l where l free
import CLP.FD
-- solving the n-queens problem in Curry with FD constraints:
queens :: [Option] -> Int -> [Int]
queens options n =
let qs = take n (domain 1 n)
in solveFD options qs (allSafe qs)
allSafe :: [FDExpr] -> FDConstr
allSafe [] = true
allSafe (q:qs) = safe q qs (fd 1) /\ allSafe qs
safe :: FDExpr -> [FDExpr] -> FDExpr -> FDConstr
safe _ [] _ = true
safe q (q1:qs) p = no_attack q q1 p /\ safe q qs (p + fd 1)
no_attack :: FDExpr -> FDExpr -> FDExpr -> FDConstr
no_attack q1 q2 p = q1 /=# q2 /\ q1 /=# q2+p /\ q1 /=# q2-p
-------------------------------------------------------------------------
ex1 = queens [] 8
ex2 = queens [FirstFail] 16
import CLPFD
-- send more money puzzle in Curry with FD constraints:
smm l =
l =:= [s,e,n,d,m,o,r,y] &
domain l 0 9 &
s ># 0 &
m ># 0 &
allDifferent l &
1000 *# s +# 100 *# e +# 10 *# n +# d
+# 1000 *# m +# 100 *# o +# 10 *# r +# e
=# 10000 *# m +# 1000 *# o +# 100 *# n +# 10 *# e +# y &
labeling [] l
where s,e,n,d,m,o,r,y free
-- smm [s,e,n,d,m,o,r,y] where s,e,n,d,m,o,r,y free
import CLP.FD
-- send more money puzzle in Curry with FD constraints:
smm :: [Int]
smm =
let xs@[s,e,n,d,m,o,r,y] = take 8 (domain 0 9)
in solveFD [] xs $
s ># 0 /\
m ># 0 /\
allDifferent xs /\
1000 * s + 100 * e + 10 * n + d
+ 1000 * m + 100 * o + 10 * r + e
=# 10000 * m + 1000 * o + 100 * n + 10 * e + y
-- smm --> [9,5,6,7,1,0,8,2]
-----------------------------------------------------------------------------
--- Solving Su Doku puzzles in Curry with FD constraints
---
--- @author Michael Hanus
--- @version February 2013
-----------------------------------------------------------------------------
import CLPFD
import List(transpose)
import Constraint(allC)
-- Solving a Su Doku puzzle represented as a matrix of numbers (possibly free
-- variables):
sudoku :: [[Int]] -> Bool
sudoku m =
domain (concat m) 1 9 & -- define domain of all digits
allC allDifferent m & -- all rows contain different digits
allC allDifferent (transpose m) & -- all columns have different digits
allC allDifferent (squares m) & -- all 3x3 squares are different
labeling [FirstFail] (concat m)
where
-- translate a matrix into a list of small 3x3 squares
squares :: [[a]] -> [[a]]
squares [] = []
squares (l1:l2:l3:ls) = group3Rows [l1,l2,l3] ++ squares ls
group3Rows l123 = if null (head l123) then [] else
concatMap (take 3) l123 : group3Rows (map (drop 3) l123)
-- read a Su Doku specification written as a list of strings containing digits
-- and spaces
readSudoku :: [String] -> [[Int]]
readSudoku = map (map (\c -> if c==' ' then _ else ord c - ord '0'))
-- show a solved Su Doku matrix
showSudoku :: [[Int]] -> String
showSudoku = unlines . map (concatMap (\i->[chr (i + ord '0'),' ']))
-- the main function, e.g., evaluate (main s1):
main s | sudoku m = putStrLn (showSudoku m)
where m = readSudoku s
s1 = ["9 2 5 ",
" 4 6 3 ",
" 3 6",
" 9 2 ",
" 5 8 ",
" 7 4 3",
"7 1 ",
" 5 2 4 ",
" 1 6 9"]
s2 = ["819 5 ",
" 2 75 ",
" 371 4 6 ",
"4 59 1 ",
"7 3 8 2",
" 3 62 7",
" 5 7 921 ",
" 64 9 ",
" 2 438"]
s3 = [" 63 8 ",
" 1 ",
"327 1 ",
"9 2 3 ",
" 6 4 ",
" 3 4 9",
" 8 627",
" 6 ",
" 4 51 "]
-----------------------------------------------------------------------------
--- Solving Su Doku puzzles in Curry with FD constraints
---
--- @author Michael Hanus
--- @version September 2015
-----------------------------------------------------------------------------
{-# OPTIONS_CYMAKE -Wno-incomplete-patterns #-}
import CLP.FD
import List(transpose)
-- Solving a Su Doku puzzle represented as a matrix of numbers (possibly free
-- variables):
sudoku :: [[FDExpr]] -> [Int]
sudoku m = solveFD [FirstFail] (concat m) $
allC allDifferent m /\ -- all rows contain different digits
allC allDifferent (transpose m) /\ -- all columns have different digits
allC allDifferent (squares m) -- all 3x3 squares are different
where
-- translate a matrix into a list of small 3x3 squares
squares :: [[a]] -> [[a]]
squares [] = []
squares (l1:l2:l3:ls) = group3Rows [l1,l2,l3] ++ squares ls
group3Rows l123 = if null (head l123) then [] else
concatMap (take 3) l123 : group3Rows (map (drop 3) l123)
-- read a Su Doku specification written as a list of strings containing digits
-- and spaces
readSudoku :: [String] -> [[FDExpr]]
readSudoku = map (map (\c -> if c==' ' then head (domain 1 9)
else fd (ord c - ord '0')))
-- show a solved Su Doku matrix
showSudoku :: [[Int]] -> String
showSudoku = unlines . map (concatMap (\i->[chr (i + ord '0'),' ']))
-- the main function, e.g., evaluate (main s1):
main :: [[Char]] -> IO ()
main s = putStrLn (showSudoku (toMatrix m (sudoku m)))
where m = readSudoku s
toMatrix [] xs = [xs]
toMatrix (r:rs) xs = let rn = length r
in take rn xs : toMatrix rs (drop rn xs)
s1 :: [[Char]]
s1 = ["9 2 5 ",
" 4 6 3 ",
" 3 6",
" 9 2 ",
" 5 8 ",
" 7 4 3",
"7 1 ",
" 5 2 4 ",
" 1 6 9"]
s2 :: [[Char]]
s2 = ["819 5 ",
" 2 75 ",
" 371 4 6 ",
"4 59 1 ",
"7 3 8 2",
" 3 62 7",
" 5 7 921 ",
" 64 9 ",
" 2 438"]
s3 :: [[Char]]
s3 = [" 63 8 ",
" 1 ",
"327 1 ",
"9 2 3 ",
" 6 4 ",
" 3 4 9",
" 8 627",
" 6 ",
" 4 51 "]
-- A simple desk calculator GUI where the local state is stored in an IORef.
import GUI
import Char
import IOExts -- use IORefs for the GUI state
-- the GUI needs a reference to the calculator state
calcGUI :: IORef (Int,Int->Int) -> Widget
calcGUI stateref =
Col [] [
Entry [WRef display, Text "0", Background "yellow"],
Row [] (map cbutton ['1','2','3','+']),
Row [] (map cbutton ['4','5','6','-']),
Row [] (map cbutton ['7','8','9','*']),
Row [] (map cbutton ['C','0','=','/'])]
where
display free
cbutton c = Button (buttonPressed c) [Text [c]]
buttonPressed c gp = do
state <- readIORef stateref
let (d,f) = processButton c state
writeIORef stateref (d,f)
setValue display (show d) gp
-- compute new state when a button is pressed:
processButton :: Char -> (Int,Int->Int) -> (Int,Int->Int)
processButton b (d,f)
| isDigit b = (10*d + ord b - ord '0', f)
| b=='+' = (0,((f d) + ))
| b=='-' = (0,((f d) - ))
| b=='*' = (0,((f d) * ))
| b=='/' = (0,((f d) `div` ))
| b=='=' = (f d, id)
| b=='C' = (0, id)
main = do
stateref <- newIORef (0,id)
runGUI "Calculator" (calcGUI stateref)
-- a simple demo for checkbuttons in the GUI library
import GUI
checkbuttonWidget =
Col [] [
Label [Text "CheckButton Demo:"],
Entry [WRef vresult, Text "off", Background "yellow"],
Row [] [CheckButton [Text "Check1", CheckInit "1", WRef vc1,
Cmd showChecks],
CheckButton [Text "Check2", WRef vc2,
Cmd showChecks],
Button exitGUI [Text "Stop"]]]
where vc1, vc2, vresult free
showChecks gport =
do c1 <- getValue vc1 gport
c2 <- getValue vc2 gport
setValue vresult ("Check 1: "++c1++" / Check 2: "++c2) gport
main = runGUI "CheckButton Demo" checkbuttonWidget
-- A simple demo for dynamic reconfiguration of widget options:
import GUI
widget =
Col [] [
Label [Text "Text of buttons below:"],
EntryScroll [WRef tentry, Text "Stop", Background "white",
Command changetext],
Label [Text "Background color of exit button below:"],
Row []
[Entry [WRef centry, Text "red", Background "white",
Command changecolor],
PlainButton [Command changecolorp, Text "Select from palette"]],
CheckButton [WRef actbutton, Text "Deactivate buttons below",
Command deactivate],
Button (\_->putStrLn "XXX") [WRef prtbutton, Text "Print 'XXX'"],
Button exitGUI [WRef stopbutton, Text "Stop", Background "red"]]
where
tentry,centry,actbutton,prtbutton,stopbutton free
changetext wp = do
text <- getValue tentry wp
focusInput centry wp
return
[WidgetConf stopbutton (Text text), -- change button text
WidgetConf prtbutton (Text ("Print '"++text++"'")), --change button text
WidgetConf prtbutton (Cmd (\_->putStrLn text))] -- change button command
changecolor wp = do
color <- getValue centry wp
return [WidgetConf stopbutton (Background color)]
changecolorp _ = do
color <- chooseColor
return [WidgetConf stopbutton (Background color)]
deactivate wp = do
act <- getValue actbutton wp
return [WidgetConf stopbutton (Active (act=="0")),
WidgetConf prtbutton (Text ""),
WidgetConf prtbutton (Cmd (\_->done))]
main = runGUI "Config Demo" widget
------------------------------------------------------------------------------
-- A simple counter demo for the GUI library
------------------------------------------------------------------------------
import GUI
import Read
counterGUI =
Col [] [
Label [Text "A simple counter:"],
Entry [WRef val, Text "0", Background "yellow"],
Row [] [Button (updateValue incrText val) [Text "Increment"],
Button (setValue val "0") [Text "Reset"],
Button exitGUI [Text "Stop"]]]
where val free
incrText s = show (readInt s + 1)
main = runGUI "Counter Demo" counterGUI
-- A simple counter demo for the GUI library:
--
-- This counter GUI can be controlled not only by the user
-- but also by external processes that send messages to the GUI
--
-- IMPORTANT NOTE: Due to a bug in older versions of Sicstus-Prolog,
-- you need version 3.8.5 (or newer) to execute this program
-- (without "segmentation violation")
import Ports
import GUI
import Read
-- The messages that can be sent to the counter GUI:
data Msg = Set Int
-- The definition of the counter GUI together with a handler
-- "ext_handler" that is responsible to handler the external messages:
counter_gui =
(Col [] [
Label [Text "A simple counter:"],
Entry [WRef val, Text "0", Background "yellow"],
Row [] [Button (updateValue incrText val) [Text "Increment"],
Button (setValue val "0") [Text "Reset"],
Button exitGUI [Text "Stop"]]], ext_handler)
where val free
incrText s = show (readInt s + 1)
ext_handler (Set v) gp = setValue val (show v) gp
-- start the counter GUI: messages can be sent to this GUI
-- via the external port "test@<this_machine>":
main =
do msgs <- openNamedPort "test"
runControlledGUI "Counter Demo" counter_gui msgs
-- the value of the counter can be externally set to i by this function:
-- (change the value "localhost" to the name of your machine)
client i =
do p <- connectPort "test@localhost"
doSend (Set i) p
-- A simple counter demo for the GUI library.
--
-- This counter GUI can be controlled not only by GUI buttons
-- but also by inputs from the terminal.
--
-- IMPORTANT NOTE: Due to a bug in older versions of Sicstus-Prolog,
-- you need version 3.8.5 (or newer) to execute this program
-- (without "segmentation violation")
import IO
import GUI
import Read
-- The definition of the counter GUI together with a handler
-- "ext_handler" that is responsible to handle the external messages:
counterGUI =
(Col [] [
Label [Text "A simple counter:"],