From b90b54a77211d4c2d2daa8f22e024a5ddbf36ab4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Baffier Date: Thu, 30 May 2024 14:50:42 +0900 Subject: [PATCH] CI improvements (and cleaning) (#44) * Add Aqua and other CI. Clean unused learning scripts. * Clean old format icn output * Spelling --- .JuliaFormatter.toml | 1 + .github/workflows/CompatHelper.yml | 37 ++++++-- .github/workflows/SpellCheck.yml | 13 +++ .github/workflows/TagBot.yml | 16 ++++ .github/workflows/ci.yml | 111 +++++++++++++++++------- .github/workflows/register.yml | 16 ++++ Project.toml | 3 +- README.md | 6 +- docs/Project.toml | 5 -- docs/make.jl | 33 ------- docs/src/domain.md | 7 -- docs/src/icn.md | 58 ------------- docs/src/index.md | 44 ---------- docs/src/internal.md | 11 --- docs/src/learning.md | 69 --------------- docs/src/public.md | 11 --- learning/Project.toml | 5 -- learning/learn.jl | 88 ------------------- src/Constraints.jl | 3 +- src/compositions/icn_all_different.jl | 7 -- src/compositions/icn_all_equal.jl | 23 ----- src/compositions/icn_all_equal_param.jl | 7 -- src/compositions/icn_eq.jl | 7 -- src/compositions/icn_less_than_param.jl | 7 -- src/compositions/icn_ordered.jl | 7 -- src/constraint.jl | 35 ++++---- src/constraints/all_different.jl | 17 ++-- src/constraints/all_equal.jl | 24 ++--- src/constraints/cardinality.jl | 61 ++++++------- src/constraints/channel.jl | 24 ++--- src/constraints/circuit.jl | 2 +- src/constraints/count.jl | 16 ++-- src/constraints/cumulative.jl | 38 ++++---- src/constraints/element.jl | 21 ++--- src/constraints/extension.jl | 54 ++++++++---- src/constraints/instantiation.jl | 16 ++-- src/constraints/intention.jl | 9 +- src/constraints/maximum.jl | 4 +- src/constraints/mdd.jl | 36 ++++---- src/constraints/minimum.jl | 4 +- src/constraints/n_values.jl | 4 +- src/constraints/no_overlap.jl | 75 +++++++++------- src/constraints/ordered.jl | 6 +- src/constraints/regular.jl | 12 +-- src/constraints/sum.jl | 4 +- src/usual_constraints.jl | 84 ++++++++++-------- test/Aqua.jl | 32 +++++++ test/TestItemRunner.jl | 3 + test/runtests.jl | 7 +- 49 files changed, 509 insertions(+), 674 deletions(-) create mode 100644 .JuliaFormatter.toml create mode 100644 .github/workflows/SpellCheck.yml create mode 100644 .github/workflows/register.yml delete mode 100644 docs/Project.toml delete mode 100644 docs/make.jl delete mode 100644 docs/src/domain.md delete mode 100644 docs/src/icn.md delete mode 100644 docs/src/index.md delete mode 100644 docs/src/internal.md delete mode 100644 docs/src/learning.md delete mode 100644 docs/src/public.md delete mode 100644 learning/Project.toml delete mode 100644 learning/learn.jl delete mode 100644 src/compositions/icn_all_different.jl delete mode 100644 src/compositions/icn_all_equal.jl delete mode 100644 src/compositions/icn_all_equal_param.jl delete mode 100644 src/compositions/icn_eq.jl delete mode 100644 src/compositions/icn_less_than_param.jl delete mode 100644 src/compositions/icn_ordered.jl create mode 100644 test/Aqua.jl create mode 100644 test/TestItemRunner.jl diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml new file mode 100644 index 0000000..453925c --- /dev/null +++ b/.JuliaFormatter.toml @@ -0,0 +1 @@ +style = "sciml" \ No newline at end of file diff --git a/.github/workflows/CompatHelper.yml b/.github/workflows/CompatHelper.yml index cba9134..5577817 100644 --- a/.github/workflows/CompatHelper.yml +++ b/.github/workflows/CompatHelper.yml @@ -1,16 +1,43 @@ -name: CompatHelper on: schedule: - cron: 0 0 * * * workflow_dispatch: +permissions: + contents: write + pull-requests: write jobs: CompatHelper: runs-on: ubuntu-latest steps: - - name: Pkg.add("CompatHelper") - run: julia -e 'using Pkg; Pkg.add("CompatHelper")' - - name: CompatHelper.main() + - name: Check if Julia is already available in the PATH + id: julia_in_path + run: which julia + continue-on-error: true + - name: Install Julia, but only if it is not already available in the PATH + uses: julia-actions/setup-julia@v1 + with: + version: "1" + arch: ${{ runner.arch }} + if: steps.julia_in_path.outcome != 'success' + - name: "Add the General registry via Git" + run: | + import Pkg + ENV["JULIA_PKG_SERVER"] = "" + Pkg.Registry.add("General") + shell: julia --color=yes {0} + - name: "Install CompatHelper" + run: | + import Pkg + name = "CompatHelper" + uuid = "aa819f21-2bde-4658-8897-bab36330d9b7" + version = "3" + Pkg.add(; name, uuid, version) + shell: julia --color=yes {0} + - name: "Run CompatHelper" + run: | + import CompatHelper + CompatHelper.main() + shell: julia --color=yes {0} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }} - run: julia -e 'using CompatHelper; CompatHelper.main()' diff --git a/.github/workflows/SpellCheck.yml b/.github/workflows/SpellCheck.yml new file mode 100644 index 0000000..ed4fe17 --- /dev/null +++ b/.github/workflows/SpellCheck.yml @@ -0,0 +1,13 @@ +name: Spell Check + +on: [pull_request] + +jobs: + typos-check: + name: Spell Check with Typos + runs-on: ubuntu-latest + steps: + - name: Checkout Actions Repository + uses: actions/checkout@v4 + - name: Check spelling + uses: crate-ci/typos@v1.18.0 diff --git a/.github/workflows/TagBot.yml b/.github/workflows/TagBot.yml index f49313b..0cd3114 100644 --- a/.github/workflows/TagBot.yml +++ b/.github/workflows/TagBot.yml @@ -4,6 +4,22 @@ on: types: - created workflow_dispatch: + inputs: + lookback: + default: "3" +permissions: + actions: read + checks: read + contents: write + deployments: read + issues: read + discussions: read + packages: read + pages: read + pull-requests: read + repository-projects: read + security-events: read + statuses: read jobs: TagBot: if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0416bf4..74f28b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,48 @@ name: CI on: - - pull_request + pull_request: + branches: + - main + - dev + paths-ignore: + - "docs/**" + push: + branches: + - main + paths-ignore: + - "docs/**" jobs: + formatter: + runs-on: ${{ matrix.os }} + strategy: + matrix: + julia-version: [1] + julia-arch: [x86] + os: [ubuntu-latest] + steps: + - uses: julia-actions/setup-julia@latest + with: + version: ${{ matrix.julia-version }} + + - uses: actions/checkout@v4 + - name: Install JuliaFormatter and format + # This will use the latest version by default but you can set the version like so: + # + # julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter", version="0.13.0"))' + run: | + julia -e 'using Pkg; Pkg.add(PackageSpec(name="JuliaFormatter", version="1.0.50"))' + julia -e 'using JuliaFormatter; format(".", verbose=true)' + - name: Format check + run: | + julia -e ' + out = Cmd(`git diff`) |> read |> String + if out == "" + exit(0) + else + @error "Some files have not been formatted !!!" + write(stdout, out) + exit(1) + end' test: name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} runs-on: ${{ matrix.os }} @@ -9,27 +50,32 @@ jobs: fail-fast: false matrix: version: - - "1.10" - - 'nightly' + - "1.8" + - "1" # automatically expands to the latest stable 1.x release of Julia + - nightly os: - ubuntu-latest - - macOS-latest - - windows-latest arch: - x64 - x86 - exclude: + include: + # test macOS and Windows with latest Julia only - os: macOS-latest - arch: x86 + arch: x64 + version: 1 + - os: windows-latest + arch: x64 + version: 1 - os: windows-latest arch: x86 + version: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: actions/cache@v1 + - uses: actions/cache@v4 env: cache-name: cache-artifacts with: @@ -42,28 +88,29 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v4 with: file: lcov.info - docs: - name: Documentation - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@v1 - with: - version: "1" - - run: | - julia --project=docs -e ' - using Pkg - Pkg.develop(PackageSpec(path=pwd())) - Pkg.instantiate()' - - run: | - julia --project=docs -e ' - using Documenter: doctest - using Constraints - doctest(Constraints)' - - run: julia --project=docs docs/make.jl - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} + # docs: + # name: Documentation + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - uses: julia-actions/setup-julia@v1 + # with: + # version: "1" + # - run: | + # julia --project=docs -e ' + # using Pkg + # Pkg.develop(PackageSpec(path=pwd())) + # Pkg.instantiate()' + # - run: | + # julia --project=docs -e ' + # using Documenter: DocMeta, doctest + # using Constraints + # DocMeta.setdocmeta!(Constraints, :DocTestSetup, :(using Constraints); recursive=true) + # doctest(Constraints)' + # - run: julia --project=docs docs/make.jl + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} diff --git a/.github/workflows/register.yml b/.github/workflows/register.yml new file mode 100644 index 0000000..5b7cd3b --- /dev/null +++ b/.github/workflows/register.yml @@ -0,0 +1,16 @@ +name: Register Package +on: + workflow_dispatch: + inputs: + version: + description: Version to register or component to bump + required: true +jobs: + register: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: julia-actions/RegisterAction@latest + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Project.toml b/Project.toml index 7c0bcfa..8ed8239 100644 --- a/Project.toml +++ b/Project.toml @@ -27,7 +27,8 @@ TestItems = "0.1" julia = "1.8" [extras] +Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] -test = ["Test"] +test = ["Aqua", "Test"] diff --git a/README.md b/README.md index 5fbbec7..f4fc51c 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ # Constraints.jl -A back-end pacage for JuliaConstraints front packages, such as `LocalSearchSolvers.jl`. +A back-end package for JuliaConstraints front packages, such as `LocalSearchSolvers.jl`. It provides the following features: -- A dictionary to store usual constraint: `usual_contraint`, which contains the following entries +- A dictionary to store usual constraint: `usual_constraint`, which contains the following entries - `:all_different` - `:dist_different` - `:eq`, `:all_equal`, `:all_equal_param` @@ -23,7 +23,7 @@ It provides the following features: - error (a function that evaluate how much `c` is violated) - parameters length - known symmetries of `c` -- A learning function using `CompositionalNetworks.jl`. If no error function is given when instanciating `c`, it will check the existence of a composition related to `c` and set the error to it. +- A learning function using `CompositionalNetworks.jl`. If no error function is given when instantiating `c`, it will check the existence of a composition related to `c` and set the error to it. ## Contributing diff --git a/docs/Project.toml b/docs/Project.toml deleted file mode 100644 index 8889d0e..0000000 --- a/docs/Project.toml +++ /dev/null @@ -1,5 +0,0 @@ -[deps] -CompositionalNetworks = "4b67e4b5-442d-4ef5-b760-3f5df3a57537" -ConstraintDomains = "5800fd60-8556-4464-8d61-84ebf7a0bedb" -Constraints = "30f324ab-b02d-43f0-b619-e131c61659f7" -Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" diff --git a/docs/make.jl b/docs/make.jl deleted file mode 100644 index bb2c1ff..0000000 --- a/docs/make.jl +++ /dev/null @@ -1,33 +0,0 @@ -using Constraints -using CompositionalNetworks -using ConstraintDomains -using Documenter - -makedocs(; - modules=[Constraints, ConstraintDomains, CompositionalNetworks], - authors="Jean-François Baffier", - repo="https://github.com/JuliaConstraints/Constraints.jl/blob/{commit}{path}#L{line}", - sitename="Constraints.jl", - format=Documenter.HTML(; - prettyurls=get(ENV, "CI", nothing) == "true", - canonical="https://JuliaConstraints.github.io/Constraints.jl", - assets = ["assets/favicon.ico"; "assets/github_buttons.js"; "assets/custom.css"], - ), - pages=[ - "Home" => "index.md", - "Learning (ICN)" => "learning.md", - "Dependencies" => [ - "ConstraintDomains.jl" => "domain.md", - "CompositionalNetworks.jl" => "icn.md", - ], - "Library" => [ - "Public" => "public.md", - "Internal" => "internal.md" - ], - ], -) - -deploydocs(; - repo="github.com/JuliaConstraints/Constraints.jl.git", - devbranch="main", -) diff --git a/docs/src/domain.md b/docs/src/domain.md deleted file mode 100644 index 64ae2b4..0000000 --- a/docs/src/domain.md +++ /dev/null @@ -1,7 +0,0 @@ -# ConstraintDomains.jl - -Currently only discrete domains are supported using the following function. - -```@docs -ConstraintDomains.domain -``` \ No newline at end of file diff --git a/docs/src/icn.md b/docs/src/icn.md deleted file mode 100644 index 3ae214f..0000000 --- a/docs/src/icn.md +++ /dev/null @@ -1,58 +0,0 @@ -# CompositionalNetworks.jl - -```@contents -Pages = ["public.md"] -Depth = 5 -``` - -`CompositionalNetworks.jl`, a Julia package for Interpretable Compositional Networks (ICN), a variant of neural networks, allowing the user to get interpretable results, unlike regular artificial neural networks. - -The current state of our ICN focuses on the composition of error functions for `LocalSearchSolvers.jl`, but produces results independently of it and export it to either/both Julia functions or/and human readable output. - -### How does it work? - -The package comes with a basic ICN for learning global constraints. The ICN is composed of 4 layers: `transformation`, `arithmetic`, `aggregation`, and `comparison`. Each contains several operations that can be composed in various ways. -Given a `concept` (a predicate over the variables' domains), a metric (`hamming` by default), and the variables' domains, we learn the binary weights of the ICN. - -## Installation - -```julia -] add CompositionalNetworks -``` - -As the package is in a beta version, some changes in the syntax and features are likely to occur. However, those changes should be minimal between minor versions. Please update with caution. - -## Quickstart - -```julia -# 4 variables in 1:4 -doms = [domain([1,2,3,4]) for i in 1:4] - -# allunique concept (that is used to define the :all_different constraint) -err = explore_learn_compose(allunique, domains=doms) -# > interpretation: identity ∘ count_positive ∘ sum ∘ count_eq_left - -# test our new error function -@assert err([1,2,3,3], dom_size = 4) > 0.0 - -# export an all_different function to file "current/path/test_dummy.jl" -compose_to_file!(icn, "all_different", "test_dummy.jl") -``` - -The output file should produces a function that can be used as follows (assuming the maximum domain size is `7`) - -```julia -import CompositionalNetworks - -all_different([1,2,3,4,5,6,7]; dom_size = 7) -# > 0.0 (which means true, no errors) -``` - -Please see `JuliaConstraints/Constraints.jl/learn.jl` for an extensive example of ICN learning and compositions. - -## Public interface - -```@autodocs -Modules = [CompositionalNetworks] -Private = false -``` diff --git a/docs/src/index.md b/docs/src/index.md deleted file mode 100644 index e321f45..0000000 --- a/docs/src/index.md +++ /dev/null @@ -1,44 +0,0 @@ -```@meta -CurrentModule = Constraints -``` - -# Constraints.jl - -A back-end pacage for JuliaConstraints front packages, such as `LocalSearchSolvers.jl`. - -It provides the following features: -- A dictionary to store usual constraint: `usual_contraint`, which contains the following entries - - `:all_different` - - `:dist_different` - - `:eq`, `:all_equal`, `:all_equal_param` - - `:ordered` - - `:always_true` (mainly for testing default `Constraint()` constructor) -- For each constraint `c`, the following properties - - arguments length - - concept (predicate the variables compliance with `c`) - - error (a function that evaluate how much `c` is violated) - - parameters length - - known symmetries of `c` -- A learning function using `CompositionalNetworks.jl`. If no error function is given when instanciating `c`, it will check the existence of a composition related to `c` and set the error to it. - -Follow the list of the constraints currently stored in `usual_constraint`. Note that if the constraint is named `_my_constraint`, it can be accessed as `usual_contraint[:my_constraint]`. - -```@docs -Constraints._all_different -Constraints._all_equal -Constraints._all_equal_param -Constraints._dist_different -Constraints._eq -Constraints._ordered -``` - -## Contributing - -Contributions to this package are more than welcome and can be arbitrarily, and not exhaustively, split as follows: -- Adding new constraints and symmetries -- Adding new ICNs to learn error of existing constraints -- Creating other compositional networks which target other kind of constraints -- Just making stuff better, faster, user-friendlier, etc. - -### Contact -Do not hesitate to contact me (@azzaare) or other members of JuliaConstraints on GitHub (file an issue), the julialang discourse forum, the julialang slack channel, the julialang zulip server, or the Human of Julia (HoJ) discord server. \ No newline at end of file diff --git a/docs/src/internal.md b/docs/src/internal.md deleted file mode 100644 index 2b6de61..0000000 --- a/docs/src/internal.md +++ /dev/null @@ -1,11 +0,0 @@ -# Internal - -```@contents -Pages = ["internal.md"] -Depth = 5 -``` - -```@autodocs -Modules = [Constraints] -Public = false -``` diff --git a/docs/src/learning.md b/docs/src/learning.md deleted file mode 100644 index 3cedc31..0000000 --- a/docs/src/learning.md +++ /dev/null @@ -1,69 +0,0 @@ -# Learning through ICNs - -This feature is very basic so far, and should follow the procedure below -- Make the package a dev version `] dev Constraints` -- (Recommended) In `user_home/.julia/dev/Constraints`, `git checkout -b newcomposition` -- Define a new constraint `_c` and add it to `usual_constraint` in `Constraints.jl` -- Add it to the list of constraints to be learned in `learn.jl` (check the function below) -- Enter a new julia session, and run - ```julia - using Constraints - Constraints.learn_from_icn() - ``` -- Run tests: `] test Constraints` -- Commit, push, and make a draft PR to the dev branch - -```julia -function learn_from_icn() - targets = Dict( - :all_different => Dict( - :domains => [domain([1,2,3,4]) for i in 1:4], - ), - :dist_different => Dict( - :domains => [domain(Vector(1:4)) for i in 1:4], - ), - :ordered => Dict( - :domains => [domain([1,2,3,4]) for i in 1:4], - ), - :all_equal => Dict( - :domains => [domain([1,2,3,4]) for i in 1:4], - ), - :eq => Dict( - :domains => [domain(Vector(1:10)) for i in 1:2], - ), - :all_equal_param => Dict( - :domains => [domain(Vector(8:12)) for i in 1:4], - :param => 10, - ), - ) - - config = Dict( - :local_iter => 100, - :global_iter => 10, - :search => :complete, - :metric => hamming, - :population => 400, - ) - - path = joinpath(dirname(pathof(Constraints)),"compositions") - - for t in targets - @info "Starting learning for $(t.first)" - name = "_icn_$(t.first)" - compose_to_file!( - concept(usual_constraints[t.first]), - name, - joinpath(path, "$name.jl"); - domains=t.second[:domains], - param=get(t.second, :param, nothing), - local_iter=config[:local_iter], - global_iter=config[:global_iter], - search=config[:search], - metric=config[:metric], - popSize=config[:population], - language=:Julia, - ) - end - -end -``` \ No newline at end of file diff --git a/docs/src/public.md b/docs/src/public.md deleted file mode 100644 index 1afde1f..0000000 --- a/docs/src/public.md +++ /dev/null @@ -1,11 +0,0 @@ -# Public - -```@contents -Pages = ["public.md"] -Depth = 5 -``` - -```@autodocs -Modules = [Constraints] -Private = false -``` diff --git a/learning/Project.toml b/learning/Project.toml deleted file mode 100644 index 932828e..0000000 --- a/learning/Project.toml +++ /dev/null @@ -1,5 +0,0 @@ -[deps] -CompositionalNetworks = "4b67e4b5-442d-4ef5-b760-3f5df3a57537" -ConstraintDomains = "5800fd60-8556-4464-8d61-84ebf7a0bedb" -ConstraintLearning = "4bd09668-9077-4be7-adc9-6307a490e6df" -Constraints = "30f324ab-b02d-43f0-b619-e131c61659f7" diff --git a/learning/learn.jl b/learning/learn.jl deleted file mode 100644 index a04786d..0000000 --- a/learning/learn.jl +++ /dev/null @@ -1,88 +0,0 @@ -using CompositionalNetworks -using ConstraintDomains -using ConstraintLearning -using Constraints - -# FIXME - Commented concept have a new name -const DEFAULT_TARGETS = Dict( - :all_different => Dict( - :domains => [domain(1:4) for i in 1:4], - ), - :all_equal => Dict( - :domains => [domain(1:4) for i in 1:4], - ), - :all_equal_param => Dict( - :domains => [domain(8:12) for i in 1:4], - :param => 10, - ), - :dist_different => Dict( - :domains => [domain(1:4) for i in 1:4], - ), - :eq => Dict( - :domains => [domain(1:10) for i in 1:2], - ), - # :less_than_param => Dict( - # :domains => [domain(0:4) for i in 1:1], - # :param => 2, - # ), - # :minus_equal_param => Dict( - # :domains => [domain(0:4) for i in 1:2], - # :param => 3, - # ), - :ordered => Dict( - :domains => [domain(1:4) for i in 1:4], - ), - # :sequential_tasks => Dict( - # :domains => [domain(1:4) for i in 1:4], - # ), - # :sum_equal_param => Dict( - # :domains => [domain(1:9) for i in 1:3], - # :param => 15, - # ), -) - -const DEFAULT_CONFIG = Dict( - :lang => :Julia, - :local_iter => 100, - :global_iter => 100, - :search => :complete, - :metric => hamming, - :population => 400, -) - -const DEFAULT_PATH = joinpath(dirname(pathof(Constraints)), "compositions") - -function learn_from_icn(; - targets=DEFAULT_TARGETS, - config=DEFAULT_CONFIG, - path=DEFAULT_PATH -) - optimizer = ICNGeneticOptimizer(; - global_iter=config[:global_iter], - local_iter=config[:local_iter], - pop_size=config[:population] - ) - for t in targets - @info "Starting learning for $(t.first)" - con = concept(usual_constraints[t.first]) - domains = t.second[:domains] - param = get(t.second, :param, nothing) - settings = ExploreSettings(domains; search=config[:search]) - configurations = explore(domains, con; param, settings) - name = "icn_$(t.first)" - compose_to_file!( - con, - name, - joinpath(path, "$name.jl"); - configurations, - domains, - optimizer, - param, - metric=config[:metric] - ) - println() - end - -end - -learn_from_icn() diff --git a/src/Constraints.jl b/src/Constraints.jl index d8d2446..b5b1e5f 100644 --- a/src/Constraints.jl +++ b/src/Constraints.jl @@ -25,7 +25,7 @@ export constraints_descriptions export describe export error_f export extract_parameters -export learn_from_icn +# export learn_from_icn export params_length export symmetries @@ -73,5 +73,4 @@ include("constraints/circuit.jl") # SECTION - Elementary Constraints include("constraints/instantiation.jl") - end diff --git a/src/compositions/icn_all_different.jl b/src/compositions/icn_all_different.jl deleted file mode 100644 index 0125c22..0000000 --- a/src/compositions/icn_all_different.jl +++ /dev/null @@ -1,7 +0,0 @@ -function icn_all_different(x; X = zeros(length(x), 1), param=nothing, dom_size) - CompositionalNetworks.tr_in(Tuple([CompositionalNetworks.tr_count_eq_left]), X, x, param) - for i in 1:length(x) - X[i,1] = CompositionalNetworks.ar_sum(@view X[i,:]) - end - return CompositionalNetworks.ag_count_positive(@view X[:, 1]) |> (y -> CompositionalNetworks.co_identity(y; param, dom_size, nvars=length(x))) -end diff --git a/src/compositions/icn_all_equal.jl b/src/compositions/icn_all_equal.jl deleted file mode 100644 index 79ddc50..0000000 --- a/src/compositions/icn_all_equal.jl +++ /dev/null @@ -1,23 +0,0 @@ -""" - icn_all_equal(x; X = zeros(length(x), 3), param=nothing, dom_size) - -Composition `icn_all_equal` generated by CompositionalNetworks.jl. -``` -icn_all_equal = euclidian ∘ count_positive ∘ sum ∘ [contiguous_vals_minus, count_l_left, count_greater] -``` -""" -function icn_all_equal(x; X=zeros(length(x), 3), param=nothing, dom_size) - CompositionalNetworks.tr_in( - Tuple([ - CompositionalNetworks.tr_contiguous_vals_minus, - CompositionalNetworks.tr_count_l_left, - CompositionalNetworks.tr_count_greater, - ]), - X, - x, - param, - ) - X[:, 1] .= 1:length(x) .|> (i -> CompositionalNetworks.ar_sum(@view X[i, 1:3])) - return CompositionalNetworks.ag_count_positive(@view X[:, 1]) |> - (y -> CompositionalNetworks.co_euclidian(y; param, dom_size, nvars=length(x))) -end diff --git a/src/compositions/icn_all_equal_param.jl b/src/compositions/icn_all_equal_param.jl deleted file mode 100644 index 695b6fb..0000000 --- a/src/compositions/icn_all_equal_param.jl +++ /dev/null @@ -1,7 +0,0 @@ -function icn_all_equal_param(x; X = zeros(length(x), 2), param=nothing, dom_size) - CompositionalNetworks.tr_in(Tuple([CompositionalNetworks.tr_param_minus_val, CompositionalNetworks.tr_val_minus_param]), X, x, param) - for i in 1:length(x) - X[i,1] = CompositionalNetworks.ar_sum(@view X[i,:]) - end - return CompositionalNetworks.ag_count_positive(@view X[:, 1]) |> (y -> CompositionalNetworks.co_identity(y; param, dom_size, nvars=length(x))) -end diff --git a/src/compositions/icn_eq.jl b/src/compositions/icn_eq.jl deleted file mode 100644 index 6282cf0..0000000 --- a/src/compositions/icn_eq.jl +++ /dev/null @@ -1,7 +0,0 @@ -function icn_eq(x; X = zeros(length(x), 1), param=nothing, dom_size) - CompositionalNetworks.tr_in(Tuple([CompositionalNetworks.tr_count_greater]), X, x, param) - for i in 1:length(x) - X[i,1] = CompositionalNetworks.ar_sum(@view X[i,:]) - end - return CompositionalNetworks.ag_sum(@view X[:, 1]) |> (y -> CompositionalNetworks.co_identity(y; param, dom_size, nvars=length(x))) -end diff --git a/src/compositions/icn_less_than_param.jl b/src/compositions/icn_less_than_param.jl deleted file mode 100644 index 891f76b..0000000 --- a/src/compositions/icn_less_than_param.jl +++ /dev/null @@ -1,7 +0,0 @@ -function icn_less_than_param(x; X = zeros(length(x), 1), param=nothing, dom_size) - CompositionalNetworks.tr_in(Tuple([CompositionalNetworks.tr_val_minus_param]), X, x, param) - for i in 1:length(x) - X[i,1] = CompositionalNetworks.ar_sum(@view X[i,:]) - end - return CompositionalNetworks.ag_count_positive(@view X[:, 1]) |> (y -> CompositionalNetworks.co_identity(y; param, dom_size, nvars=length(x))) -end diff --git a/src/compositions/icn_ordered.jl b/src/compositions/icn_ordered.jl deleted file mode 100644 index 219d96d..0000000 --- a/src/compositions/icn_ordered.jl +++ /dev/null @@ -1,7 +0,0 @@ -function icn_ordered(x; X = zeros(length(x), 1), param=nothing, dom_size) - CompositionalNetworks.tr_in(Tuple([CompositionalNetworks.tr_contiguous_vals_minus]), X, x, param) - for i in 1:length(x) - X[i,1] = CompositionalNetworks.ar_sum(@view X[i,:]) - end - return CompositionalNetworks.ag_count_positive(@view X[:, 1]) |> (y -> CompositionalNetworks.co_identity(y; param, dom_size, nvars=length(x))) -end diff --git a/src/constraint.jl b/src/constraint.jl index 2ab242a..83417c4 100644 --- a/src/constraint.jl +++ b/src/constraint.jl @@ -6,28 +6,33 @@ const USUAL_SYMMETRIES = Dict(:permutable => sort) """ Constraint -Parametric stucture with the following fields. +Parametric structure with the following fields. - `concept`: a Boolean function that, given an assignment `x`, outputs `true` if `x` satisfies the constraint, and `false` otherwise. -- `error`: a positive function that works as preferences over invalid assignements. Return `0.0` if the constraint is satisfied, and a strictly positive real otherwise. +- `error`: a positive function that works as preferences over invalid assignments. Return `0.0` if the constraint is satisfied, and a strictly positive real otherwise. """ -mutable struct Constraint{FConcept<:Function,FError<:Function} +mutable struct Constraint{FConcept <: Function, FError <: Function} args::Int concept::FConcept description::String error::FError - params::Vector{Dict{Symbol,Bool}} + params::Vector{Dict{Symbol, Bool}} symmetries::Set{Symbol} function Constraint(; - args=0, - concept=x -> true, - description="No given description!", - error=(x; param=0, dom_size=0) -> Float64(!concept(x)), - params=Vector{Dict{Symbol,Bool}}(), - syms=Set{Symbol}() + args = 0, + concept = x -> true, + description = "No given description!", + error = (x; param = 0, dom_size = 0) -> Float64(!concept(x)), + params = Vector{Dict{Symbol, Bool}}(), + syms = Set{Symbol}() ) - return new{typeof(concept),typeof(error)}( - args, concept, description, error, params, syms + return new{typeof(concept), typeof(error)}( + args, + concept, + description, + error, + params, + syms ) end end @@ -39,7 +44,7 @@ Return the concept (function) of constraint `c`. Apply the concept of `c` to values `x` and optionally `param`. """ concept(c::Constraint) = c.concept -function concept(c::Constraint, x; param=nothing) +function concept(c::Constraint, x; param = nothing) return isnothing(param) ? concept(c)(x) : concept(c)(x; param) end @@ -50,7 +55,7 @@ Return the error function of constraint `c`. Apply the error function of `c` to values `x` and optionally `param`. """ error_f(c::Constraint) = c.error -function error_f(c::Constraint, x; param=nothing, dom_size=0) +function error_f(c::Constraint, x; param = nothing, dom_size = 0) return isnothing(param) ? error_f(c)(x; dom_size) : error_f(c)(x; param, dom_size) end @@ -125,7 +130,7 @@ concept_vs_error(all_different, make_error(:all_different), [1, 2, 3]) # Returns function concept_vs_error(c, e, args...; kargs...) return c(args...; kargs...) ≠ (e(args...; kargs...) > 0.0) end -@testitem "Empty constraint" tags = [:constraint, :empty] begin +@testitem "Empty constraint" tags=[:constraint, :empty] begin c = Constraint() @test concept(c, []) == true @test error_f(c, []) == 0.0 diff --git a/src/constraints/all_different.jl b/src/constraints/all_different.jl index b4eec40..5bff73e 100644 --- a/src/constraints/all_different.jl +++ b/src/constraints/all_different.jl @@ -32,26 +32,27 @@ c([1, 0, 0, 1]; vals=[0]) xcsp_all_different(list, ::Nothing) = allunique(list) function xcsp_all_different(list, except) - return xcsp_all_different(list=Iterators.filter(x -> x ∉ except[:, 1], list)) + return xcsp_all_different(list = Iterators.filter(x -> x ∉ except[:, 1], list)) end -xcsp_all_different(; list, except=nothing) = xcsp_all_different(list, except) +xcsp_all_different(; list, except = nothing) = xcsp_all_different(list, except) -@usual concept_all_different(x; vals=nothing) = xcsp_all_different(list=x, except=vals) +@usual concept_all_different(x; vals = nothing) = xcsp_all_different( + list = x, except = vals) ## SECTION - Test Items -@testitem "All Different" tags = [:usual, :constraints, :all_different] begin +@testitem "All Different" tags=[:usual, :constraints, :all_different] begin c = USUAL_CONSTRAINTS[:all_different] |> concept e = USUAL_CONSTRAINTS[:all_different] |> error_f vs = Constraints.concept_vs_error @test c([1, 2, 3, 4]) @test !c([1, 2, 3, 1]) - @test c([1, 0, 0, 4]; vals=[0]) - @test !c([1, 0, 0, 1]; vals=[0]) + @test c([1, 0, 0, 4]; vals = [0]) + @test !c([1, 0, 0, 1]; vals = [0]) @test vs(c, e, [1, 2, 3, 4]) @test vs(c, e, [1, 2, 3, 1]) - @test vs(c, e, [1, 0, 0, 4]; vals=[0]) - @test vs(c, e, [1, 0, 0, 1]; vals=[0]) + @test vs(c, e, [1, 0, 0, 4]; vals = [0]) + @test vs(c, e, [1, 0, 0, 1]; vals = [0]) end diff --git a/src/constraints/all_equal.jl b/src/constraints/all_equal.jl index 0d28148..8c311ad 100644 --- a/src/constraints/all_equal.jl +++ b/src/constraints/all_equal.jl @@ -34,9 +34,9 @@ c([1, 2, 3, 4]; op=/, val=1, pair_vars=[1, 2, 3, 4]) c([1, 2, 3, 4]; op=*, val=1, pair_vars=[1, 2, 3, 4]) ``` """ -xcsp_all_equal(; list) = concept_all_equal(list; val=first(list)) +xcsp_all_equal(; list) = concept_all_equal(list; val = first(list)) -@usual function concept_all_equal(x; val=nothing, pair_vars=zero(x), op=+) +@usual function concept_all_equal(x; val = nothing, pair_vars = zero(x), op = +) if iszero(pair_vars) return concept_all_equal(x, val) else @@ -44,25 +44,25 @@ xcsp_all_equal(; list) = concept_all_equal(list; val=first(list)) return concept_all_equal(aux, val) end end -concept_all_equal(x, ::Nothing) = xcsp_all_equal(list=x) +concept_all_equal(x, ::Nothing) = xcsp_all_equal(list = x) ## SECTION - Test Items -@testitem "All Equal" tags = [:usual, :constraints, :all_equal] begin +@testitem "All Equal" tags=[:usual, :constraints, :all_equal] begin c = USUAL_CONSTRAINTS[:all_equal] |> concept e = USUAL_CONSTRAINTS[:all_equal] |> error_f vs = Constraints.concept_vs_error @test c([0, 0, 0, 0]) @test !c([1, 2, 3, 4]) - @test c([3, 2, 1, 0]; pair_vars=[0, 1, 2, 3]) - @test !c([0, 1, 2, 3]; pair_vars=[0, 1, 2, 3]) - @test c([1, 2, 3, 4]; op=/, val=1, pair_vars=[1, 2, 3, 4]) - @test !c([1, 2, 3, 4]; op=*, val=1, pair_vars=[1, 2, 3, 4]) + @test c([3, 2, 1, 0]; pair_vars = [0, 1, 2, 3]) + @test !c([0, 1, 2, 3]; pair_vars = [0, 1, 2, 3]) + @test c([1, 2, 3, 4]; op = /, val = 1, pair_vars = [1, 2, 3, 4]) + @test !c([1, 2, 3, 4]; op = *, val = 1, pair_vars = [1, 2, 3, 4]) @test vs(c, e, [0, 0, 0, 0]) @test vs(c, e, [1, 2, 3, 4]) - @test vs(c, e, [3, 2, 1, 0]; pair_vars=[0, 1, 2, 3]) - @test vs(c, e, [0, 1, 2, 3]; pair_vars=[0, 1, 2, 3]) - @test vs(c, e, [1, 2, 3, 4]; op=/, val=1, pair_vars=[1, 2, 3, 4]) - @test vs(c, e, [1, 2, 3, 4]; op=*, val=1, pair_vars=[1, 2, 3, 4]) + @test vs(c, e, [3, 2, 1, 0]; pair_vars = [0, 1, 2, 3]) + @test vs(c, e, [0, 1, 2, 3]; pair_vars = [0, 1, 2, 3]) + @test vs(c, e, [1, 2, 3, 4]; op = /, val = 1, pair_vars = [1, 2, 3, 4]) + @test vs(c, e, [1, 2, 3, 4]; op = *, val = 1, pair_vars = [1, 2, 3, 4]) end diff --git a/src/constraints/cardinality.jl b/src/constraints/cardinality.jl index e7c6f7a..6374f9a 100644 --- a/src/constraints/cardinality.jl +++ b/src/constraints/cardinality.jl @@ -59,7 +59,7 @@ co = concept(:cardinality_open) co([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) ``` """ -function xcsp_cardinality(; list, values, occurs, closed=false) +function xcsp_cardinality(; list, values, occurs, closed = false) counts = zeros(Int, Indices(distinct(values))) for t in list if t ∉ values @@ -75,54 +75,55 @@ function xcsp_cardinality(; list, values, occurs, closed=false) return true end -@usual function concept_cardinality(x; bool=false, vals) +@usual function concept_cardinality(x; bool = false, vals) values = vals[:, 1] occurs = if size(vals, 2) == 1 ones(Int, size(vals, 1)) elseif size(vals, 2) ≥ 3 - map(i -> vals[i, 2]:(vals[i, 2] ≤ vals[i, 3] ? 1 : -1):(vals[i, 3]), 1:size(vals, 1)) + map(i -> vals[i, 2]:(vals[i, 2] ≤ vals[i, 3] ? 1 : -1):(vals[i, 3]), + 1:size(vals, 1)) else vals[:, 2] end - return xcsp_cardinality(; list=x, values, occurs, closed=bool) + return xcsp_cardinality(; list = x, values, occurs, closed = bool) end -@usual concept_cardinality_closed(x; vals) = concept_cardinality(x; bool=true, vals) -@usual concept_cardinality_open(x; vals) = concept_cardinality(x; bool=false, vals) +@usual concept_cardinality_closed(x; vals) = concept_cardinality(x; bool = true, vals) +@usual concept_cardinality_open(x; vals) = concept_cardinality(x; bool = false, vals) ## SECTION - Test Items -@testitem "Cardinality" tags = [:usual, :constraints, :cardinality] begin +@testitem "Cardinality" tags=[:usual, :constraints, :cardinality] begin c = USUAL_CONSTRAINTS[:cardinality] |> concept e = USUAL_CONSTRAINTS[:cardinality] |> error_f vs = Constraints.concept_vs_error - @test c([2, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) - @test c([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3], bool=false) - @test !c([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3], bool=true) - @test c([2, 5, 10, 10]; vals=[2 1; 5 1; 10 2]) - @test c([2, 5, 10, 10]; vals=[2 0 1 42; 5 1 3 7; 10 2 3 -4]) - @test !c([2, 5, 5, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) - @test !c([2, 5, 10, 8]; vals=[2 1; 5 1; 10 2]) - @test !c([5, 5, 5, 10]; vals=[2 0 1 42; 5 1 3 7; 10 2 3 -4]) - - - @test vs(c, e, [2, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) - @test vs(c, e, [8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3], bool=false) - @test vs(c, e, [8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3], bool=true) - @test vs(c, e, [2, 5, 10, 10]; vals=[2 1; 5 1; 10 2]) - @test vs(c, e, [2, 5, 10, 10]; vals=[2 0 1 42; 5 1 3 7; 10 2 3 -4]) - @test vs(c, e, [2, 5, 5, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) - @test vs(c, e, [2, 5, 10, 8]; vals=[2 1; 5 1; 10 2]) - @test vs(c, e, [5, 5, 5, 10]; vals=[2 0 1 42; 5 1 3 7; 10 2 3 -4]) + @test c([2, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3]) + @test c([8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3], bool = false) + @test !c([8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3], bool = true) + @test c([2, 5, 10, 10]; vals = [2 1; 5 1; 10 2]) + @test c([2, 5, 10, 10]; vals = [2 0 1 42; 5 1 3 7; 10 2 3 -4]) + @test !c([2, 5, 5, 10]; vals = [2 0 1; 5 1 3; 10 2 3]) + @test !c([2, 5, 10, 8]; vals = [2 1; 5 1; 10 2]) + @test !c([5, 5, 5, 10]; vals = [2 0 1 42; 5 1 3 7; 10 2 3 -4]) + + @test vs(c, e, [2, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3]) + @test vs(c, e, [8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3], bool = false) + @test vs(c, e, [8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3], bool = true) + @test vs(c, e, [2, 5, 10, 10]; vals = [2 1; 5 1; 10 2]) + @test vs(c, e, [2, 5, 10, 10]; vals = [2 0 1 42; 5 1 3 7; 10 2 3 -4]) + @test vs(c, e, [2, 5, 5, 10]; vals = [2 0 1; 5 1 3; 10 2 3]) + @test vs(c, e, [2, 5, 10, 8]; vals = [2 1; 5 1; 10 2]) + @test vs(c, e, [5, 5, 5, 10]; vals = [2 0 1 42; 5 1 3 7; 10 2 3 -4]) cc = USUAL_CONSTRAINTS[:cardinality_closed] |> concept ec = USUAL_CONSTRAINTS[:cardinality_closed] |> error_f - @test cc([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) == c([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3], bool=true) - @test vs(cc, ec, [8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) + @test cc([8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3]) == + c([8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3], bool = true) + @test vs(cc, ec, [8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3]) co = USUAL_CONSTRAINTS[:cardinality_open] |> concept eo = USUAL_CONSTRAINTS[:cardinality_open] |> error_f - @test co([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) == c([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3], bool=false) - @test vs(co, eo, [8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) - + @test co([8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3]) == + c([8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3], bool = false) + @test vs(co, eo, [8, 5, 10, 10]; vals = [2 0 1; 5 1 3; 10 2 3]) end diff --git a/src/constraints/channel.jl b/src/constraints/channel.jl index 1b79f48..7af817f 100644 --- a/src/constraints/channel.jl +++ b/src/constraints/channel.jl @@ -59,17 +59,17 @@ function xcsp_channel(; list) end function concept_channel(x, ::Val{2}) mid = length(x) ÷ 2 - return xcsp_channel(list=(@view(x[1:mid]), @view(x[mid+1:end]))) + return xcsp_channel(list = (@view(x[1:mid]), @view(x[(mid + 1):end]))) end -concept_channel(x, ::Val) = xcsp_channel(list=x) +concept_channel(x, ::Val) = xcsp_channel(list = x) concept_channel(x, id) = count(!iszero, x) == 1 == x[id] -@usual function concept_channel(x; dim=1, id = nothing) +@usual function concept_channel(x; dim = 1, id = nothing) return isnothing(id) ? concept_channel(x, Val(dim)) : concept_channel(x, id) end -@testitem "Channel" tags = [:usual, :constraints, :channel] begin +@testitem "Channel" tags=[:usual, :constraints, :channel] begin c = USUAL_CONSTRAINTS[:channel] |> concept e = USUAL_CONSTRAINTS[:channel] |> error_f vs = Constraints.concept_vs_error @@ -77,16 +77,16 @@ end @test c([2, 1, 4, 3]) @test c([1, 2, 3, 4]) @test !c([2, 3, 1, 4]) - @test c([2, 1, 5, 3, 4, 2, 1, 4, 5, 3]; dim=2) - @test !c([2, 1, 4, 3, 5, 2, 1, 4, 5, 3]; dim=2) - @test c([false, false, true, false]; id=3) - @test !c([false, false, true, false]; id=1) + @test c([2, 1, 5, 3, 4, 2, 1, 4, 5, 3]; dim = 2) + @test !c([2, 1, 4, 3, 5, 2, 1, 4, 5, 3]; dim = 2) + @test c([false, false, true, false]; id = 3) + @test !c([false, false, true, false]; id = 1) @test vs(c, e, [2, 1, 4, 3]) @test vs(c, e, [1, 2, 3, 4]) @test vs(c, e, [2, 3, 1, 4]) - @test vs(c, e, [2, 1, 5, 3, 4, 2, 1, 4, 5, 3]; dim=2) - @test vs(c, e, [2, 1, 4, 3, 5, 2, 1, 4, 5, 3]; dim=2) - @test vs(c, e, [false, false, true, false]; id=3) - @test vs(c, e, [false, false, true, false]; id=1) + @test vs(c, e, [2, 1, 5, 3, 4, 2, 1, 4, 5, 3]; dim = 2) + @test vs(c, e, [2, 1, 4, 3, 5, 2, 1, 4, 5, 3]; dim = 2) + @test vs(c, e, [false, false, true, false]; id = 3) + @test vs(c, e, [false, false, true, false]; id = 1) end diff --git a/src/constraints/circuit.jl b/src/constraints/circuit.jl index c2f3bc4..a750dff 100644 --- a/src/constraints/circuit.jl +++ b/src/constraints/circuit.jl @@ -60,7 +60,7 @@ end end ## SECTION - Test Items -@testitem "Circuit" tags = [:usual, :constraints, :circuit] begin +@testitem "Circuit" tags=[:usual, :constraints, :circuit] begin c = USUAL_CONSTRAINTS[:circuit] |> concept e = USUAL_CONSTRAINTS[:circuit] |> error_f vs = Constraints.concept_vs_error diff --git a/src/constraints/count.jl b/src/constraints/count.jl index 44779e6..026db29 100644 --- a/src/constraints/count.jl +++ b/src/constraints/count.jl @@ -59,13 +59,14 @@ function xcsp_count(; list, values, condition) return condition[1](count(y -> y ∈ values, list), condition[2]) end -@usual concept_count(x; vals, op, val) = xcsp_count(list = x, values = vals, condition = (op, val)) +@usual concept_count(x; vals, op, val) = xcsp_count( + list = x, values = vals, condition = (op, val)) @usual concept_at_least(x; vals, val) = concept_count(x; vals, op = ≥, val) @usual concept_at_most(x; vals, val) = concept_count(x; vals, op = ≤, val) @usual concept_exactly(x; vals, val) = concept_count(x; vals, op = ==, val) ## SECTION - Test Items -@testitem "Count" tags = [:usual, :constraints, :count] begin +@testitem "Count" tags=[:usual, :constraints, :count] begin c = USUAL_CONSTRAINTS[:count] |> concept e = USUAL_CONSTRAINTS[:count] |> error_f vs = Constraints.concept_vs_error @@ -79,9 +80,12 @@ end c_exactly = USUAL_CONSTRAINTS[:exactly] |> concept e_exactly = USUAL_CONSTRAINTS[:exactly] |> error_f - @test c([2, 1, 4, 3]; vals = [1, 2, 3, 4], op = ≥, val = 2) && c_at_least([2, 1, 4, 3]; vals = [1, 2, 3, 4], val = 2) - @test c([1, 2, 3, 4]; vals = [1, 2], op = ==, val = 2) && c_exactly([1, 2, 3, 4]; vals = [1, 2], val = 2) - @test !c([2, 1, 4, 3]; vals = [1, 2], op = ≤, val = 1) && !c_at_most([2, 1, 4, 3]; vals = [1, 2], val = 1) + @test c([2, 1, 4, 3]; vals = [1, 2, 3, 4], op = ≥, val = 2) && + c_at_least([2, 1, 4, 3]; vals = [1, 2, 3, 4], val = 2) + @test c([1, 2, 3, 4]; vals = [1, 2], op = ==, val = 2) && + c_exactly([1, 2, 3, 4]; vals = [1, 2], val = 2) + @test !c([2, 1, 4, 3]; vals = [1, 2], op = ≤, val = 1) && + !c_at_most([2, 1, 4, 3]; vals = [1, 2], val = 1) @test vs(c, e, [2, 1, 4, 3]; vals = [1, 2, 3, 4], op = ≥, val = 2) @test vs(c_at_least, e_at_least, [2, 1, 4, 3]; vals = [1, 2, 3, 4], val = 2) @@ -89,4 +93,4 @@ end @test vs(c_exactly, e_exactly, [1, 2, 3, 4]; vals = [1, 2], val = 2) @test vs(c, e, [2, 1, 4, 3]; vals = [1, 2], op = ≤, val = 2) @test vs(c_at_most, e_at_most, [2, 1, 4, 3]; vals = [1, 2], val = 1) -end \ No newline at end of file +end diff --git a/src/constraints/cumulative.jl b/src/constraints/cumulative.jl index ab3abca..a80faa3 100644 --- a/src/constraints/cumulative.jl +++ b/src/constraints/cumulative.jl @@ -31,10 +31,10 @@ c([1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = <, val = 5) ``` """ function xcsp_cumulative(; origins, lengths, heights, condition) - tasks = Vector{Tuple{eltype(origins),eltype(origins)}}() + tasks = Vector{Tuple{eltype(origins), eltype(origins)}}() for t in Iterators.zip(origins, lengths, heights) push!(tasks, (t[1], t[3])) - push!(tasks,(t[1]+t[2], -t[3])) + push!(tasks, (t[1] + t[2], -t[3])) end η = zero(eltype(origins)) for t in sort!(tasks) @@ -46,30 +46,38 @@ end function concept_cumulative(x, pair_vars, op, val) return xcsp_cumulative( - origins=x, lengths=pair_vars[1,:], heights=pair_vars[2, :], condition=(op, val) + origins = x, + lengths = pair_vars[1, :], + heights = pair_vars[2, :], + condition = (op, val) ) end -function concept_cumulative(x, pair_vars::Vector{T}, op, val) where {T<:Number} +function concept_cumulative(x, pair_vars::Vector{T}, op, val) where {T <: Number} return concept_cumulative(x, fill(pair_vars, 2), op, val) end -@usual function concept_cumulative(x; pair_vars=ones(eltype(x), (2, length(x))), op=≤, val) +@usual function concept_cumulative( + x; + pair_vars = ones(eltype(x), (2, length(x))), + op = ≤, + val +) return concept_cumulative(x, pair_vars, op, val) end -@testitem "Cumulative" tags = [:usual, :constraints, :cumulative] begin +@testitem "Cumulative" tags=[:usual, :constraints, :cumulative] begin c = USUAL_CONSTRAINTS[:cumulative] |> concept e = USUAL_CONSTRAINTS[:cumulative] |> error_f vs = Constraints.concept_vs_error - @test c([1, 2, 3, 4, 5]; val=1) - @test !c([1, 2, 2, 4, 5]; val=1) - @test c([1, 2, 3, 4, 5]; pair_vars=[3 2 5 4 2; 1 2 1 1 3], op= ≤, val=5) - @test !c([1, 2, 3, 4, 5]; pair_vars=[3 2 5 4 2; 1 2 1 1 3], op= <, val=5) + @test c([1, 2, 3, 4, 5]; val = 1) + @test !c([1, 2, 2, 4, 5]; val = 1) + @test c([1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = ≤, val = 5) + @test !c([1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = <, val = 5) - @test vs(c, e, [1, 2, 3, 4, 5]; val=1) - @test vs(c, e, [1, 2, 2, 4, 5]; val=1) - @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars=[3 2 5 4 2; 1 2 1 1 3], op= ≤, val=5) - @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars=[3 2 5 4 2; 1 2 1 1 3], op= <, val=5) -end \ No newline at end of file + @test vs(c, e, [1, 2, 3, 4, 5]; val = 1) + @test vs(c, e, [1, 2, 2, 4, 5]; val = 1) + @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = ≤, val = 5) + @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = <, val = 5) +end diff --git a/src/constraints/element.jl b/src/constraints/element.jl index 341167c..8a681a3 100644 --- a/src/constraints/element.jl +++ b/src/constraints/element.jl @@ -41,31 +41,32 @@ function concept_element(x, id, op, val) end function concept_element(x, ::Nothing, op, ::Nothing) - return concept_element(x[2:end-1]; id=x[1], op, val=x[end]) + return concept_element(x[2:(end - 1)]; id = x[1], op, val = x[end]) end function concept_element(x, ::Nothing, op, val) - return concept_element(x[2:end]; id=x[1], op, val) + return concept_element(x[2:end]; id = x[1], op, val) end function concept_element(x, id, op, ::Nothing) - return concept_element(x[1:end-1]; id, op, val=x[end]) + return concept_element(x[1:(end - 1)]; id, op, val = x[end]) end -@usual concept_element(x; id = nothing, op = ==, val = nothing) = concept_element(x, id, op, val) +@usual concept_element(x; id = nothing, op = ==, val = nothing) = concept_element( + x, id, op, val) -@testitem "Element" tags = [:usual, :constraints, :element] begin +@testitem "Element" tags=[:usual, :constraints, :element] begin c = USUAL_CONSTRAINTS[:element] |> concept e = USUAL_CONSTRAINTS[:element] |> error_f vs = Constraints.concept_vs_error - @test c([1, 2, 3, 4, 5]; id=1, val=1) - @test !c([1, 2, 3, 4, 5]; id=1, val=2) + @test c([1, 2, 3, 4, 5]; id = 1, val = 1) + @test !c([1, 2, 3, 4, 5]; id = 1, val = 2) @test c([1, 2, 3, 4, 2]) @test !c([1, 2, 3, 4, 1]) - @test vs(c, e, [1, 2, 3, 4, 5]; id=1, val=1) - @test vs(c, e, [1, 2, 3, 4, 5]; id=1, val=2) + @test vs(c, e, [1, 2, 3, 4, 5]; id = 1, val = 1) + @test vs(c, e, [1, 2, 3, 4, 5]; id = 1, val = 2) @test vs(c, e, [1, 2, 3, 4, 2]) @test vs(c, e, [1, 2, 3, 4, 1]) -end \ No newline at end of file +end diff --git a/src/constraints/extension.jl b/src/constraints/extension.jl index e62b762..7b0e276 100644 --- a/src/constraints/extension.jl +++ b/src/constraints/extension.jl @@ -58,7 +58,7 @@ c = concept(:conflicts) c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) ``` """ -function xcsp_extension(; list, supports=nothing, conflicts=nothing) +function xcsp_extension(; list, supports = nothing, conflicts = nothing) return xcsp_extension(list, supports, conflicts) end @@ -78,7 +78,7 @@ end @usual concept_conflicts(x; pair_vars) = xcsp_extension(list = x, conflicts = pair_vars) -@testitem "Extension" tags = [:usual, :constraints, :extension] begin +@testitem "Extension" tags=[:usual, :constraints, :extension] begin c = USUAL_CONSTRAINTS[:extension] |> concept e = USUAL_CONSTRAINTS[:extension] |> error_f c_supports = USUAL_CONSTRAINTS[:supports] |> concept @@ -87,19 +87,37 @@ end e_conflicts = USUAL_CONSTRAINTS[:conflicts] |> error_f vs = Constraints.concept_vs_error - @test c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) - @test c([1, 2, 3, 4, 5]; pair_vars=([[1, 2, 3, 4, 5]], [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]])) - @test !c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) - @test c_supports([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) - @test !c_supports([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) - @test c_conflicts([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) - @test !c_conflicts([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) - - @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) - @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars=([[1, 2, 3, 4, 5]], [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]])) - @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) - @test vs(c_supports, e_supports, [1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) - @test vs(c_supports, e_supports, [1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) - @test vs(c_conflicts, e_conflicts, [1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) - @test vs(c_conflicts, e_conflicts, [1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) -end \ No newline at end of file + @test c([1, 2, 3, 4, 5]; pair_vars = [[1, 2, 3, 4, 5]]) + @test c( + [1, 2, 3, 4, 5]; + pair_vars = ([[1, 2, 3, 4, 5]], [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) + ) + @test !c([1, 2, 3, 4, 5]; pair_vars = [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) + @test c_supports([1, 2, 3, 4, 5]; pair_vars = [[1, 2, 3, 4, 5]]) + @test !c_supports([1, 2, 3, 4, 5]; pair_vars = [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) + @test c_conflicts([1, 2, 3, 4, 5]; pair_vars = [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) + @test !c_conflicts([1, 2, 3, 4, 5]; pair_vars = [[1, 2, 3, 4, 5]]) + + @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars = [[1, 2, 3, 4, 5]]) + @test vs( + c, + e, + [1, 2, 3, 4, 5]; + pair_vars = ([[1, 2, 3, 4, 5]], [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) + ) + @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars = [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) + @test vs(c_supports, e_supports, [1, 2, 3, 4, 5]; pair_vars = [[1, 2, 3, 4, 5]]) + @test vs( + c_supports, + e_supports, + [1, 2, 3, 4, 5]; + pair_vars = [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]] + ) + @test vs( + c_conflicts, + e_conflicts, + [1, 2, 3, 4, 5]; + pair_vars = [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]] + ) + @test vs(c_conflicts, e_conflicts, [1, 2, 3, 4, 5]; pair_vars = [[1, 2, 3, 4, 5]]) +end diff --git a/src/constraints/instantiation.jl b/src/constraints/instantiation.jl index 15afb4c..c29be0c 100644 --- a/src/constraints/instantiation.jl +++ b/src/constraints/instantiation.jl @@ -28,17 +28,17 @@ c([1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 6]) """ xcsp_instantiation(; list, values) = list == values +@usual concept_instantiation(x; pair_vars) = xcsp_instantiation( + list = x, values = pair_vars) -@usual concept_instantiation(x; pair_vars) = xcsp_instantiation(list=x, values=pair_vars) - -@testitem "Instantiation" tags = [:usual, :constraints, :instantiation] begin +@testitem "Instantiation" tags=[:usual, :constraints, :instantiation] begin c = USUAL_CONSTRAINTS[:instantiation] |> concept e = USUAL_CONSTRAINTS[:instantiation] |> error_f vs = Constraints.concept_vs_error - @test c([1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 5]) - @test !c([1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 6]) + @test c([1, 2, 3, 4, 5]; pair_vars = [1, 2, 3, 4, 5]) + @test !c([1, 2, 3, 4, 5]; pair_vars = [1, 2, 3, 4, 6]) - @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 5]) - @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 6]) -end \ No newline at end of file + @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars = [1, 2, 3, 4, 5]) + @test vs(c, e, [1, 2, 3, 4, 5]; pair_vars = [1, 2, 3, 4, 6]) +end diff --git a/src/constraints/intention.jl b/src/constraints/intention.jl index 421f9df..4494140 100644 --- a/src/constraints/intention.jl +++ b/src/constraints/intention.jl @@ -50,11 +50,10 @@ xcsp_intension(; list, predicate) = predicate(list) # Dist different TODO - check if a better name exists predicate_dist_different(x) = abs(x[1] - x[2]) ≠ abs(x[3] - x[4]) +@usual concept_dist_different(x) = xcsp_intension( + list = x, predicate = predicate_dist_different) - -@usual concept_dist_different(x) = xcsp_intension(list = x, predicate = predicate_dist_different) - -@testitem "Dist different (intension)" tags = [:usual, :constraints, :intension] begin +@testitem "Dist different (intension)" tags=[:usual, :constraints, :intension] begin c = USUAL_CONSTRAINTS[:dist_different] |> concept e = USUAL_CONSTRAINTS[:dist_different] |> error_f vs = Constraints.concept_vs_error @@ -64,4 +63,4 @@ predicate_dist_different(x) = abs(x[1] - x[2]) ≠ abs(x[3] - x[4]) @test vs(c, e, [1, 2, 3, 4]) @test vs(c, e, [1, 2, 3, 3]) -end \ No newline at end of file +end diff --git a/src/constraints/maximum.jl b/src/constraints/maximum.jl index 8f5e1d8..fba4278 100644 --- a/src/constraints/maximum.jl +++ b/src/constraints/maximum.jl @@ -30,7 +30,7 @@ xcsp_maximum(; list, condition) = condition[1](maximum(list), condition[2]) @usual concept_maximum(x; op = ==, val) = xcsp_maximum(; list = x, condition = (op, val)) -@testitem "Maximum" tags = [:usual, :constraints, :maximum] begin +@testitem "Maximum" tags=[:usual, :constraints, :maximum] begin c = USUAL_CONSTRAINTS[:maximum] |> concept e = USUAL_CONSTRAINTS[:maximum] |> error_f vs = Constraints.concept_vs_error @@ -40,4 +40,4 @@ xcsp_maximum(; list, condition) = condition[1](maximum(list), condition[2]) @test vs(c, e, [1, 2, 3, 4, 5]; op = ==, val = 5) @test vs(c, e, [1, 2, 3, 4, 5]; op = ==, val = 6) -end \ No newline at end of file +end diff --git a/src/constraints/mdd.jl b/src/constraints/mdd.jl index ae6b131..3ef7085 100644 --- a/src/constraints/mdd.jl +++ b/src/constraints/mdd.jl @@ -57,7 +57,7 @@ xcsp_mdd(; list, diagram) = accept(diagram, list) @usual concept_mdd(x; language) = xcsp_mdd(; list = x, diagram = language) -@testitem "MDD" tags = [:usual, :constraints, :mdd] default_imports = false begin +@testitem "MDD" tags=[:usual, :constraints, :mdd] default_imports=false begin using ConstraintCommons using Constraints using Test @@ -70,31 +70,31 @@ xcsp_mdd(; list, diagram) = accept(diagram, list) Dict( # level x1 (:r, 0) => :n1, (:r, 1) => :n2, - (:r, 2) => :n3, + (:r, 2) => :n3 ), Dict( # level x2 (:n1, 2) => :n4, (:n2, 2) => :n4, - (:n3, 0) => :n5, + (:n3, 0) => :n5 ), Dict( # level x3 (:n4, 0) => :t, - (:n5, 0) => :t, - ), + (:n5, 0) => :t + ) ] a = MDD(states) - @test c([0,2,0]; language = a) - @test c([1,2,0]; language = a) - @test c([2,0,0]; language = a) - @test !c([2,1,2]; language = a) - @test !c([1,0,2]; language = a) - @test !c([0,1,2]; language = a) - - @test vs(c, e, [0,2,0]; language = a) - @test vs(c, e, [1,2,0]; language = a) - @test vs(c, e, [2,0,0]; language = a) - @test vs(c, e, [2,1,2]; language = a) - @test vs(c, e, [1,0,2]; language = a) - @test vs(c, e, [0,1,2]; language = a) + @test c([0, 2, 0]; language = a) + @test c([1, 2, 0]; language = a) + @test c([2, 0, 0]; language = a) + @test !c([2, 1, 2]; language = a) + @test !c([1, 0, 2]; language = a) + @test !c([0, 1, 2]; language = a) + + @test vs(c, e, [0, 2, 0]; language = a) + @test vs(c, e, [1, 2, 0]; language = a) + @test vs(c, e, [2, 0, 0]; language = a) + @test vs(c, e, [2, 1, 2]; language = a) + @test vs(c, e, [1, 0, 2]; language = a) + @test vs(c, e, [0, 1, 2]; language = a) end diff --git a/src/constraints/minimum.jl b/src/constraints/minimum.jl index 109edb2..e70320b 100644 --- a/src/constraints/minimum.jl +++ b/src/constraints/minimum.jl @@ -30,7 +30,7 @@ xcsp_minimum(; list, condition) = condition[1](minimum(list), condition[2]) @usual concept_minimum(x; op = ==, val) = xcsp_minimum(; list = x, condition = (op, val)) -@testitem "Minimum" tags = [:usual, :constraints, :minimum] begin +@testitem "Minimum" tags=[:usual, :constraints, :minimum] begin c = USUAL_CONSTRAINTS[:minimum] |> concept e = USUAL_CONSTRAINTS[:minimum] |> error_f vs = Constraints.concept_vs_error @@ -40,4 +40,4 @@ xcsp_minimum(; list, condition) = condition[1](minimum(list), condition[2]) @test vs(c, e, [1, 2, 3, 4, 5]; op = ==, val = 1) @test vs(c, e, [1, 2, 3, 4, 5]; op = ==, val = 0) -end \ No newline at end of file +end diff --git a/src/constraints/n_values.jl b/src/constraints/n_values.jl index c44ea69..ad45f3a 100644 --- a/src/constraints/n_values.jl +++ b/src/constraints/n_values.jl @@ -47,7 +47,7 @@ xcsp_nvalues(; list, condition, except = nothing) = xcsp_nvalues(list, condition return xcsp_nvalues(list = x, condition = (op, val), except = vals) end -@testitem "nValues" tags = [:usual, :constraints, :nvalues] begin +@testitem "nValues" tags=[:usual, :constraints, :nvalues] begin c = USUAL_CONSTRAINTS[:nvalues] |> concept e = USUAL_CONSTRAINTS[:nvalues] |> error_f vs = Constraints.concept_vs_error @@ -61,4 +61,4 @@ end @test vs(c, e, [1, 2, 3, 4, 5]; op = ==, val = 2) @test vs(c, e, [1, 2, 3, 4, 3]; op = <=, val = 5) @test vs(c, e, [1, 2, 3, 4, 3]; op = <=, val = 3) -end \ No newline at end of file +end diff --git a/src/constraints/no_overlap.jl b/src/constraints/no_overlap.jl index 96f52b0..0904aaf 100644 --- a/src/constraints/no_overlap.jl +++ b/src/constraints/no_overlap.jl @@ -62,54 +62,64 @@ function xcsp_no_overlap(origins, lengths, zero_ignored) end function xcsp_no_overlap( - origins::AbstractVector{NTuple{K,T}}, - lengths::AbstractVector{NTuple{K,T}}, - zero_ignored, -) where {K,T<:Number} + origins::AbstractVector{NTuple{K, T}}, + lengths::AbstractVector{NTuple{K, T}}, + zero_ignored +) where {K, T <: Number} return all( dim -> xcsp_no_overlap(; - origins=map(t -> t[dim], origins), - lengths=map(t -> t[dim], lengths), - zero_ignored), - 1:K, + origins = map(t -> t[dim], origins), + lengths = map(t -> t[dim], lengths), + zero_ignored + ), + 1:K ) end -function xcsp_no_overlap(; origins, lengths, zero_ignored=true) +function xcsp_no_overlap(; origins, lengths, zero_ignored = true) return xcsp_no_overlap(origins, lengths, zero_ignored) end function concept_no_overlap(x, pair_vars, _, bool, ::Val{1}) - return xcsp_no_overlap(; origins=x, lengths=pair_vars[:,1], zero_ignored=bool) + return xcsp_no_overlap(; origins = x, lengths = pair_vars[:, 1], zero_ignored = bool) end function concept_no_overlap(x, pair_vars, dim, bool, _) l = Int(length(x) ÷ dim) # @info l x dim - origins = reinterpret(reshape, NTuple{dim,eltype(x)}, reshape(x, (dim, l))) - lengths = reinterpret(reshape, NTuple{dim,eltype(x)}, reshape(pair_vars[:,1], (dim, l))) - return xcsp_no_overlap(; origins, lengths, zero_ignored=bool) + origins = reinterpret(reshape, NTuple{dim, eltype(x)}, reshape(x, (dim, l))) + lengths = reinterpret( + reshape, NTuple{dim, eltype(x)}, reshape(pair_vars[:, 1], (dim, l))) + return xcsp_no_overlap(; origins, lengths, zero_ignored = bool) end @usual function concept_no_overlap( - x; - pair_vars=ones(eltype(x), length(x)), - dim=1, - bool=true + x; + pair_vars = ones(eltype(x), length(x)), + dim = 1, + bool = true ) idim = Int(dim) return concept_no_overlap(x, pair_vars, idim, bool, Val(idim)) end -@usual function concept_no_overlap_no_zero(x; pair_vars=ones(eltype(x), length(x)), dim=1) - return concept_no_overlap(x; pair_vars, dim, bool=true) +@usual function concept_no_overlap_no_zero( + x; + pair_vars = ones(eltype(x), length(x)), + dim = 1 +) + return concept_no_overlap(x; pair_vars, dim, bool = true) end -@usual function concept_no_overlap_with_zero(x; pair_vars=ones(eltype(x), length(x)), dim=1) - return concept_no_overlap(x; pair_vars, dim, bool=false) +@usual function concept_no_overlap_with_zero( + x; + pair_vars = ones(eltype(x), length(x)), + dim = 1 +) + return concept_no_overlap(x; pair_vars, dim, bool = false) end -@testitem "noOverlap" tags = [:usual, :constraints, :no_overlap] begin +@testitem "noOverlap" tags=[:usual, :constraints, :no_overlap] begin c = USUAL_CONSTRAINTS[:no_overlap] |> concept e = USUAL_CONSTRAINTS[:no_overlap] |> error_f vs = Constraints.concept_vs_error @@ -121,11 +131,13 @@ end @test !c([1, 2, 4, 6, 3]; pair_vars = [1, 1, 3, 1, 1]) @test c( [1, 1, 1, 3, 5, 2, 7, 7, 5, 12, 8, 7]; - pair_vars = [2, 4, 1, 4 ,2 ,3, 5, 1, 2, 3, 3, 2], dim = 3 + pair_vars = [2, 4, 1, 4, 2, 3, 5, 1, 2, 3, 3, 2], + dim = 3 ) @test !c( [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]; - pair_vars = [2, 4, 1, 4 ,2 ,3, 5, 1, 2, 3, 3, 2], dim = 3 + pair_vars = [2, 4, 1, 4, 2, 3, 5, 1, 2, 3, 3, 2], + dim = 3 ) @test vs(c, e, [1, 2, 3, 4, 5]) @@ -134,14 +146,17 @@ end @test vs(c, e, [1, 2, 4, 6, 3]; pair_vars = [1, 1, 1, 3, 1]) @test vs(c, e, [1, 2, 4, 6, 3]; pair_vars = [1, 1, 3, 1, 1]) @test vs( - c, e, + c, + e, [1, 1, 1, 3, 5, 2, 7, 7, 5, 12, 8, 7]; - pair_vars = [2, 4, 1, 4 ,2 ,3, 5, 1, 2, 3, 3, 2], dim = 3 + pair_vars = [2, 4, 1, 4, 2, 3, 5, 1, 2, 3, 3, 2], + dim = 3 ) @test vs( - c, e, + c, + e, [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]; - pair_vars = [2, 4, 1, 4 ,2 ,3, 5, 1, 2, 3, 3, 2], dim = 3 + pair_vars = [2, 4, 1, 4, 2, 3, 5, 1, 2, 3, 3, 2], + dim = 3 ) - -end \ No newline at end of file +end diff --git a/src/constraints/ordered.jl b/src/constraints/ordered.jl index 47a2523..3842196 100644 --- a/src/constraints/ordered.jl +++ b/src/constraints/ordered.jl @@ -84,11 +84,11 @@ xcsp_ordered(; list, operator, lengths = nothing) = xcsp_ordered(list, operator, return xcsp_ordered(list = x, operator = op, lengths = pair_vars) end @usual concept_increasing(x) = issorted(x) -@usual concept_decreasing(x) = issorted(x; rev=true) +@usual concept_decreasing(x) = issorted(x; rev = true) @usual concept_strictly_increasing(x) = concept_ordered(x; op = <) @usual concept_strictly_decreasing(x) = concept_ordered(x; op = >) -@testitem "Ordered" tags = [:usual, :constraints, :ordered] begin +@testitem "Ordered" tags=[:usual, :constraints, :ordered] begin c = USUAL_CONSTRAINTS[:ordered] |> concept e = USUAL_CONSTRAINTS[:ordered] |> error_f vs = Constraints.concept_vs_error @@ -102,4 +102,4 @@ end @test vs(c, e, [1, 2, 3, 4, 5]; op = <) @test vs(c, e, [1, 2, 3, 4, 3]; op = ≤) @test vs(c, e, [1, 2, 3, 4, 3]; op = <) -end \ No newline at end of file +end diff --git a/src/constraints/regular.jl b/src/constraints/regular.jl index cc10cad..71ffafc 100644 --- a/src/constraints/regular.jl +++ b/src/constraints/regular.jl @@ -44,7 +44,7 @@ xcsp_regular(; list, automaton) = accept(automaton, list) @usual concept_regular(x; language) = xcsp_regular(; list = x, automaton = language) -@testitem "regular" tags = [:usual, :constraints, :regular] default_imports = false begin +@testitem "regular" tags=[:usual, :constraints, :regular] default_imports=false begin using ConstraintCommons using Constraints using Test @@ -60,15 +60,15 @@ xcsp_regular(; list, automaton) = accept(automaton, list) (:c, 0) => :d, (:d, 0) => :d, (:d, 1) => :e, - (:e, 0) => :e, + (:e, 0) => :e ) start = :a finish = :e a = Automaton(states, start, finish) - @test c([0,0,1,1,0,0,1,0,0]; language = a) - @test !c([1,1,1,0,1]; language = a) + @test c([0, 0, 1, 1, 0, 0, 1, 0, 0]; language = a) + @test !c([1, 1, 1, 0, 1]; language = a) - @test vs(c, e, [0,0,1,1,0,0,1,0,0]; language = a) - @test vs(c, e, [1,1,1,0,1]; language = a) + @test vs(c, e, [0, 0, 1, 1, 0, 0, 1, 0, 0]; language = a) + @test vs(c, e, [1, 1, 1, 0, 1]; language = a) end diff --git a/src/constraints/sum.jl b/src/constraints/sum.jl index 3a02d18..0c393ee 100644 --- a/src/constraints/sum.jl +++ b/src/constraints/sum.jl @@ -35,7 +35,7 @@ xcsp_sum(; list, coeffs, condition) = condition[1](sum(coeffs .* list), conditio return xcsp_sum(list = x, coeffs = pair_vars, condition = (op, val)) end -@testitem "sum" tags = [:usual, :constraints, :sum] begin +@testitem "sum" tags=[:usual, :constraints, :sum] begin c = USUAL_CONSTRAINTS[:sum] |> concept e = USUAL_CONSTRAINTS[:sum] |> error_f vs = Constraints.concept_vs_error @@ -49,4 +49,4 @@ end @test vs(c, e, [1, 2, 3, 4, 5]; op = ==, val = 2) @test vs(c, e, [1, 2, 3, 4, 3]; op = <=, val = 15) @test vs(c, e, [1, 2, 3, 4, 3]; op = <=, val = 3) -end \ No newline at end of file +end diff --git a/src/usual_constraints.jl b/src/usual_constraints.jl index 155914a..267c514 100644 --- a/src/usual_constraints.jl +++ b/src/usual_constraints.jl @@ -9,7 +9,7 @@ Adding a new constraint is as simple as defining a new function with the same na @usual concept_all_different(x; vals=nothing) = xcsp_all_different(list=x, except=vals) ``` """ -const USUAL_CONSTRAINTS = Dict{Symbol,Constraint}(:always_true => Constraint()) +const USUAL_CONSTRAINTS = Dict{Symbol, Constraint}(:always_true => Constraint()) """ describe(constraints::Dict{Symbol,Constraint}=USUAL_CONSTRAINTS; width=150) @@ -25,8 +25,8 @@ Return a pretty table with the description of the constraints in `constraints`. describe() ``` """ -function describe(constraints::Dict{Symbol,Constraint}=USUAL_CONSTRAINTS; width=150) - df = DataFrame(; Names=Symbol[], Description=String[]) +function describe(constraints::Dict{Symbol, Constraint} = USUAL_CONSTRAINTS; width = 150) + df = DataFrame(; Names = Symbol[], Description = String[]) for (name, cons) in constraints push!(df, (name, cons.description)) end @@ -34,10 +34,10 @@ function describe(constraints::Dict{Symbol,Constraint}=USUAL_CONSTRAINTS; width= dl = maximum(c -> length(string(c.description)), values(USUAL_CONSTRAINTS)) return pretty_table( df; - columns_width=[l, min(dl, width - l)], - linebreaks=true, - autowrap=true, - alignment=:l + columns_width = [l, min(dl, width - l)], + linebreaks = true, + autowrap = true, + alignment = :l ) end @@ -57,9 +57,9 @@ extract_parameters(:all_different) ``` """ function ConstraintCommons.extract_parameters( - s::Symbol, - constraints_dict=USUAL_CONSTRAINTS; - parameters=ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS + s::Symbol, + constraints_dict = USUAL_CONSTRAINTS; + parameters = ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS ) return ConstraintCommons.extract_parameters(concept(constraints_dict[s]); parameters) end @@ -94,7 +94,7 @@ macro usual(ex::Expr) c = shrink_concept(s) # Dict storing the existence or not of a default value for each kwarg - defaults = Dict{Symbol,Bool}() + defaults = Dict{Symbol, Bool}() # Check if a `;` is present in the call, then loop over kwargs if length(ex.args[1].args) > 2 @@ -107,7 +107,6 @@ macro usual(ex::Expr) end end - error = make_error(c) concept = eval(ex) if haskey(USUAL_CONSTRAINTS, c) @@ -138,8 +137,18 @@ Return a pretty table with the parameters of the constraints in `C`. constraints_parameters() ``` """ -function constraints_parameters(C=USUAL_CONSTRAINTS) - df = DataFrame(Constraint=Symbol[], bool=String[], dim=String[], id=String[], language=String[], op=String[], pair_vars=String[], val=String[], vals=String[]) +function constraints_parameters(C = USUAL_CONSTRAINTS) + df = DataFrame( + Constraint = Symbol[], + bool = String[], + dim = String[], + id = String[], + language = String[], + op = String[], + pair_vars = String[], + val = String[], + vals = String[] + ) for (s, c) in C base = vcat([s], fill("", length(USUAL_CONSTRAINT_PARAMETERS))) @@ -154,17 +163,17 @@ function constraints_parameters(C=USUAL_CONSTRAINTS) sort!(df) hl_odd = Highlighter( - f=(data, i, j) -> i % 2 == 0, - crayon=Crayon(background=:light_blue, foreground=:black), + f = (data, i, j) -> i % 2 == 0, + crayon = Crayon(background = :light_blue, foreground = :black) ) return pretty_table( df; - highlighters=hl_odd, - header_crayon=crayon"yellow bold", - title="Available parameters per constraint (× -> required, o -> optional)", - show_subheader=false, - crop=:none + highlighters = hl_odd, + header_crayon = crayon"yellow bold", + title = "Available parameters per constraint (× -> required, o -> optional)", + show_subheader = false, + crop = :none ) end @@ -181,8 +190,8 @@ Return a pretty table with the descriptions of the constraints in `C`. constraints_descriptions() ``` """ -function constraints_descriptions(C=USUAL_CONSTRAINTS) - df = DataFrame(Constraint=Symbol[], Description=String[]) +function constraints_descriptions(C = USUAL_CONSTRAINTS) + df = DataFrame(Constraint = Symbol[], Description = String[]) for (s, c) in C push!(df, [s, c.description]) @@ -191,21 +200,21 @@ function constraints_descriptions(C=USUAL_CONSTRAINTS) sort!(df) hl_odd = Highlighter( - f=(data, i, j) -> i % 2 == 0, - crayon=Crayon(background=:light_blue), + f = (data, i, j) -> i % 2 == 0, + crayon = Crayon(background = :light_blue) ) return pretty_table( df; # highlighters = hl_odd, - header_crayon=crayon"yellow bold", - autowrap=true, - linebreaks=true, - columns_width=[0, 80], - hlines=:all, - alignment=:l, - show_subheader=false, - crop=:none + header_crayon = crayon"yellow bold", + autowrap = true, + linebreaks = true, + columns_width = [0, 80], + hlines = :all, + alignment = :l, + show_subheader = false, + crop = :none ) end @@ -228,7 +237,7 @@ concept(s::Symbol, args...; kargs...) = concept(USUAL_CONSTRAINTS[s])(args...; k concept(s::Symbol) = concept(USUAL_CONSTRAINTS[s]) ## SECTION - Test Items -@testitem "Usual constraints" tags = [:usual, :constraints] default_imports = false begin +@testitem "Usual constraints" tags=[:usual, :constraints] default_imports=false begin using ConstraintDomains using Constraints using Test @@ -242,9 +251,12 @@ concept(s::Symbol) = concept(USUAL_CONSTRAINTS[s]) for _ in 1:1000 for (id, method_params) in enumerate(extract_parameters(c.concept)) params = Dict( - map(p -> (p => rand(generate_parameters(domains, p))), method_params) + map(p -> (p => rand(generate_parameters(domains, p))), method_params), + ) + x = rand( + occursin("Bool", Base.arg_decl_parts(methods(c.concept)[id])[2][2][2]) ? + dom_bool : domains, ) - x = rand(occursin("Bool", Base.arg_decl_parts(methods(c.concept)[id])[2][2][2]) ? dom_bool : domains) @test concept_vs_error(c.concept, c.error, x; params...) end end diff --git a/test/Aqua.jl b/test/Aqua.jl new file mode 100644 index 0000000..c99483b --- /dev/null +++ b/test/Aqua.jl @@ -0,0 +1,32 @@ +@testset "Aqua.jl" begin + import Aqua + import Constraints + + # TODO: Fix the broken tests and remove the `broken = true` flag + Aqua.test_all( + Constraints; + ambiguities = (broken = true,), + deps_compat = false, + piracies = (broken = true,), + unbound_args = (broken = false) + ) + + @testset "Ambiguities: Constraints" begin + # Aqua.test_ambiguities(Constraints;) + end + + @testset "Piracies: Constraints" begin + # Aqua.test_piracies(Constraints;) + end + + @testset "Dependencies compatibility (no extras)" begin + Aqua.test_deps_compat( + Constraints; + check_extras = false # ignore = [:Random] + ) + end + + @testset "Unbound type parameters" begin + # Aqua.test_unbound_args(Constraints;) + end +end diff --git a/test/TestItemRunner.jl b/test/TestItemRunner.jl new file mode 100644 index 0000000..cf86c5a --- /dev/null +++ b/test/TestItemRunner.jl @@ -0,0 +1,3 @@ +@testset "TestItemRunner" begin + @run_package_tests +end diff --git a/test/runtests.jl b/test/runtests.jl index b9e874d..4ab2afd 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,8 @@ +using Test using TestItemRunner +using TestItems -@run_package_tests +@testset "Package tests: Constraints" begin + include("Aqua.jl") + include("TestItemRunner.jl") +end