Skip to content

Commit 4396b7f

Browse files
committed
Implement part of XCSP3 internal structure Part 1
1 parent 2f50967 commit 4396b7f

File tree

11 files changed

+1497
-0
lines changed

11 files changed

+1497
-0
lines changed

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
*.jl.*.cov
2+
*.jl.cov
3+
*.mem
4+
/docs/build/
5+
.gitignore
6+
_git2_*
7+
8+
/.benchmarkci
9+
/benchmark/*.json
10+
11+
*Manifest.toml
12+
13+
/extra_md/
14+
/xcsp3*

Project.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,18 @@ uuid = "bb10fa4c-83a6-4385-9a0a-8a86edc06950"
33
authors = ["Jean-François BAFFIER (@Azzaare)"]
44
version = "0.0.1"
55

6+
[deps]
7+
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
8+
EzXML = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615"
9+
TestItems = "1c621080-faea-4a02-84b6-bbd5e436b8fe"
10+
611
[compat]
12+
Aqua = "0.8"
13+
DataStructures = "0.18"
14+
EzXML = "1"
15+
JET = "0.9"
16+
Test = "1"
17+
TestItems = "1"
718
julia = "1.10"
819

920
[extras]

src/XCSP3.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
11
module XCSP3
22

33
#SECTION - Imports
4+
import DataStructures
5+
import EzXML
46
import TestItems: @testitem
57

68
#SECTION - Exports
9+
export AbstractObjective, ObjectiveType, MinimizeObjective, MaximizeObjective
10+
export Expression, Sum, Minimum, Maximum, NValues, Lex
11+
export AbstractConstraint, IntensionConstraint, ExtensionConstraint
12+
export RegularConstraint, MDDConstraint
13+
export Instance
714

815
#SECTION - Includes
16+
include("variable.jl")
17+
include("objective.jl")
18+
include("constraint.jl")
19+
include("constraints/intension.jl")
20+
include("constraints/extension.jl")
21+
include("constraints/regular.jl")
22+
include("constraints/mdd.jl")
23+
include("instance.jl")
924

1025
#SECTION - Main function (optional)
1126

src/constraint.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# constraint.jl
2+
3+
"""
4+
AbstractConstraint is the supertype for all constraints in XCSP3.
5+
"""
6+
abstract type AbstractConstraint end

src/constraints/extension.jl

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# constraints/extension.jl
2+
3+
"""
4+
ExtensionConstraint{T1, T2}
5+
6+
Represents an extension constraint in XCSP3, defined by a list of variables and tuples.
7+
8+
XML Structure for non-unary positive table constraints:
9+
```xml
10+
<extension>
11+
<list> (intVar wspace)2+ </list>
12+
<supports> ("(" intVal ("," intVal)+ ")")* </supports>
13+
</extension>
14+
```
15+
16+
XML Structure for non-unary negative table constraints:
17+
```xml
18+
<extension>
19+
<list> (intVar wspace)2+ </list>
20+
<conflicts> ("(" intVal ("," intVal)+ ")")* </conflicts>
21+
</extension>
22+
```
23+
24+
XML Structure for unary positive table constraints:
25+
```xml
26+
<extension>
27+
<list> intVar </list>
28+
<supports> ((intVal | intIntvl) wspace)* </supports>
29+
</extension>
30+
```
31+
32+
XML Structure for unary negative table constraints:
33+
```xml
34+
<extension>
35+
<list> intVar </list>
36+
<conflicts> ((intVal | intIntvl) wspace)* </conflicts>
37+
</extension>
38+
```
39+
40+
Examples:
41+
```julia
42+
# Ternary constraint with supports (Example 26 from XCSP3 spec)
43+
# <extension id="c1">
44+
# <list> x1 x2 x3 </list>
45+
# <supports> (0,1,0)(1,0,0)(1,1,0)(1,1,1) </supports>
46+
# </extension>
47+
ExtensionConstraint(
48+
id = "c1",
49+
list = ["x1", "x2", "x3"],
50+
supports = [[0, 1, 0], [1, 0, 0], [1, 1, 0], [1, 1, 1]]
51+
)
52+
53+
# Quaternary constraint with conflicts (Example 26 from XCSP3 spec)
54+
# <extension id="c2">
55+
# <list> y1 y2 y3 y4 </list>
56+
# <conflicts> (1,2,3,4)(3,1,3,4) </conflicts>
57+
# </extension>
58+
ExtensionConstraint(
59+
id = "c2",
60+
list = ["y1", "y2", "y3", "y4"],
61+
conflicts = [[1, 2, 3, 4], [3, 1, 3, 4]]
62+
)
63+
64+
# Unary constraint with supports (Example 27 from XCSP3 spec)
65+
# <extension id="c3">
66+
# <list> x </list>
67+
# <supports> 1 2 4 8..10 </supports>
68+
# </extension>
69+
ExtensionConstraint(
70+
id = "c3",
71+
list = ["x"],
72+
supports = [1, 2, 4, 8, 9, 10] # Note: Intervals expanded to individual values
73+
)
74+
75+
# Short table constraint (Example 28 from XCSP3 spec)
76+
# <extension id="c4">
77+
# <list> z1 z2 z3 z4 </list>
78+
# <supports> (1,*,1,2)(2,1,*,*) </supports>
79+
# </extension>
80+
ExtensionConstraint(
81+
id = "c4",
82+
list = ["z1", "z2", "z3", "z4"],
83+
supports = [[1, "*", 1, 2], [2, 1, "*", "*"]] # "*" represents any value
84+
)
85+
```
86+
"""
87+
struct ExtensionConstraint{T1, T2, T3} <: AbstractConstraint
88+
id::String # Optional ID, empty string if not provided
89+
list::Vector{T1} # Variables involved
90+
supports::Vector{T2} # List of support tuples (can be empty)
91+
conflicts::Vector{T3} # List of conflict tuples (can be empty)
92+
end
93+
94+
# Constructor for non-unary constraints with supports
95+
function ExtensionConstraint(;
96+
id::AbstractString = "",
97+
list::Vector,
98+
supports = Vector{Vector{Number}}(),
99+
conflicts = Vector{Vector{Number}}(),
100+
)
101+
sup = supports isa Vector ? supports : Vector(supports)
102+
conf = conflicts isa Vector ? conflicts : Vector(conflicts)
103+
T1, T2, T3 = eltype(list), eltype(sup), eltype(conf)
104+
return ExtensionConstraint{T1, T2, T3}(id, list, sup, conf)
105+
end
106+
107+
## SECTION - Test items
108+
109+
@testitem "ExtensionConstraint" tags=[:constraints, :extension] begin
110+
import XCSP3: ExtensionConstraint
111+
112+
# Test examples from XCSP3 specification
113+
114+
# Example 26: Ternary constraint with supports
115+
# <extension id="c1">
116+
# <list> x1 x2 x3 </list>
117+
# <supports> (0,1,0)(1,0,0)(1,1,0)(1,1,1) </supports>
118+
# </extension>
119+
@test begin
120+
ctr = ExtensionConstraint(;
121+
id = "c1",
122+
list = ["x1", "x2", "x3"],
123+
supports = [[0, 1, 0], [1, 0, 0], [1, 1, 0], [1, 1, 1]],
124+
)
125+
ctr.id == "c1" &&
126+
ctr.list == ["x1", "x2", "x3"] &&
127+
length(ctr.supports) == 4 &&
128+
isempty(ctr.conflicts)
129+
end
130+
131+
# Example 26: Quaternary constraint with conflicts
132+
# <extension id="c2">
133+
# <list> y1 y2 y3 y4 </list>
134+
# <conflicts> (1,2,3,4)(3,1,3,4) </conflicts>
135+
# </extension>
136+
@test begin
137+
ctr = ExtensionConstraint(;
138+
id = "c2",
139+
list = ["y1", "y2", "y3", "y4"],
140+
conflicts = [[1, 2, 3, 4], [3, 1, 3, 4]],
141+
)
142+
ctr.id == "c2" &&
143+
ctr.list == ["y1", "y2", "y3", "y4"] &&
144+
isempty(ctr.supports) &&
145+
length(ctr.conflicts) == 2
146+
end
147+
148+
# Example 27: Unary constraint with supports
149+
# <extension id="c3">
150+
# <list> x </list>
151+
# <supports> 1 2 4 8..10 </supports>
152+
# </extension>
153+
@test begin
154+
ctr = ExtensionConstraint(;
155+
id = "c3",
156+
list = ["x"],
157+
supports = [1, 2, 4, 8, 9, 10], # Note: Intervals expanded to individual values
158+
)
159+
ctr.id == "c3" &&
160+
ctr.list == ["x"] &&
161+
length(ctr.supports) == 6 &&
162+
isempty(ctr.conflicts)
163+
end
164+
165+
# Example 28: Short table constraint
166+
# <extension id="c4">
167+
# <list> z1 z2 z3 z4 </list>
168+
# <supports> (1,*,1,2)(2,1,*,*) </supports>
169+
# </extension>
170+
@test begin
171+
ctr = ExtensionConstraint(;
172+
id = "c4",
173+
list = ["z1", "z2", "z3", "z4"],
174+
supports = [[1, "*", 1, 2], [2, 1, "*", "*"]], # "*" represents any value
175+
)
176+
ctr.id == "c4" &&
177+
ctr.list == ["z1", "z2", "z3", "z4"] &&
178+
length(ctr.supports) == 2 &&
179+
isempty(ctr.conflicts)
180+
end
181+
end

src/constraints/intension.jl

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# constraints/intension.jl
2+
3+
"""
4+
IntensionConstraint
5+
6+
Represents an intension constraint in XCSP3, defined by a Boolean expression.
7+
8+
XML Structure:
9+
```xml
10+
<intension>
11+
<function> boolExpr </function>
12+
</intension>
13+
```
14+
15+
Note that the opening and closing tags for <function> are optional, which gives:
16+
```xml
17+
<intension> boolExpr </intension>
18+
```
19+
20+
The function expression must follow XCSP3 functional notation:
21+
- Operators: eq, ne, lt, le, gt, ge, not, and, or, xor, iff, imp
22+
- Functions: add, sub, mul, div, mod, sqr, neg, abs, min, max, dist
23+
- Variables: referenced directly by name
24+
- Constants: integers
25+
26+
Example:
27+
```julia
28+
# Using the _function keyword (matching full XML syntax)
29+
IntensionConstraint(id="c1", _function="eq(add(x,y),z)") # x + y = z with ID "c1"
30+
31+
# Using direct expression (matching simplified XML syntax)
32+
IntensionConstraint("c2", "lt(x,y)") # x < y with ID "c2"
33+
34+
# Without ID
35+
IntensionConstraint(nothing, "eq(add(x,y),z)") # x + y = z without ID
36+
```
37+
"""
38+
struct IntensionConstraint <: AbstractConstraint
39+
id::String # Optional ID, empty string if not provided
40+
expression::String # Boolean expression in functional form
41+
42+
# Inner constructor
43+
function IntensionConstraint(id::String, expression::String)
44+
@assert !isempty(expression) "Function expression cannot be empty"
45+
return new(id, expression)
46+
end
47+
end
48+
49+
# Constructor for simplified syntax (direct expression)
50+
function IntensionConstraint(id::Union{String, Nothing}, expression::String)
51+
# Create the constraint
52+
return IntensionConstraint(isnothing(id) ? "" : string(id), expression)
53+
end
54+
55+
# External constructor with keyword arguments matching XML structure
56+
function IntensionConstraint(;
57+
id::Union{String, Nothing} = nothing,
58+
_function::String, # Parameter matching XML tag (with underscore)
59+
)
60+
# Call the constructor
61+
return IntensionConstraint(id, _function)
62+
end
63+
64+
## SECTION - Test items
65+
66+
@testitem "IntensionConstraint" tags=[:constraints, :intension] begin
67+
import XCSP3: IntensionConstraint
68+
69+
# Test examples from XCSP3 specification
70+
71+
# Example with function tag:
72+
# <intension id="c1">
73+
# <function> eq(add(x,y),z) </function>
74+
# </intension>
75+
@test begin
76+
ctr = IntensionConstraint(id = "c1", _function = "eq(add(x,y),z)")
77+
ctr.id == "c1" && ctr.expression == "eq(add(x,y),z)"
78+
end
79+
80+
# Example with function tag:
81+
# <intension id="c2">
82+
# <function> ge(w,z) </function>
83+
# </intension>
84+
@test begin
85+
ctr = IntensionConstraint(id = "c2", _function = "ge(w,z)")
86+
ctr.id == "c2" && ctr.expression == "ge(w,z)"
87+
end
88+
89+
# Example in simplified form:
90+
# <intension id="c1"> eq(add(x,y),z) </intension>
91+
@test begin
92+
ctr = IntensionConstraint("c1", "eq(add(x,y),z)")
93+
ctr.id == "c1" && ctr.expression == "eq(add(x,y),z)"
94+
end
95+
96+
# Example in simplified form:
97+
# <intension id="c2"> ge(w,z) </intension>
98+
@test begin
99+
ctr = IntensionConstraint("c2", "ge(w,z)")
100+
ctr.id == "c2" && ctr.expression == "ge(w,z)"
101+
end
102+
end

0 commit comments

Comments
 (0)