From 0a69e73701ee383e2a8dc2cf17fc9a3bd6042eaf Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Tue, 18 Jun 2024 05:33:46 +0000 Subject: [PATCH] build based on 03836e9 --- .../PR50/.documenter/.vitepress/config.mts | 202 + .../.documenter/.vitepress/theme/index.ts | 19 + .../.documenter/.vitepress/theme/style.css | 179 + .../.documenter/assets/JuMP-logo-dark.png | Bin 0 -> 3318 bytes .../PR50/.documenter/assets/JuMP-logo.png | Bin 0 -> 3343 bytes previews/PR50/.documenter/assets/logo.png | Bin 0 -> 60313 bytes .../PR50/.documenter/assets/pluto-logo.png | Bin 0 -> 3908 bytes .../PR50/.documenter/assets/toqubo-logo.png | Bin 0 -> 47032 bytes .../constraints/comparison_constraints.md | 178 + .../constraints/connection_constraints.md | 189 + .../constraints/constraint_commons.md | 333 ++ .../constraints/constraint_domains.md | 1736 +++++++ .../constraints/constraint_models.md | 425 ++ .../.documenter/constraints/constraints.md | 528 ++ .../counting_summing_constraints.md | 249 + .../constraints/elementary_constraints.md | 50 + .../constraints/generic_constraints.md | 244 + .../constraints/graph_constraints.md | 52 + .../PR50/.documenter/constraints/intro.md | 4 + .../constraints/language_constraints.md | 132 + .../packing_scheduling_constraints.md | 123 + previews/PR50/.documenter/cp/advanced.md | 10 + previews/PR50/.documenter/cp/applications.md | 10 + previews/PR50/.documenter/cp/contribution.md | 10 + previews/PR50/.documenter/cp/cp101.md | 14 + previews/PR50/.documenter/cp/ecosystem.md | 10 + .../PR50/.documenter/cp/getting_started.md | 141 + previews/PR50/.documenter/cp/intro.md | 4 + previews/PR50/.documenter/cp/models.md | 10 + previews/PR50/.documenter/cp/opt.md | 14 + previews/PR50/.documenter/cp/tuto_xp.md | 10 + previews/PR50/.documenter/full_api.md | 4441 +++++++++++++++++ previews/PR50/.documenter/index-old.md | 54 + previews/PR50/.documenter/index.md | 58 + .../PR50/.documenter/learning/aggregation.md | 64 + .../PR50/.documenter/learning/arithmetic.md | 64 + .../PR50/.documenter/learning/comparison.md | 178 + .../learning/compositional_networks.md | 180 + .../learning/constraint_learning.md | 508 ++ previews/PR50/.documenter/learning/intro.md | 4 + previews/PR50/.documenter/learning/layers.md | 215 + .../.documenter/learning/qubo_constraints.md | 44 + .../.documenter/learning/qubo_encoding.md | 60 + .../.documenter/learning/qubo_learning.md | 171 + .../.documenter/learning/transformation.md | 443 ++ .../PR50/.documenter/meta/meta_strategist.md | 4 + previews/PR50/.documenter/perf/api.md | 178 + .../PR50/.documenter/perf/benchmark_ext.md | 39 + .../PR50/.documenter/perf/chairmarks_ext.md | 35 + .../PR50/.documenter/perf/perf_checker.md | 65 + .../PR50/.documenter/perf/perf_interface.md | 118 + previews/PR50/.documenter/perf/tutorial.md | 71 + .../.documenter/public/JuMP-logo-dark.png | Bin 0 -> 3318 bytes .../PR50/.documenter/public/JuMP-logo.png | Bin 0 -> 3343 bytes previews/PR50/.documenter/public/logo.png | Bin 0 -> 60313 bytes .../PR50/.documenter/public/pluto-logo.png | Bin 0 -> 3908 bytes .../PR50/.documenter/public/toqubo-logo.png | Bin 0 -> 47032 bytes previews/PR50/.documenter/public_api.md | 1480 ++++++ previews/PR50/.documenter/solvers/cbls.md | 929 ++++ previews/PR50/.documenter/solvers/intro.md | 4 + .../solvers/local_search_solvers.md | 2704 ++++++++++ previews/PR50/siteinfo.js | 1 + 62 files changed, 16988 insertions(+) create mode 100644 previews/PR50/.documenter/.vitepress/config.mts create mode 100644 previews/PR50/.documenter/.vitepress/theme/index.ts create mode 100644 previews/PR50/.documenter/.vitepress/theme/style.css create mode 100644 previews/PR50/.documenter/assets/JuMP-logo-dark.png create mode 100644 previews/PR50/.documenter/assets/JuMP-logo.png create mode 100644 previews/PR50/.documenter/assets/logo.png create mode 100644 previews/PR50/.documenter/assets/pluto-logo.png create mode 100644 previews/PR50/.documenter/assets/toqubo-logo.png create mode 100644 previews/PR50/.documenter/constraints/comparison_constraints.md create mode 100644 previews/PR50/.documenter/constraints/connection_constraints.md create mode 100644 previews/PR50/.documenter/constraints/constraint_commons.md create mode 100644 previews/PR50/.documenter/constraints/constraint_domains.md create mode 100644 previews/PR50/.documenter/constraints/constraint_models.md create mode 100644 previews/PR50/.documenter/constraints/constraints.md create mode 100644 previews/PR50/.documenter/constraints/counting_summing_constraints.md create mode 100644 previews/PR50/.documenter/constraints/elementary_constraints.md create mode 100644 previews/PR50/.documenter/constraints/generic_constraints.md create mode 100644 previews/PR50/.documenter/constraints/graph_constraints.md create mode 100644 previews/PR50/.documenter/constraints/intro.md create mode 100644 previews/PR50/.documenter/constraints/language_constraints.md create mode 100644 previews/PR50/.documenter/constraints/packing_scheduling_constraints.md create mode 100644 previews/PR50/.documenter/cp/advanced.md create mode 100644 previews/PR50/.documenter/cp/applications.md create mode 100644 previews/PR50/.documenter/cp/contribution.md create mode 100644 previews/PR50/.documenter/cp/cp101.md create mode 100644 previews/PR50/.documenter/cp/ecosystem.md create mode 100644 previews/PR50/.documenter/cp/getting_started.md create mode 100644 previews/PR50/.documenter/cp/intro.md create mode 100644 previews/PR50/.documenter/cp/models.md create mode 100644 previews/PR50/.documenter/cp/opt.md create mode 100644 previews/PR50/.documenter/cp/tuto_xp.md create mode 100644 previews/PR50/.documenter/full_api.md create mode 100644 previews/PR50/.documenter/index-old.md create mode 100644 previews/PR50/.documenter/index.md create mode 100644 previews/PR50/.documenter/learning/aggregation.md create mode 100644 previews/PR50/.documenter/learning/arithmetic.md create mode 100644 previews/PR50/.documenter/learning/comparison.md create mode 100644 previews/PR50/.documenter/learning/compositional_networks.md create mode 100644 previews/PR50/.documenter/learning/constraint_learning.md create mode 100644 previews/PR50/.documenter/learning/intro.md create mode 100644 previews/PR50/.documenter/learning/layers.md create mode 100644 previews/PR50/.documenter/learning/qubo_constraints.md create mode 100644 previews/PR50/.documenter/learning/qubo_encoding.md create mode 100644 previews/PR50/.documenter/learning/qubo_learning.md create mode 100644 previews/PR50/.documenter/learning/transformation.md create mode 100644 previews/PR50/.documenter/meta/meta_strategist.md create mode 100644 previews/PR50/.documenter/perf/api.md create mode 100644 previews/PR50/.documenter/perf/benchmark_ext.md create mode 100644 previews/PR50/.documenter/perf/chairmarks_ext.md create mode 100644 previews/PR50/.documenter/perf/perf_checker.md create mode 100644 previews/PR50/.documenter/perf/perf_interface.md create mode 100644 previews/PR50/.documenter/perf/tutorial.md create mode 100644 previews/PR50/.documenter/public/JuMP-logo-dark.png create mode 100644 previews/PR50/.documenter/public/JuMP-logo.png create mode 100644 previews/PR50/.documenter/public/logo.png create mode 100644 previews/PR50/.documenter/public/pluto-logo.png create mode 100644 previews/PR50/.documenter/public/toqubo-logo.png create mode 100644 previews/PR50/.documenter/public_api.md create mode 100644 previews/PR50/.documenter/solvers/cbls.md create mode 100644 previews/PR50/.documenter/solvers/intro.md create mode 100644 previews/PR50/.documenter/solvers/local_search_solvers.md create mode 100644 previews/PR50/siteinfo.js diff --git a/previews/PR50/.documenter/.vitepress/config.mts b/previews/PR50/.documenter/.vitepress/config.mts new file mode 100644 index 0000000..311b379 --- /dev/null +++ b/previews/PR50/.documenter/.vitepress/config.mts @@ -0,0 +1,202 @@ +import { defineConfig } from 'vitepress' +import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs' +import mathjax3 from "markdown-it-mathjax3"; +import footnote from "markdown-it-footnote"; + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + base: '/previews/PR50/',// TODO: replace this in makedocs! + title: 'Julia Constraints', + description: "A VitePress Site", + lastUpdated: true, + cleanUrls: true, + outDir: '../final_site', // This is required for MarkdownVitepress to work correctly... + + ignoreDeadLinks: true, + + markdown: { + math: true, + config(md) { + md.use(tabsMarkdownPlugin), + md.use(mathjax3), + md.use(footnote) + }, + theme: { + light: "github-light", + dark: "github-dark"} + }, + themeConfig: { + outline: 'deep', + logo: { src: '/logo.png', width: 24, height: 24}, + search: { + provider: 'local', + options: { + detailedView: true + } + }, + nav: [ +{ text: 'Home', link: '/index' }, +{ text: 'Constraint Programming', collapsed: false, items: [ +{ text: 'Part 1: Basics', collapsed: false, items: [ +{ text: 'Introduction', link: '/cp/intro' }, +{ text: 'CP 101', link: '/cp/cp101' }, +{ text: 'Optimization(s)?', link: '/cp/opt' }, +{ text: 'Getting Started', link: '/cp/getting_started' }, +{ text: 'Ecosystem', link: '/cp/ecosystem' }] + }, +{ text: 'Part 2: Advanced', collapsed: false, items: [ +{ text: 'CP Techniques', link: '/cp/advanced' }, +{ text: 'Applications', link: '/cp/applications' }, +{ text: 'Models', link: '/cp/models' }, +{ text: 'Tutorials&XP', link: '/cp/tuto_xp' }, +{ text: 'Contributing', link: '/cp/contribution' }] + }] + }, +{ text: 'Constraints', collapsed: false, items: [ +{ text: 'Introduction', link: '/constraints/intro' }, +{ text: 'ConstraintCommons.jl', link: '/constraints/constraint_commons' }, +{ text: 'ConstraintDomains.jl', link: '/constraints/constraint_domains' }, +{ text: 'Constraints.jl', collapsed: false, items: [ +{ text: 'Basic Tools', link: '/constraints/constraints' }, +{ text: 'Generic Constraints', link: '/constraints/generic_constraints' }, +{ text: 'Language Constraints', link: '/constraints/language_constraints' }, +{ text: 'Comparison Constraints', link: '/constraints/comparison_constraints' }, +{ text: 'Counting and Summing Constraints', link: '/constraints/counting_summing_constraints' }, +{ text: 'Connection Constraints', link: '/constraints/connection_constraints' }, +{ text: 'Packing and Scheduling Constraints', link: '/constraints/packing_scheduling_constraints' }, +{ text: 'Graph Constraints', link: '/constraints/graph_constraints' }, +{ text: 'Elementary Constraints', link: '/constraints/elementary_constraints' }] + }, +{ text: 'ConstraintModels.jl', link: '/constraints/constraint_models' }] + }, +{ text: 'Learning', collapsed: false, items: [ +{ text: 'Introduction', link: '/learning/intro' }, +{ text: 'CompositionalNetworks.jl', collapsed: false, items: [ +{ text: 'About ICNs', link: '/learning/compositional_networks' }, +{ text: 'Layers', link: '/learning/layers' }, +{ text: 'Transformations Layer', link: '/learning/transformation' }, +{ text: 'Arithmetic Layer', link: '/learning/arithmetic' }, +{ text: 'Aggregation Layer', link: '/learning/aggregation' }, +{ text: 'Comparison Layer', link: '/learning/comparison' }] + }, +{ text: 'QUBOConstraints.jl', collapsed: false, items: [ +{ text: 'Model as QUBO', link: '/learning/qubo_constraints' }, +{ text: 'Encoding', link: '/learning/qubo_encoding' }, +{ text: 'Learning', link: '/learning/qubo_learning' }] + }, +{ text: 'ConstraintLearning.jl', link: '/learning/constraint_learning' }] + }, +{ text: 'Solvers', collapsed: false, items: [ +{ text: 'Introduction', link: '/solvers/intro' }, +{ text: 'JuMPed', collapsed: false, items: [ +{ text: 'CBLS.jl', link: '/solvers/cbls' }] + }, +{ text: 'Others', collapsed: false, items: [ +{ text: 'LocalSearchSolvers.jl', link: '/solvers/local_search_solvers' }] + }] + }, +{ text: 'Meta Strategist', collapsed: false, items: [ +{ text: 'MetaStrategist.jl', link: '/meta/meta_strategist' }] + }, +{ text: 'Performance Checking', collapsed: false, items: [ +{ text: 'PerfChecker.jl', link: '/perf/perf_checker' }, +{ text: 'Tutorial', link: '/perf/tutorial' }, +{ text: 'Interface', link: '/perf/perf_interface' }, +{ text: 'BenchmarkToolsExt', link: '/perf/benchmark_ext' }, +{ text: 'ChairmarksExt', link: '/perf/chairmarks_ext' }, +{ text: 'API', link: '/perf/api' }] + }, +{ text: 'API', collapsed: false, items: [ +{ text: 'Public', link: '/public_api' }, +{ text: 'Full', link: '/full_api' }] + } +] +, + sidebar: [ +{ text: 'Home', link: '/index' }, +{ text: 'Constraint Programming', collapsed: false, items: [ +{ text: 'Part 1: Basics', collapsed: false, items: [ +{ text: 'Introduction', link: '/cp/intro' }, +{ text: 'CP 101', link: '/cp/cp101' }, +{ text: 'Optimization(s)?', link: '/cp/opt' }, +{ text: 'Getting Started', link: '/cp/getting_started' }, +{ text: 'Ecosystem', link: '/cp/ecosystem' }] + }, +{ text: 'Part 2: Advanced', collapsed: false, items: [ +{ text: 'CP Techniques', link: '/cp/advanced' }, +{ text: 'Applications', link: '/cp/applications' }, +{ text: 'Models', link: '/cp/models' }, +{ text: 'Tutorials&XP', link: '/cp/tuto_xp' }, +{ text: 'Contributing', link: '/cp/contribution' }] + }] + }, +{ text: 'Constraints', collapsed: false, items: [ +{ text: 'Introduction', link: '/constraints/intro' }, +{ text: 'ConstraintCommons.jl', link: '/constraints/constraint_commons' }, +{ text: 'ConstraintDomains.jl', link: '/constraints/constraint_domains' }, +{ text: 'Constraints.jl', collapsed: false, items: [ +{ text: 'Basic Tools', link: '/constraints/constraints' }, +{ text: 'Generic Constraints', link: '/constraints/generic_constraints' }, +{ text: 'Language Constraints', link: '/constraints/language_constraints' }, +{ text: 'Comparison Constraints', link: '/constraints/comparison_constraints' }, +{ text: 'Counting and Summing Constraints', link: '/constraints/counting_summing_constraints' }, +{ text: 'Connection Constraints', link: '/constraints/connection_constraints' }, +{ text: 'Packing and Scheduling Constraints', link: '/constraints/packing_scheduling_constraints' }, +{ text: 'Graph Constraints', link: '/constraints/graph_constraints' }, +{ text: 'Elementary Constraints', link: '/constraints/elementary_constraints' }] + }, +{ text: 'ConstraintModels.jl', link: '/constraints/constraint_models' }] + }, +{ text: 'Learning', collapsed: false, items: [ +{ text: 'Introduction', link: '/learning/intro' }, +{ text: 'CompositionalNetworks.jl', collapsed: false, items: [ +{ text: 'About ICNs', link: '/learning/compositional_networks' }, +{ text: 'Layers', link: '/learning/layers' }, +{ text: 'Transformations Layer', link: '/learning/transformation' }, +{ text: 'Arithmetic Layer', link: '/learning/arithmetic' }, +{ text: 'Aggregation Layer', link: '/learning/aggregation' }, +{ text: 'Comparison Layer', link: '/learning/comparison' }] + }, +{ text: 'QUBOConstraints.jl', collapsed: false, items: [ +{ text: 'Model as QUBO', link: '/learning/qubo_constraints' }, +{ text: 'Encoding', link: '/learning/qubo_encoding' }, +{ text: 'Learning', link: '/learning/qubo_learning' }] + }, +{ text: 'ConstraintLearning.jl', link: '/learning/constraint_learning' }] + }, +{ text: 'Solvers', collapsed: false, items: [ +{ text: 'Introduction', link: '/solvers/intro' }, +{ text: 'JuMPed', collapsed: false, items: [ +{ text: 'CBLS.jl', link: '/solvers/cbls' }] + }, +{ text: 'Others', collapsed: false, items: [ +{ text: 'LocalSearchSolvers.jl', link: '/solvers/local_search_solvers' }] + }] + }, +{ text: 'Meta Strategist', collapsed: false, items: [ +{ text: 'MetaStrategist.jl', link: '/meta/meta_strategist' }] + }, +{ text: 'Performance Checking', collapsed: false, items: [ +{ text: 'PerfChecker.jl', link: '/perf/perf_checker' }, +{ text: 'Tutorial', link: '/perf/tutorial' }, +{ text: 'Interface', link: '/perf/perf_interface' }, +{ text: 'BenchmarkToolsExt', link: '/perf/benchmark_ext' }, +{ text: 'ChairmarksExt', link: '/perf/chairmarks_ext' }, +{ text: 'API', link: '/perf/api' }] + }, +{ text: 'API', collapsed: false, items: [ +{ text: 'Public', link: '/public_api' }, +{ text: 'Full', link: '/full_api' }] + } +] +, + editLink: { pattern: "https://https://github.com/JuliaConstraints/JuliaConstraints.github.io/edit/main/docs/src/:path" }, + socialLinks: [ + { icon: 'github', link: 'https://github.com/JuliaConstraints/JuliaConstraints.github.io' } + ], + footer: { + message: 'Made with Documenter.jl & VitePress
', + copyright: `© Copyright ${new Date().getUTCFullYear()}.` + } + } +}) diff --git a/previews/PR50/.documenter/.vitepress/theme/index.ts b/previews/PR50/.documenter/.vitepress/theme/index.ts new file mode 100644 index 0000000..463b5d8 --- /dev/null +++ b/previews/PR50/.documenter/.vitepress/theme/index.ts @@ -0,0 +1,19 @@ +// .vitepress/theme/index.ts +import { h } from 'vue' +import type { Theme } from 'vitepress' +import DefaultTheme from 'vitepress/theme' + +import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client' +import './style.css' + +export default { + extends: DefaultTheme, + Layout() { + return h(DefaultTheme.Layout, null, { + // https://vitepress.dev/guide/extending-default-theme#layout-slots + }) + }, + enhanceApp({ app, router, siteData }) { + enhanceAppWithTabs(app) + } +} satisfies Theme \ No newline at end of file diff --git a/previews/PR50/.documenter/.vitepress/theme/style.css b/previews/PR50/.documenter/.vitepress/theme/style.css new file mode 100644 index 0000000..d2ca479 --- /dev/null +++ b/previews/PR50/.documenter/.vitepress/theme/style.css @@ -0,0 +1,179 @@ +@import url(https://fonts.googleapis.com/css?family=Space+Mono:regular,italic,700,700italic); +@import url(https://fonts.googleapis.com/css?family=Space+Grotesk:regular,italic,700,700italic); + +/* Customize default theme styling by overriding CSS variables: +https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css + */ + + /* Layouts */ + +/* + :root { + --vp-layout-max-width: 1440px; +} */ + +.VPHero .clip { + white-space: pre; + max-width: 500px; +} + +/* Fonts */ + + :root { + /* Typography */ + --vp-font-family-base: "Barlow", "Inter var experimental", "Inter var", + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, + Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + + /* Code Snippet font */ + --vp-font-family-mono: "Space Mono", Menlo, Monaco, Consolas, "Courier New", + monospace; +} + +.mono { + /* + Disable contextual alternates (kind of like ligatures but different) in monospace, + which turns `/>` to an up arrow and `|>` (the Julia pipe symbol) to an up arrow as well. + This is pretty bad for Julia folks reading even though copy+paste retains the same text. + */ + font-feature-settings: 'calt' 0; +} + +/* Colors */ + +:root { + --julia-blue: #4063D8; + --julia-purple: #9558B2; + --julia-red: #CB3C33; + --julia-green: #389826; + + --vp-c-brand: #389826; + --vp-c-brand-light: #3dd027; + --vp-c-brand-lighter: #9499ff; + --vp-c-brand-lightest: #bcc0ff; + --vp-c-brand-dark: #535bf2; + --vp-c-brand-darker: #454ce1; + --vp-c-brand-dimm: #212425; +} + + /* Component: Button */ + +:root { + --vp-button-brand-border: var(--vp-c-brand-light); + --vp-button-brand-text: var(--vp-c-white); + --vp-button-brand-bg: var(--vp-c-brand); + --vp-button-brand-hover-border: var(--vp-c-brand-light); + --vp-button-brand-hover-text: var(--vp-c-white); + --vp-button-brand-hover-bg: var(--vp-c-brand-light); + --vp-button-brand-active-border: var(--vp-c-brand-light); + --vp-button-brand-active-text: var(--vp-c-white); + --vp-button-brand-active-bg: var(--vp-button-brand-bg); +} + +/* Component: Home */ + +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient( + 120deg, + #9558B2 30%, + #CB3C33 + ); + + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + #9558B2 30%, + #389826 30%, + #CB3C33 + ); + --vp-home-hero-image-filter: blur(40px); +} + +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} + +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(72px); + } +} + +/* Component: Custom Block */ + +:root.dark { + --vp-custom-block-tip-border: var(--vp-c-brand); + --vp-custom-block-tip-text: var(--vp-c-brand-lightest); + --vp-custom-block-tip-bg: var(--vp-c-brand-dimm); + + /* // Tweak the color palette for blacks and dark grays */ + --vp-c-black: hsl(220 20% 9%); + --vp-c-black-pure: hsl(220, 24%, 4%); + --vp-c-black-soft: hsl(220 16% 13%); + --vp-c-black-mute: hsl(220 14% 17%); + --vp-c-gray: hsl(220 8% 56%); + --vp-c-gray-dark-1: hsl(220 10% 39%); + --vp-c-gray-dark-2: hsl(220 12% 28%); + --vp-c-gray-dark-3: hsl(220 12% 23%); + --vp-c-gray-dark-4: hsl(220 14% 17%); + --vp-c-gray-dark-5: hsl(220 16% 13%); + + /* // Backgrounds */ + /* --vp-c-bg: hsl(240, 2%, 11%); */ + --vp-custom-block-info-bg: hsl(220 14% 17%); + /* --vp-c-gutter: hsl(220 20% 9%); + + --vp-c-bg-alt: hsl(220 20% 9%); + --vp-c-bg-soft: hsl(220 14% 17%); + --vp-c-bg-mute: hsl(220 12% 23%); + */ +} + + /* Component: Algolia */ + +.DocSearch { + --docsearch-primary-color: var(--vp-c-brand) !important; +} + +/* Component: MathJax */ + +mjx-container > svg { + display: block; + margin: auto; +} + +mjx-container { + padding: 0.5rem 0; +} + +mjx-container { + display: inline-block; + margin: auto 2px -2px; +} + +mjx-container > svg { + margin: auto; + display: inline-block; +} + +/** + * Colors links + * -------------------------------------------------------------------------- */ + + :root { + --vp-c-brand-1: #CB3C33; + --vp-c-brand-2: #CB3C33; + --vp-c-brand-3: #CB3C33; + --vp-c-sponsor: #ca2971; + --vitest-c-sponsor-hover: #c13071; +} + +.dark { + --vp-c-brand-1: #91dd33; + --vp-c-brand-2: #91dd33; + --vp-c-brand-3: #91dd33; + --vp-c-sponsor: #91dd33; + --vitest-c-sponsor-hover: #e51370; +} \ No newline at end of file diff --git a/previews/PR50/.documenter/assets/JuMP-logo-dark.png b/previews/PR50/.documenter/assets/JuMP-logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..23a0862739ac7d2b789882396eb811530bd7b065 GIT binary patch literal 3318 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 literal 0 HcmV?d00001 diff --git a/previews/PR50/.documenter/assets/logo.png b/previews/PR50/.documenter/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4a1302eacc6c702423c1d41d64283fb33c8e5646 GIT binary patch literal 60313 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 Ss?rev0000)L|G5#-?`f zmJSTYI1l~*&_VD-^Gp9<@UMf`>UVF!XwW|?b(xVcScQw)Emb|A(d7wdk0j5e)wRN3 z=e|7Wy(}(&$U*083b9n9&PTR!sv znfmR_=P=IduppOX-OudC?ViTo-rtI%$+?U;PnDxw*T*UT%5(l4$-Z5_T^bReD3mot z5>5OPBM|8SXaBqZ>j&;8)@VX{@t?)y@cMqD-p-XBLjHq{jEd>S)hlc!ZEYMv(ST}h|TedS#9HB^{s_kr$w-0I(Kn>ov~4O z7;k6?C*)@X81bC7VnzlU{t9rq7ENDs=Xzr_(@M$q!jmRxF3qY8Ad2OFy^W~)^J4c& zMyF=zJ0C6HuK5xD-Ut@`D|2t3JH|N`(;EYIU&vzaZkiLa>dFy4_`#k?Hv_Agm{)~{iY`47rn{ zyDJBIN9l>=$G^}T9%d`cPPSgF6l(76n-P$bmisl9mH!4w@DvnZx#ye=@fKAd$Xb^BUkKm-(s+h^^LdpZ=WKj+bF?jTtCRuu zJ3W?=dbW7_;q!7q$YeoBKOmJ#ax$k+F_!%MKxaZB$FYt1SBRw={lrE%iSO5VOOsU? zviJHWwft;%Ajh{uJXqgfCXJU?urhJ?>1L6*0sQ)orEvhy8XqAD8T8E$>wunrD6Rp$ zR!^enyIbDUn9uex;PI0^1rt&e>W-XJ+YxUxD8sSQOgX8(`df1^^_9LT7tiQXjASNe z?q2QThlRyTBswdXRjf-gCJBn1-IeTrd>6P(J;^laekKy@|NV6Winu}GqNGL$d&A^=T^{8{9R_>?LatKf7w)zE*Nz)_zFFa zG8i4wu5|WzDFR&l_EoI@8xHRTmB$aj5oz{0HJ8Mb%4+=)x-i%gj;flDMkkcjgY8`C z!?5a0{OlGp^1Vl3upf5@W)OikJbJFOU)3Uxl_p|i7L|w{kO<0czKHF1iL9N`!V7Bm z?`hBGv%{glI|07B0pUNA(mB!Xjc0X=NZWtH++H9H2N!UH)HmNF{C5Nk zR<54@S+~f_koG*!t~_K5Uj2zLT8Eyu;@N=MFNm=@$*p~wFyN$qQ;**m6P&CZutP*| zNKSrhqb37*4x)gVG@$f_Um^><@Tl<3A;Al-K+1f8kHJaC7Cd^%5|HhB5ji!Y?vAui|8~6szB$%k;Z%Kzil)11u}w51bY{l@g3b*;QE$&De_D%`G{8Y(ig;Io zW(atGZZU7G;OQa9Jo*>Ru?83=R#6rD8U3vxmpDeTbRB(?P^vsS{F2ZSy=cJLF`odR z4QCmfQx~72Mh(~;Bhr4Dq6c-0%5&zrAJS3PAX0X`A!YqI-TX?&F-`#sanUxLQjj{U z5D`KyV_u*&unCp0LfXH`Olmxt3bky7dtHLURg{*(9f8tM#D7!4={f7f4*MwL_>gmsW`%(!y zb=d}SAP5bgJV6YXRM&h)wWU~F0$ilhJ`GDdM(jliAkUjTIyfo%ZgNifJOtxCeOw90 z8$YZgpF_A*;#a0<$w8+-q@=eRywn{<{*N)&{=`rAgnojeJ!|n)QV#CqMhc|mhvb%B z^@aG??Bhd_cW#zDSB(Gfkjr1-_l!DAkJX9L(?hlk@DPPDOM4cJ+S?MBBb$b z7C{3-x*kZcp8DENG7t!ZwHz#T`+VMq5f3Mwl)+TY2z;D6K1~u1CXNb%3|mD zP>lc(lt$N?T9JVyA|dnwpeX*$n~L7VpX!H#-jvU;ZL3of0U@jCVV~JEQy#qld%ADy zL11W!gQCO^68@~IK#4X^!5fmrdNFVKYHH@R86B(57LSxKu!@p+Ar{GoDxAgwWq&&S zIHo)?Ig{bGQxcUwAtSyZ{(KNgH?1C`X{pgVSr+&=qAyD!=d!p;H{_4z7r55!feFrf zx{-Qyr`!vaykBNPO23545_iV?JbJPx!BH()>-CL8Rf}}3^t|6IUlg0e%0c_N-$%}r zd76dRHPhoy6JcuutSGQ2z*hIfEDZLH4w#wzkMyV{-lve6W8db}u`ijL>1OJQXu7!< z`We-r;DXX8gyyvmHDijkgWLzB>!ARAl~pr6#a#Dg(jLk-Ul!LZ>Lpo4chA~ z2__49VKYX+nvTAl+*&~PGzaMUf-6A}vB(MekL%PZ?`C_F9`C{E%ss9p#J9ByC(vQO zq_pKSMVa-6z``t_zDs82`(j~F->%xee+^_RI(2-Y>I~@mRx?9E1BI4%+r%uSjLztT z0e#=fy^x*=#Yih&3;YIUh~A0W?8%DS-v1SXz76z%sn5pcC^pk`-fnCg_6U1$O%FZW zVDlI9w*oU@UO(2Wa@mQxuoTM%Yh}1;>ZbZ09Yoj2mp-!{;Rj1@-F2U>>>dd?2D^px z^-e(01N9-IDe&dZ2Tqy{%UQ2a8Q{i75~*F?aywUGVf`=KE@AmG2n;=mKDfl2ulOWT z7pCwfw+dfkb*(Ezmh1pK@@e%xC0HU&(VCvTRSY&BiAggQmc+=J1>Q4krxn|(2FjDJ zOlThnGSexm-5Ho7mli;#dsU^Jmuc;y-&K>y1* zaHhsxB7%!JOFR%D4_p3_(}txsgCekk2lCsZO0)Mn-$;?5iyozET_eqI$t#YFHBH(~ zK|8U8`y1W4!`Ses{{^U}2-{M!B0fXB@A8)q%QPAyhn? z3nqT#|CL}K9GdDRXxERsVX81~JEbt6N1mkl5O8(_y$;b1?Nr~$Ft<9Ka>S2U8o|;= zve|~uF9>YCVt6nJl_j3uw<$5IP2Yf^H)zsD_Wgpou$TQki3@G+*Sa?Dm5bFRpif;7 z)?B_y6lnP17OM&}NJ@Tgm32D+(Fq-UUAtL!vAG0}a3_uW32pW>sSOje!Xam8NPFa= z=)aldx-X^sk!=3>CG_(tbJM%JWJ49DpcmOy^WRVv<1Vg{$N!K^lfwmui0_o!PkeiN zsBJsb%j24Wad(2WJ!OGG@SZ+s%Xst-?nS4DVJFg^<~9me4!cQ=e^Dq&3B^naANsI= zqO!XJ-88Q!0u6Dw;vZbjI|J zPKHDY(0Rqt7OGMahb;v?WU;G*W>|&-kzYr@Z&qg zR;+Er^Dhm%6%xo=8^;e`JSH>2`4f1GPWd;;>bSQ>#m*zH8L;WkB|;^|XWF)Ba|iu) zUoco-{(tA)>9jA`r1KuMZO1&Kh%o*z)YsltXh?CZhq6JGqu-@`<(D>`mI2YOh;M-#f+anR}yR31mE{YUO5!BGO2R^62Q!<&g?yQK`) zf>8HV7?%l^RDVzJH>mP!n29bj)UfNUN7T2dGyRk+-4MSLEm4{%H%ZJWRHQjvB1qr;U}1tRKlZ$9_?5n_BVCu>KNs1saY*p@k8oH%Fhj?n5N@xm^af-YjJ3tnn-yz`b&(n6c{@#C}0r` zDM2}x11Y?XDQ+bYic)5F%H!R&`F5v=`Wnws4Nr5gtpsw^(e_7bxUmAFNW>u0VhHew zWjTfiS^ujXvXLwp*F$!O9^@UBrB=srt*zA0PGVi-)!yZ2w1?jH0X)o7&m0ssgK>)e zw~=)QEsmahOVn~2$7B@zRntyY?jXh?M=eC%m^^vanyImF3pvk{k4(ZIx_+yHdF4yv zhQnTyo4x5SY|9%%&4PqcdQz+w(iwv(Xtsjb)}Exf&dU&HeGQ*&2&(?O5Z&HVl)?LZ zms4%((ktT-zQM|c4zoLyP3fs9vYT=-$hw-Es7!JmY&lpD|2z%Z=(_EOvCp`l-;p;j{vj0u7wM+-{D(Q!#0 z&1J6)+tCUwsNdGQ+71wxiR^|B!{^}(D)w!~HQQ_qf3x#Rzbjti6R-{to6kmXc8UMe zQg(1D1`?s#{_4gzUi}Xzyc|i-yJei zdwY5kw=EN638rT7PX!cBhFU|=yFp`t#+3CJ&{<*6f6F)9E_Kz8T2q55-Ar8)C!#}e z+e3Uu+Cb{v* zA0hB91tg8km@eb83M|j{BU}WBsl#O!P~G41#G@Rii`HtNm{sU8?t8ell-8 zeAt#Cg3LgSd-LW9R)ke=F zD8kNc(2pD(KkC62X4?^}@FbbOqXHh5Po;Tstt!TsKKXO8PiJk>v2({p5)KuFnBQ_t zf;v9wV7{QoFA0@U59ex%J!u}?LI|FwS0PL#1z1VJ#=U`^F}B_WlLPl}K+~?=Dre%4@ud|R zFy6{p%-hl9F^>twfPu@}#M5v}^C~*fCM8mklQuDX_wka-y6tO^vnIWP2@9f=_opl? zxrZkFcU1#QuCK>z=Qo;5Q;XLn_3Jo2WuVc%a2?39Lqt7d$amr6)t5@o678R-2#P#n z`fldq;ngdGExOK)3DwkC<4V4Y*1HcPFLVCWmt8vs^BWzvnQ$gGpV#5~W?ys%lxFUR z3I(WoYR?!|;j4#;k4*WvC}VDI{#yk!(H-~5sfQ7IanFCVcMPJ)f2LY+2iph|GJByN zo*8kC2iIhfCzGi%Rl#!PBYpA=Cy0|gly~OP)d^-1Q6$x;ZB8YT${u;?zQgsQ%2zu) zj%!po?U+fEo= z+S#BeWsryZReDUt%-vPvrS0Z|j%oKzl}+A*7xz_N`dhA?Q~=el;7$Wve<*RzvC(&{ z<6J5iBWRy=6w3a!Brj${dc`8va^82qcqH9;bajBc>*abPQM{KCRf!i~0L8Fc{N(>!^5A2TEPt=NfiB9*LcT zzOtCL@INxCu9y@!x+F{jAw*i(4#k9TI5v&v1Uo9-p_Bp_^l^qK;J$Iu`e(2^mO?!YJ7Z_6E6lmAOW-^XdbJ@#x7WMOekQcr z${#}v40P?DxdC1=7^fvtVoy+y!BWCz2+&PTuf&84^<@Td_5|0s&J#77i?UTn7bxt_ z`I67jM0;5LvTQmvX}=2?V8^DLn5OF5q5C4W?ZJ&s=LzA@zFVppYI3bj2q`70$;y~Gnu zCU&bDRZ-Bw=046|(@lLP1AI1cPthcUQ5A0;uk~VzSc%YRzYwGDuEll(z5ChaYuhd{ z`%|zF=3~V6I-or8=8~mZrQeg0zk~m%H?H~_%zsQe&(vHi$5vRq-(M>b+ZE z>iY@X+_xRy>21QVzX}SidEgaqc)_cy7hQiJMjw9p$FkC8bFaJ}Vt_G6A(c>2w_$Ze z$?5*sw}C12(hcns8`tYL7Iqxu0J42IW-|%)fv!(JVRt+NHfL>>Ngf#c(wDjl-Seq| zlKq8`pEt>fl(BzZQ+s&T>SSI24NM0DfeUHQ znnMa=S!x04DBqQCY#1#`?a|aq>d)5Ek{Zg1SLS!s{WN_1sA(_#d1Y*8$t(;($5xLO zWb&4u_mfvyh{8LY&syLX{Jqng%JtZTDLbE213&%=WQrIKaYJA3*()M3jZ&DT+`;(1 zx$R2~LFY<9tI;S$HE8rOjoGGHP|wuDwdeR=a1YgVaE$p^RMpQtR=JJfQ|uJhDs8wl zP7s?G-`KB&imX2d3lk~G6ecX}cok%`WQLj~hl1JgYDw~G>P&dOCg{#~?9sP+wtFQ} z1&7t=#o^Q9BeX4bhM=Rf8y-~|mk+)yxbT;ney=ftX(!2HN%a{GcU)B7OmpEi{I~Dv z6LNFSLt9P^L00QfTM#&Tgi7cOv8u{&-EShPY!WzYuv0hR#J1HR9`bz3%Tg7ADVnrk zh28p!Vm(M748TV#xy=DkX z`n%!bD{qlD)c>*o_LoXY8ZYm`>x|L($r02j?P{~Wfy7TXYm*-@FJm!q3y zJY`}B?S)Z=UHIF+{v36IAGPa~DrPJzEexx@|8kOuW>h!WZ(p$Xt>x5*@*C#5u@u@D ztA+PFiP2bnCzo9dVs<3~3<9`~tG!Fx1>8wZlqH5U&rb2mEk^^)-Cz10ED@G8x8adJ z9J5Vb{u_y#T+i7po6@JW$%+$bJK4@F_B2ToJRNHuHXZ4YBA{{si9;JlRWn7I+&L^`bC}hWwJH4;XAbH$?2ctMb&iV?yzR|1 z^^H^6jL_HPp?ll#GP=+bzpjSU&UZGgimks03pc+C%O8Mt!R3_wgY>VS-6qy%A zujIuc8?C6HVHc@Tt^J2JDkAL=vh=G`O^x<&tgqi>M6yfKyLCZQ`{_V^*onIMW;A|@ zd__$sjj0KaoIipt92-J<%tl*f?})$ld{LIBf){5A>h%eqlwD1M)G~XHCoPbVX?G>` z%^BsK2M~BmErwlWjvPB!?*NHD5LNy?aC4#BMaf<2%V}1F57eI)+_3bu{V27-8fXWj zJVqL>&vUHdTve--S=?oFk6kLY0d~<(*O;O$@!)>MIp=SgOXV?y_E%gBHv%}6bmt0K zgFef-I0U}50^eI{&#|A~V5THOQ`z=&W|i{sWaZ!DY(dl9`Hd}RuWeF*6kZXO>9;nh zZ_1fpuDRz6RsS}~^W0WvOc8ux<(Nm;W0wV0?K(IzY=E<@v|2z?M}ZQ$#!Q$!`#%`} z{ZiSiLTp}hAwjIG(QRNm*$C~8|+mk&VAZRs2BBsk+^-Rz{igitm*yDcGKMNsTbV9^y0g1%G7Lcynb zAhA^(IR;WkUpI!;U!n-OMOw}{?(Sb^^6mwB*nJyS3#q3?&;qMi;Wa{Ot`H%hZ9OdM zFZFM0b2RePB4qZ_gT`!;Kv?{ZdIbk`Iv8kCv|q3PDznD1h0<3<#YAACrqr8$2}e8yL_zNk;c7fIiT~gQ=U`Pl6vt1z? zv9_vULg#czxv18; z$A(nbLKt_W>a&Fsx~wfA?(Csc1|z5;5r&-!Qqu7H+dAr415FQDRBLbmJv!+?DjZhf zH2^d9+!7%r%WZf>yc8*64{g;y=-k!znzrCej^x6AmT%c@8L!uq1TNlT@mso{Ue-xpsLTHDu)TdJRl@xd7~MBcS0A z3u(}m4irbAG!yq9d+WRESk^YzkLG2AiPwgJwrWqF@cRFP1X)d~w0XT!0vi3>fdj_P zx0tRwh|Q~$3m~VQTVA%Nh%GxVP%3X%WKqPA)8op7b`1(VJxz0|)wkB<)27Pa1OHfk zNB)Q~=~r@J`@BSg(7I2%n@Q^mv`MaKN`0I%Q{(riG}rHN>Z5jCt_(edOWE~K{TGZv zy1wO)$Z1rJ$F!2VrG*n9sJ(qVqST;E{0UJ(R($_v_t9sx9bWnn98m@T7~h)&oO}NU zPsSiU)RX>Bf~n{xM6LEl&g$711;{bKf|Y&J=@HERW81y!`%|Iq{kt3^#mlY`GR%E? z*Q^@T1VtL2PrJS%%$Xa`W2~~_O|Cw<+3bKceOsDO9=xxn^VlG-jBQ6MAMMN6@yUT} zr1z_h*6cmV<^@(gA#%|9d&v2*LddV1dZ(n2AVo5s=slZN?*=Xb#WFiA&D43z}B1D3Q0z(`veaXR^iS zW1+wU5k5E=Xq2ctR}EUxif=Jn-e7JL*fD`X?mFBmI$q0TMuw-7-g*VX>$~D91Z6zyXN54O12BQ~pJRM`72>3B^)7K>}kgPci zc^v$Ty=cVL??P#K{wsi1_kV33U`-cS3CtjVzMFSb_K+~0ea|&?3qF4mASJyx#R35> z7#=ylUB$)DMu|_CdA1u1RE>~G_xvplfe08CesZfhOi2mR(tnNT^2h%RAYy}eH!nQ} zj9op3wy%0V)sWk%QvCHo8Se#%hF%KKM?+h@P#P$lx2LdD`UtbclQI4Kha!|){zE@K zg^zzfgG^Bzqr8Qi+7YWsOUJ)u4^iI&2>``MS7ZzG+mF5kpIX7zDKMKkXHk@Pfyzww zhQRY81SDe_2*glY$i)DAWFH`39Fy=gJ7QkA0JWkSv`j#|8pYT5$`R+i4D zwEkfDT!);7heRTEmXq|9|DRXvVeRp1f3S<0-|l@Hmw%cK(aZ>`+k^?pvgR8NCJO$f z9dnj!>gHu4(V`Li(>z1oGBz()yUy3eOq7@0I9gp)k(b9igvoGS?pZpeQ$Xso@<~qN zxGV`-$JtXgIazKa$?@cXS1d7x$fL_w*oMpIMUKZDK$+}{mV#1wk?84}U9E8H)aKgp z^NzY)Du%ZIV(=(deL{&=&Dd~k6Ztx;ye36%LndJ{$c!rn-&Ox3m^z)z`kEZF8dWD( zYN@%hB{@=DJh5|PgcBOLSyXb_?)-psj9xID(6x5^Xc(tm~?aE=tx6F1V82T9XQ z&4*k^i8-La`>g)3_N+9xYcI&-RY94FZroRKF}G8#pWKURM)aF$LN+usEcDMS3KD%E zUIvglrFzRaHi?57lglu;I2j-ADH@h6uGEXzfhPASaO3m}M>HW0%DT^a8V z4Aos0GpjH25v94tJ;`D88XYC;kq%v+7vFaD2Pfw`Ihrq3M6t599lXm+XI{O=&*+uj z6=|!f>V}4Fz8oP`L^k{I_JO*~Wy*Fe2wVPRgs1B+!7&@5JXlZR*XZS;$@mek|~@ zb;sJ=N$basPBaaAa;WJJECQc`@mZ{qRGAah(tt#|{3AG7!5{t*G8JJkcd}u9vNFSJ zCt=6-O(NNr7fY{6MoJIt7POJvvz$8LiZC^b1RvP70kIYO7xTsCS{FX20?9jBS6?4D zbvz_H6k@zzU@~4A=%$QT0jwvVAnk1;!KrE?*~6gl*bKFZ;##Xk`Yq+InH2bqN!YcU zQ^OCJr(mrht~H=#`vNZ25-%|n4R65qzSr>h_6|N@mhCP!S=0Z;#NsX1Zy=#Q=ZS`q zROL8SS}o_44St`Dr7S;_NIZvoHECN{AThw;%c4Hh5wqNYIThITg1LYYTmGlvOj$n! z^}+#hFdiIw)&ky_=IM&|5CqN@k&QLZ3Qb2V(+0NaQO><3rQOZ_pD;%^ z5=+K5mA%VPvyw{Fb$VhPq`*m4$ljW}Mu~U73d;qeQKonZaI}UW7BlX9*SIc>2~Z36 z%eX(VyIk2F8Ua%OvDN88|4pWH>+*ewl_|5CGmf$uK)Ye>Ig(NJrPFMpY+ZyKItTm$Or9k5mTRch&4B@qBd7ccfXG3t}W?g8(dgG zTw&Ffqi5Q($G;=Tzzs5m$cbES=ANie6>eOOgk6;LDa*nW5Ko@I@2JH)^jW&D>;Cgy9SsG!6R)~P)SRY z1vjpTu-yLR^aL-G_Z;7fYWBE7Dl_Jn(J;u%D+H&Oq-5q7msT&rOI-ofp4BbprRLE> z=`qCA)X|0#zAC0wUw+jwj{I(g(Fgnr1{<8?LJVDv+AYs3XfANNR~L{*dn7ErP~S?= zdf<-3;*fTig4o+rnB2kM`VtgutjyJK5#M;OyhSR=LMjw@_F$` z6DdGkOjFzFv`nI>oE;Sn-#@(BM;Lu3EtV8Mom0_W3@>QrUe2iyQKw+(ee3!zq1%3L zV)MnzhmGdySftC@Z(imI0g{?}#yOleh#8hPnQTurf<}2qCAU%=1rXfqJ@m6``PtW2f0tL~S%Wqr#=#e7Lx^ zIO}7z*8S)AqH(O8>Y6Eb($uvQj76M(UdE`5^;oO*hi%?MHu51y?*ws+&%cei!Py2} zm^=AssK3_BZRxiTV}_uEJx7QW+CAaG!}I3af7tMaZ(-u5-AlUMhA@5ST}zz}aldzp zO32N%*vH&m3vF5m)VFRCwbtC1>>;|&tyf0C)`twfqJ|nWt?@WA^T<*rI<9VOUi)#E zbFJdo75wJvi!|&RQ8jYH^C`@{<<+LyoHAnl@SPz0JZI-|n>OzNxUXmxMlM^Kf|oWf zo)hRxR!U!pUw-&{kVi{MWPz!%gO;5BV6DnA?^>Vzd4}XNOu+IK*EON+G2RT@0zZ7j z^0l945=6(HH-i+mui%Fs@0ghy^PY4XvT|lp`|j*hbkf`%PLGilszNUQv`57IIm?nz zn}B=JEj$^(|~!u55mYTSF%mSv>5l_`!p6s|lO z3H4ry&4ns#F-&yUATK@8UYfxTt3vZ;iMk?%wXe4x6zRg8QmNZuxLGQAjYo^w^|m|K z#97!$kdp9m6FPKAfhe>Yxn)*{k4Iu zQEot3JHZNUOA*Hg{GkQN&ro0FBJ$xnRKGQxp)s|+iK?X+7#+r?lSjm}1rr8G(RJUx zKNTH}cUA1q*vDL&e?exn_nc6TNoKp>CR9eKi6%Xt!WI9`_QBsosCAWRUq8l89PPis z5}r2a?Y;YAd81F;e{*0fHFt89%(fE|p7Euz{)uVNwB=P!gjoj)U6y_QTz#N&e&daE z3p3=&H1dD^@bI#0-zJw+D_r234{L%Zs$5^@}b=xs!q`es|$s!1{TZbXl%@gTYjp zw&1jnuK$ff_~{6*tPlyzyb?y3T1z!0r$Gy`+EOR_|tf&6A{; zT0%Yp#$mrr{2tgk-+0|s^5c~}7n{wUm;|_oXr1tU z#{zc5_>5#h#d}o2KNdP7{^;FsqfA8rUE&~x z?QaAT^aDef-#Hb3xc$4V1)I`zfhqqI_t@7mB?@4xi2Ec)$YBU%dH;bizqW`g?RDb* zLQUVF-tSj^2LIF}%X4wTVEktQHU+L$GZ|majX8w}a<3*Sk;VXf<>Y5z?(nikWqD@z zUut-;UHRQO;;{F?*d9(HMEA)21e-nn)HQ6KqQ^}n_Zu>n3bG-v33}){yV(Zd!9eWi zvKY97J$r}~DAbOPu$A*%95_%X>sf4N6fwPq+Pq|!v<~bmZEUu2p-zuh`J2KeBUFYS zwN7~qu#RgxXrmTR`fq$DaD=efD**5@<35S=^^w32*P^D66RZ0VJ}(sHYy*DiGT-n5 zJ}bTpH?=X+l>+N&4XqIwf!! zi5i!f#rOWz+Mp#aUA-Jgy(X>Gjzn(tVE@g$TQZqMy9V zLTU=5qzeNaDD>`*&1k6kTNTHTxs!UopHGdRW)*gUCe-$$jwyOvz>;%p@u0M*_Feoq z()Lc#Wqx4mrMr~*TZ1%|<#)%|ai!pr&Yn5|_CCj|hn3a4A91)Rv8uvYjB^6~>;{;o zywA^sEh@;_Xar{!M2Y6go zO)OFhxu>Rcmi&7;u*}ji)};8iYg=qo7eM)fyR+N_B8%Um`OP%J>?3>?t4J=56}LPV zT#>(;@5IYw%%m6NZD&u-4vbZhU+)pnDS%Et1Cmo%jQX)jy>*V0G~2H2eD%SP!GZKe z){hZsH#`QAvCsAfrN5O>s1Sqks=m(*2!(AqqIgREj#+|n#*0=fn z2yFW0r!NlT(L?Vka`ZKDC#v`B^m9v*?uZH?4Bv@ZBkQ(*tWluxCx4<_&1tdO7G(EM z>+E0hp5M*DQT3P0X09J4TkRf2NZf)f-=T}O&(=%pu&5lI7MjsjpB29(sc+Xd|rTjWJ%A&q#;rdZyT{QU(-Qdc;JBQWN&$--Ry6$yby?Gt%@JAC- zymGw=KJS@rLf7_6AWk#p{_V*sch@o>NX#L*#&X8nf+mm3$41Hh2sU7nteP5(r~*jy zEa~U)HUx|f(3#Bdhy5hWe=!G-*3Q}!*0ayvij;;sZUbihx2F zU0QB|jc09XhjrRMZ$Qcpj`^g7ea+K^%h7cWXfMd`tQ**7Ok40uwKAu&GVI@KbJAx4i7 zHJoeTjhRtz&24`rD{wI+b8h3$1s*!uobX1EU+JkT*ie(W#6=1~?LRl{pK=icNJ)?G zy(9`Xu;^A!O4;SwpTKVVSWmD+I3E4JZj`Qyz!P${kj{aX7q>~qwP`zkzh)V47o}t# z+(S@*gG|gl&eD^4yp4QakfeJM8sqpeT*ro=RAGIP04>a-ybmE6pOFzu!n&0JIlthp zePWh96ISGTTvr-0{0)z$kC~wV5kt9w><>&f>U{mk92kUnmhU+jHGVthE}MF0M}6BK zK92Do`9Y@4{pqELjIm;77x+^bhk&a~-+&g+28`XwUSNfvs`hTde=uloUp{H?+h6F> zK23pJ=mhLGAKWjw(fI1_&U5-93+hIAMLHp%}NchjV!vT-kLcbS`K4R9Qq3fi=Wg%7y)Jo z8|x#y`h(pQBQW7wS3{N+;?dH3xVcV%5~lds48QETu#aV)HnAt^o(KF0e{<^NW!I`6 zU=jBRrhS^6V8uXia&-gUvzaoersAxl*(jU~kh4Hacr@&cISYB0ZcurzDaW?YchaP1 zu?}ky>(!2M)VsHbtfw)bLh;-Ovoh&kt*Nt$2W{J>_j(U9GF(H+lR6WfF zvi=aAE}y8i$$>>Zm!BBfLJkp8nzY+r1l1ubkevN_*}SnyWj=L656_Q|5L_$3Ip8Nn z<3o>7|{r5=2=I3r;B+}>Lc;t1Exri@7LujPB{Mo^34%y%3CeR%Hq z{!Q~Gcu2Tr$Lm28OxljI6Zrnv!7R@`&jx%?f<8ZQB2Wlh1qAJ!3@IZ))LC7k9rwxS)?2#bnDt3nmQ-s4%J>+N zlt1r@8rsq%cq*W-&TBc8P7%Z^Qefwetl^C*UvFbfTJ54!1^oMJAZ_OqU74iu9X4o# zF#sU|WK>`I{>J(g+7E!x@M;;)KgD>H(n0XKXTxVC9qCU@f~`ucGiJ-I!u*=gK&uim z`5jK`i6!(@pB=LTSas+-KtN1%4eoE;+$B6K*(0ivkC{dXImiABM$mgdN~PDH7^oc~ zF4d;;lDP?2um$Lus|p6dit?2AX0~)NgW3UF@ZSi^V-8U*|LR;JaecR$E^p0}@C*F* zB;u%^Gt}$?n-w5N5-oYYCdA1@8j0Q-(ngf-7aioQ*$RNt7{^$mCHSL=>i*MoDc~xL zXt967J$1*(CE)L$=5+Y2*xZ#_Z&{&Y<`GmLkU*O$F|oP- zrA4;^eLn3CBED+sKtW5-XdZ*1x>0l2`ls#oV&LsNXVf=9 z$wPmj-)vjG4!%)04JQ6j2_kxnHcXUhLx*Rm$0LeCY0xh%EZxd=-~hnl+dVAWO>u|? zh{kt*a!&x(%FMw0ae4Rv<~=Zo5&ci3sn0#nnqZx6hBji<9v3iupUlS_MKEI)S; z+8iXXVm>aY1TvGL4emPY9@!11s)O%E76<#^c46$--ix6`t1riuv;s2i37^G0D;Eh{ zr_4n**ALKDU2ynmw5b`EtT(aWj zyag35ND!{h^l)8NlNrg*MTmot&x`~+4VW|Gj2S_ z1f)QI&nxyBBVW&i4~;qfEZZ|@gAH{g0<8Gz>urch^XCG$NukbhVqh6?T5fwRc-?df=b0_Aw?pMq&1fO*Ceyahp1`E_gTr4f4Pps;i_rjnP&Kz# zny%^*`Kq>lLM!;45D4r<$blM5)XK0QT~4!&$#gD7PL%GA*elq_5NF$K*+sFjc&%(~ z?o|xL5mMmy;LM2m#A_A6p#F}F3X@=q@|3_vxocqm zXiz}ko`|o0HgX;y8?13Od0No~2rj2AgIFdjHmpX{RNR5>*(=^Js!2@POQt zw&0{v=njtVw#94fH@Os|HKdK@9z$HMtTX}r`bZW&oP9uP!-&2GYIJ(QGY~ zr?FsR!E3-XU$ncNe(LXeCZR7u%tN$_OU%>>z$9D9J;8;=%R{w*R}M?J3Aey5GfUF_ zd>a#d3B>*NV+rC;MoCB zX@kFn8LK{{y|k#KPq!U;5oru}6CF`5v@8SGFSz7v24?%_X!#DhtZ0=@cdl#E&Ty6? z6Hs^>+bjk9*9V#_;4bZbeVs4_ef`dK#|8@f_hl6o;6J<&yu%*Gdxb9OLl%6|uk6PO z$Ewq|FF*pkMa{^H`lH zxtBV&zv{xDif$__;%n$J72iv9rcBdHyf3Ui)8F71PY4U!I>Fsf@;`U3mC@nCf%_L) zG^($UR9H!wMSfC)ahhINz0F#gy6h6K^Y>Ly_z5Gs3^Cg!M$uA-`ywC4tJD}6Y!@bV zsw;eH(rTlnn!PRU*Q80E{`KfC(sL&__qonG8dhm;hhsTg)%4Tc+=-82VNbwieAP!- z=mEszUeg9{YvX3zc@)F)KXwJesz+aig$i)2#X;Ef{QdseVrCgL0sJF=mQS9kqw{G1! zJ}K?DFO}_eYfjj}wRCyats5GR4#)Yo#2i>Hhl0!>`7zuUJa;aB)!W`&^GV}pf}D-O zd7$(0?wf0(y*%Gsm%7xcv3nX%{GQk^D<&^4pppQzdG~#obk7D>BNv9;vxrY~+8nd9 zp@;dEHQ!)vYrjdYQ;hRXiN(dw(}G5CKq^D>ob$eZNp|D5~y3+C6O zGrOh>Da4Gwx_zVJ6jyrY3k%5fbE6?4A$4lDFeQeGrK&`_96lXJ^}=7R9xiet@&n?4 zBq5Q{IRc{f4i=(zeHV83VDMy~0c?{u^adFWRt#Pt{TNA;3gTm%p3H!(GSPWSV9-}* z?#y~7;nhSR%oimU9)xjaV}kp}MRt*&l~ngz zmC->VxAD<`lFtF#^j*AsBH`AJ=b!Cdx4RL0C*pZI&n2D>kJX5~3FQ50Iqi4s)QN2} zA;Nf1AGS6<;LKh`~wxe*!K5Y6^+3Q2*VGG-rnc2b> zQjkh4dvKi7@P7wBesue5r^o;^h^|vw?279rbxxfSDnVi1-)Hzg?0sciRA1EYkP4E5 zq=YomDcvGUOG$%>beAy1s9+$aNW+lQDcwklGz{H2ERp1XAa`@Rns3rSi5zK%Hnc9nLm2>2r)@m9ii?Yo`w6g zt6@3fyn? z$4!{IF4ZIi3$)9GX(X$XC~lW~fVTwz5AmcZe%cmko+%HzHDL9{N&oj@f^YnvYU<&m z4JuTM+nE9;R=bPLDt1~G+*D@nVz*KIUK`^B)oa-ZqH5Ak5+5NqLcn8*YrlWE-Rfhk zag8TW;07uomR4X?+#aPu)ZvvAv82muk1QR{sNK*|gYfPh1*#>GnK**;1NG~HsROMg z?qO>F4~V0NTUQXM#jD>{eAuGO*83>_k+=A_H@IO?u+;f;jLL``ea}sv`sSFAP26uK zIrkaPdi#M|u(DC2sf?54Tw;SD6zXfOsCvtYLE?7zF$mmI^!P8B8?w5 z(gu=|!wkFuGFT}GZJRnCYXl2=A!!EDAGb_%9`8a1$an$(!=$CKl+(QUq=Z|lBgc11 zeX9zk&Ac2CNFzFJB_tE2f5RH3MfjJOSp*?-7>x}q%C{+p?wk?eclFC9o>3t@r&mgB z{mkJQ+jESFn=`|l%6(qJpI7n$+T2+bv0`Aauq-=ac@EGsuAA9FkoFBPE;IK(a(zTJ ztjaE>=-QTHOYlTQ?0_~)05S{Y8|br}jU1(po?-L0%hRNY#eqI|kPMcve#JO^Fxc}V zNb}a!7Y%kd0=cFt5Jj3c401QQpiehPrJ}hOdw54eEjt{H=0FyrSCJB}+gcvOF*3XpY5(;8N&ZvEJp*-2VKB6J7` zxazOvqdMPzHJ>Bcfc&MXTFd_8RvW~jISE?k2i^ebTIqr#en+4tCKeS3z&O>nr{)vC z=KVnN`V*S3(%KXbX1kZ^PqFa`EYi@XVY=PQknCE1P@#9Q+@6wjy|k334aaIUix2W% zc|aN(31Bqg7Nefl4<6kUxL44s5C6G|{fFqDwQ;459l@Q_JBeJM^tEoReC_Ej4G5_Q zNqSQN5*Y%?h0?O04sl9zHg;B7Wp4@F%;Ok&_th6ezmAj1U`cL>^nlfqs0PrmagfZ% z8(Y4jJd?x#R^dzBmBJu4ou_j4v*`T8!Us9TJWIL--&+?uc>EL&Hg`KWo$-i5i=vN9 zfqn{=>L#Yj$EWP{2Zpyt>&+LsYw(3es`B`O0)5>i+?L=@6k^@iaD)05>2^7RsjeZp z^3Cs5kJLWU*ZmflS+Q6$&fiSU5`M$f+fQT?U3Go3*=*B$%C7~0&4-YcfGRffg zPX-mkt zRMLDB5ebPItvoAf)a2K-3L-{`H>R$ zTG_Qt!Sh@2-ne%PR0jBL5z=JTCAv%McQbZ+U$DIA!ul!seF`}WAZvTxf>tw0IFkP} z&J*d&!?V~(@$^s8{4ixIrO&m6ZcA9HY?c^r{vNb_4tjx~>vRh~!z+PcNzbE0PjmGx zc#28abE>*Hxi1m+1e9v9AElt*X_Ln8g0~i~(rHrNRm{$zRXSE^{-O1S=yz>;x}^)C zfG9@ejK_mpDL8yaiApIuCy8MF&q+eCg69|G9NgtL6$8*@u`J5(?QPO$4_7B4`M$A% zn{fY2P>98s2!5*67r!wF1v_RBWY7z30^ja*OUZ2IBcmUhIXuiAWxSSH7~9y8&^lLB z6*E$oQ$kZ#`}%2V+pSHB!^PtGzp7~tVBC)|V`O{{4c}GA9wZ&?Q7yPNXLYi-I0l&z z6e`1X_79#58zx*Yo4)%c{uz9Pib&2tj*qMM`>j6>7ergx5u0zbbGC9g$(!S&zMR?< zJaKYd5^D+pO=Z`B*KUnHkh;tA{^!O9dQ+WzGMNudYh4qGJ04{Y8(%R$~qHE9diQGQ=OY9`y1))kNmMPJaG=)HSun32puBBD^}C| z{E+GW#(c1H@7}sE-Mkbi1*5Uo!F`sYsOkekEdKUy z){4!y%c+HlMT7beJ^vcW5qA!-sAOOmsG+OaCQHyKTV5{l&o_7wJA$buK+$4k>Q*-N z%JE7&DbpXzzMXhuP$}W(I^4p`AbGm|&=VpxB%bBLxAD92lh#+7fbRg+tYMvv+;U;r z^4kYjhn{%yx?~Hw+4}5j_aAFVPtz!VUGy&ig*6${{jMh0xLQ*3iAZ>zuC^+!#cExgbX&Z?zC9nM? zTA<&R-H;^00?VDQ@UF)v6c{TI_-A5SIs9DpTf&))3G5pgDbmMV5{icsMLm~`9AL72 ztsK6XPZqR9iyg&m)IiU73&#HFOyJb6FXV{XirF2R!WTiw41+WTT1eVLY-4&1ZM)NfU~lDZA_sEHQ4I|{blZBC!$rx044=*$5O#>(HirPD1KGE`)i`7dA|tsSLmSUMYHN{ zvCE4xX#Mc^TEr`rD;>Y$I|ro2`1w_#;mbBB^pmOc=bU8O1C}N{kOq}B9~a$Iv^L6^b>kj<05pKSqV|*I<+rKkJsyzjzq`Ocv)(9z zzaF;_97o0n)_av3T)~4qnsM0HSwBeE9vt9oP*aC-IIQub^Y1 zR{GegI1uy<$8$jP*55qelo>o2fz9Hu4>udlwa<~z}zYQz`>saKo$EoXr#6%CGfF;zQqom z)#=dAq$w*DMuS0GjYtNl_|R@-j1&e-58R}f??i|P&`iLvHJ{M~8rGTsxpzF6AHQ-CRG>U!u*80@2@WuDFak5OFRQ=c zXu~p$DC|8}aQsu}Y;^STx=)X2VS?0ipy$S7t+h?d&F#Qh0@R3Ei5~r>$R0Ld$T3+2 z5m^tdTM_-lw7;n*X?E$*hJV^RQ;$8>>OkQ0tZzHg-3z_jzGcjmPXxB(|3rOj3+j5 zVuQ%EaT3RSIRZ03n=AU7}Y$7bmz~}y8N=+RwMpXr4@FW%th0(D181Y z;3ibnCzg&X(8qrA1o!Pj#zp6Qi(|8*dh8THS<^z8319tXbL%FE*;?&KK%w&lnoxGU zT4&<*GM(BV7&9d3rcnJBx_-5ACSWrhlEDHi6sh}c1KgLXQ;%RF7J}djxDAw=7UQMG z=l2!@6M+%g-8zI50eb*8(eh(lR}A#zf)xk$;s(77XJeTWXLo_vMlmy&+K_q9+AmR> z`~mS=%0KOXa^tWt*6W4m_q3?g2-}I+*XxGIf!bw(Da&_&<;LBweK*tr+~R+{fz@^q z>u#OnjxT>8jR7Ad35YVG7&L?Sy`otH77-KH?}C&1nZhcislZ_c6fM>&7^4bkcq>cP zq^_Sn)--~&$}7z8V4IKEqzjzvlA2V4cwbiyptL#DL~kr~wXp-WzM&%sCjL4w(!ATm zn=nNmYTozY-h$v-ikRokq=g25o%kRNhl4viWJxdB{K>X2eb51Vma-Cx<4WCUHgGdP z9@4twQ+0&F!Jqy4{$~=1Y3Xr;gg34M7eo^4%={Lv*1xO(IFr-g2hB5MOHLV@`~vYl z#n0`y4Q(eLnSn>>f{(CJ=}apXgTq{>8X_%=*b;VyE#R)$3J17q0l<80hNv4 z-8PNnIjC4t0a;5QhG|uE`b}Y$?<55Pot*6kUGH7*rB7(f^vB>WxWDmS4!HF++lGfb z2yI_$d#_$La>*P46CK85ui_UV$`SVrc)@MFPyoORQMcm1@@Xy8p=s*~>U#jJ0@Njn zH$QKsD6v61Nr6FL^WuZ68ldMOFt1Q`x#_f-f!bH-D?5+e`#Xmg+Yejau2SxYruK~9 z)gobDXT83yA$fB-PH}-HFp1aSPb^}uNYTEK`V(_k3smv$|4*n0Yw|t*Mm73QVUmjy z5)y({RZLX1`pvCsIMds|n|uY~v|ze?{d|)IU$uTAk}C_#Fz8Cc>p7*7j=YZLB1zLy z9_*2(yvd}bJuf!c2(*MTr1zSGSN*BLV0(+su3AhCd{$tni@4E>IW`X39ZiuYW=qh~ ztof?Ht;+t-D@XxxS`+}`k=yZyf0^StCE5?qAH%a==FsCkrVsY?iLHwf7(WE|MB2)MSu=7xO z+PuoU{*bSX2DEaPxQ9VEvuBLzd>M8CaiQO`Eiz(v9sPm1iR5QbM8_zumW8kZ!MWy5 zm!Lz@#1w?{0v`1Utcp>2Q)CgIETW&30GX#l;sf*q=e<$=0Fd0%Aa;4X57lot z0;n;h2LKl3Sc1@pr6{J2O#@$kBbWTdbuSH)V6IPd8w*uG!M3llwc2MSME67#DrIOD z%V=xzLHN>XVAY%(1AT`ej8;zwApYUI6(Q`MUfQ-<-Gc@8+E7p^8n$ycu*Gr)Pl6AFcC&CmA=rH=ylHC30)4vF zmQgG%7H)~X_<@_99z_F=PBV}T`q3gSmXyEj0Wi3hk}z0RBL`gr3&qZKL{otLZ1Fo? zm^_J#1!iDn#0)(#SX#P3KYm5Qs2dh{ZnJ2zj&4@!SQkEGrd(?FQ40&8t3o}$Z- zNvz9u%QnEOa>P0x_bjoI6*ohir^;w2KbJGVnXTf^+{|=Hw4**at#VWgw?Ec8^c3HH(!M&(hjkKGZePp^3YK-290pl_d^916or;1VY z5)>+s78j>>g8_hu8s10&)|-${>!P{4h_&NO@38V1gJTTveDCeEll~&HV+Y_&76#eD zOYr;c=U#@(?RRAQ^f0x8E9kvo&vdaEZkf}4^vlm29?l$c$8MdYNTBe9+|(8iiU-ZP}YjWCl2(H@)Z{nlW<= zqcS9d{Iy5>5qZ{^FEx$wGkaY@5jm`&!_UFP3?#kav6QYjO`y(N%m;y-dXG{3-j_ZBzYFI?k8MEvpAu>2w|T@(i)`Y)AG2pgokzWI2ZnuDew>^_J#U=i;StxvMRfGiH!?swblX?Q=LQ_*tZo!jt1khJA()q zSrwV!fEL~v1w0FAh%B1p@FOLiU3^<<&8{f~njiz_4C+8EgIpi+tU?vR*_}QvM^(v8 zRHQ@iV|~q5@^C;KgRkiBQ6j7Cfx!lF^$W)vm*X}+^>72@MyE6}Wu@L~R<%iNNJSLq zTwADcT6OQ;-igm#AP{~cMWjtL&fNV0UY+G?ZEj|!wc%lYO%{;KXY}*tY?@yWjIG2H zrh+h2WkBRMwhX}2iy|9JJ|vW;Ie3YhbSOE0k6n`iq(X^TNZ0XT(5iY5xSizib(g*i z)S*77vm`TDSqZj8Qz>~zlLn+Bo7P3okpXFXjZP-JfFwZ+K#=p$qPg~sSwMl8w#-aK zQ#ro*pcY0fKgB)aPpT$=*@-|=7#{!r5lxkiCfR&C;SG7hv_#(+%YGL`@QE}1r1t6k zK}w*Y2gxx@W_P;GZ#uDdh%voJ9>H1RyA>eFpFt}BlP^qn;kP4?Dc}Yr?JaJ=h^VPe zC+4RTOcVtJ#Mfh#z7n98h0Q$ba}~&CX$#ibj{h(S{ zUxgQx-?^s&kR#|X9`I6k>b#x3f2|F5h!hh=;=aN@2I2%1WhvL3X@TX(aRq#B31VG$^tDY7)e1d>&D9CV5mfz=I{&# z(%GdCp+6oY)<98s;pr2(9~=pM0t-KAQi9Ut;=vbtsaji;9X+G4cY6T}ASMY|(I&Jb zg%%{ZxTdx35kfIYtGFk--;D_(7i+Bci$)`r<0{Gm@`Y$u4>1UeBD`-u&zA;i@;f^@ zCtlUT0dWYvJ@-FH{2n#_M$^s2&G_1x$2#jS=r_Bx)E60fE!~%q2V5vFIaUrX-T@#T5%u9! zdu*J(hYdFHv|sudqKb7^FtU|X4g+ol+Sf$>httVT!ZO>3-c&vcph0;nj=)M<;K^N{ z#>vSc2-H&6%gH5aiw*$lC2%lR`v*@vA1Tma2W+$5mzQAO=b#${1ld||98D5V2P@#8 zR|eB6jY~$?(}LDBfQOZJ^>tNU<7#;k0q-?|8;?u|fJQbInzz?jBA;XV-M`) zD44a~#HD0yW5F34RA-0J7Px*PJ+K_K7!BN5u>Kj%AH_%8tVe*~T$q&}CF;DbzDTGi z2CZickkhUncDjyWe&ySLjsXG@uvJ7JJ}ew7{}xw}x3_d2{8%X*{Ypi!Bq3=1t^LB{ zfTUzv7w@VLu<&3@MA4koxVL7w`7_|bS}#z8u)7*yfS4Zv4|UtW>r5-|=>wB^;7%o= zm8wSa8aGycF~&3h0`?pM+7yNsQ*2Ne_Mz629Xsx!UHZERsemozh|tqyEx?N`Um7&1 z6lW^sO`Z$++yn7b4Z3(6iMimjA{L{8HC;gfkpL9Cc2vliW$9)-^*05$><9;FW!fz< zF0pR*75j;1^?J2%gRRLY_oqs~V4f)05BtEdX=B?0?*!| zTDVQY6Yg~)M4R-p{h~V{9g`=PWAE>WRZFm>Rcq28{Jrvj49N4^q$4LZ`%y%+XyCqV zrK5lpNPH%kOmYze#b@P7lubOE&QIyh0rb>L%RSl_tfRkSmG{J^Ys>!87%jp;t#XHs zWDvO;4J^mO@gm>Bb3l+>+#^!< zicGS~@1U1to|!zuiknONqYEb}KAV&3-inuT<>tw%KX7{lXpkLECZxUWEF1wUui6`g zzi^=*{(EvC6n5uOZhH%zs6ZftK_CQpmMAb;XpYsJ0zgqo@R_gx7LJmho^@Y-nNOO4 z48SXB9`R8NpKpSuXnmDP`SXMjV zA1q*ym@|=!O!-HR3kXhx+;B-w-k#~!BwlAf-g-0qF%HDvbvD@W&Wrdtd&V@`_DSH9 z6Oc-DNRySU_`Ia!%5mNvFc1!2l`=H*qc>myt=z*KDcNu)c*06@jc-E%2s7S;`FT^D z5+4HD4GKz$<{7*CRzM8erx*kvdjvdY7!WT2#6XEaOLDwrG+>6t?S-g9rT+Zt3oJ+j z?%`&;$SuBHAKk#!Ub_BWZ6Xa{ljh(4w|?N~VFmc0{pULT6hIG8`*CkXEEBz+Zx(lYkuS=j)UB?DJe0U0{|_;Aj;pqj#s%d&y*bNEUq2E<>G zncs?Gbb_Y`(zG~M_O--K6mT@iM6Ljt8;P3RRBzpI2=*8d9aT>)zyj@uV{cQII}(hy z7y>y8QpL6Flk*@h5Tek2;nvcW` zeXe%xqBJ%bkCO6fU zugn(!re+_~rAw8L?{pnkkN0A<0rC(~9lh2toRt5MN%{=r;+AU?G_gU+N>=prG0j^K8HWk>c@EFD4{f z%i$kuunXP0frFD0F`#$@ffhK7{z-pE2#Yk$lyhG~%+5Ff^Co`@-W|uiyY2$C=x8C6 z_uGAe6F^-&jv^bR1vFY1gj{J|k4%%P|=Jx#WM5{(wfhu3p%T>)pOi*3XUY9I(1Fqj?4L8oK%A310OP4a2DOm@}vC!rgo z0Oge;jej{RMyo0CnOx-U>paQSx8jh8%zrLA=rE++=z$vL<_{wS8dc>E0|)J7$v5@~ z_Vfp`)roaJFxk~wQt7{OA9}BN_p9D$mNfI8gxmiMJnyK!Lw`vr?-Rd++%emHeY2rE?{WI_sVsjCWz&U@G~Z-Ya!qz3>Wqbr%gZi zkt1ZD%cLfJp5d-1A{rQ%2h<-eOI{dlBA}(~a!orD8#4t=Q&)sR?KE5WrpFDG zf0VBT@@pb!`Sd>(;kawY^EJUdkWuGtAE4L$^IqoKsPFKVRMZKxlWcL=tDJMDqR$>? zM*%XXb*0|+@r^D>Bx2);hhg~uU3(K#amt83ANox*qSHU_hXWSE{RLKvAE5%dz3$L9XS=rr? zBA-r^htj0_FHI=wa`*U13BxzCsH4L%*%fW6%Yu~C6)xF6;A%n>G zt##Q)2Ti$NA>@C)v8okCF*%#^%4nVvIsTZh4I6RLfQ zVH!I7OZ<%1$eVC||1@ZQA3W^$U`dDXcWW#@YDe(?!#L#NK>lVSnb*KOS9^}Qg$wX0 z_jM7}&Yf3uZFA;ahYwWfv*Lf9&y;w9@3TLfS6KeJTij2tSXIx(abvl|&PC5PNXJYr zWx2iiDP7zJ57)}mRt>&yTy4jV=sq_pKwHO!A)&3c#$rXjFuK3-!fWigJ6-?YFXj5} zBVVF4<9cQ8qM(1x&HlYL5t<}}c+{I7OxXuqg`eG!beJG+l&fQo)de;{ht|LwSR>FF+>-qOF z&F)Ji@2Oc)1}_kRR)5>F3&Cd$f55K&Yn$Cot_RPI+T3}s6D;?};I^^koenRrVS5J| zRWyI%zWbk7+lQwQLFlXA;1{clx99{oI($*;d&^dePL<02`RrOg5~_EEA0O+hgU%_Khu+Wej# z{p%i|PxpKCxA*5aE*;gPv(yB6IiRKlI?H6K%q<>~bg=6mo>M^s%{ASu?7M992(x?8 zMYx3%g2)r8m!IwCwPWzFIpSY4QLaesOYTdpVr2bF(0F>WThO@QTyLA*xX}WwkCR|F zRwYacbL4JN)}<~rUW1Cl@}>KX>S{;JKPhuK7p%_4*KRlNpKCrtOSj(8n;67vLlJ}h zr_&m{A=A&iMHYWI6(qWMBf(FOKD^oG(-+N+qjSILbH8Yg35qc2DmKH`g;fL;p^)?f zLua0wGd-$zYTs_I_*|RfG&iJzm&+lAPMZfYTk0ZuQayy>buTl43mqlhFI3Buk4l@s zmj_Ai>N5rp?3&g36`jT#nW?pfZ0edmc311nzgH3E>w|r(UKxH|$z~SOZ0o!)sH%8{ zfR{`9Oq+ZE?ZtKoEVc>ErKWM`i|1&*?(>A|VS54%$cM)-Ji|o)eY7(jKkL%fK7WzF zzr4Ii2iRt3Xb+@c}45n`Qo5J1CI(=~xT;;q}+toFGg6|&bj{E)e ztNq@m`shJL{rJ>esl&u(q%I1fa*nfqZ8xwV0`sG`3uw;Z^;PD@HwkjuSF81&9}{I} z46r^Nc=6AtD-P+vcBH`g!#`87&m+nnU*ATPI$&{W;O&*M_2g5S3~ObqWId&%oo&yz z)GFVA+2)Hp+^hZPDS!JVZ)i}0y`xiW@N4Wsd8$i7G`Xje1HQ>)F3NY*ns<$? z*Bgc_h@`7+oh8`@35-%I76}Y&hP>X#I+Zdn2%YG9@XX2bQljUevcO@5b*{wSy{P-1 z%H-;@yWW$(s31bsd7#v;e$V;i!i~+e46L5=Q~PdDEYtpUlWkYru;0nk!w9v!@8lxt zUYgAY54Q72f8+*x>$TemgzGCzy(oqrYBQ6@ELP3?lyJ_(TDmpzh;&HUi@YgMQTJI7 zC=jg2^}PRcn_W31+MGWCQJ4KS+sv`3uS3`Nl($=WcV$O|W@n4WvKsa+r4RhdgJ<4B zGItA=FVem*gxvS>(tGk?FfRZ5Wd$Nd5Zq=y9oS&6oNYF9BJ$*9`%H4jMz35s$N!jl z%Utr68Owaq>NgQPOgo-~Q6tLSjepc3q9T3_8fFu-T$VZ%k8A z9^LMs>?>T?3E?)-OvLf7x#Slgh?T8})av61o6`LlP1Jgzuu5Z=@-+T=5j-ZtQH|Hk z^{@EP%Xl62=H3v`1ia;MRrB!nEe??%;)9Kfjjs2Meb%r0Qo!Bo8@>NZ^9%_#?i`wK zY=-fG-))&@R~Uv57f@pOUiVs87)HQT93_6A*H``VQxZ8Dc1Pw`6KnIqe}nC;oK!AN zd3P{M;gr|MPWu5fSwV)M8ns8c>mtfCy!V2#W1s#qgJk=e7yjEnxeMG9pSCQYnEYK{ zK2JF>@cV`zKRfo}4)MB5m)0qDNzR9Ei}@AFtn$Lll9FQ5uMZ}Bhu0A_R|aIpPfuIv zmM;uH(H>pLW$e+6IJ_%haxxbcd|X+sn(S|?T6(I}JpO~bgxYZa%v?FJB+Mj7*@BK@ z&}XJ=x@)spbUWrjWp{oT#nYC-D9!&z5hcTvD8-hO z>Spir`OR1lzOGmt_*vr+__MI*p$*;e=sg(+zib_3it^KNuZr#zOWhL&Z5z6wc_f2} zTi2EQtPD>R$3SXFzRyQ&_~_Kh?jbwP z*^T{A?D_OEktXs1k90m*pVi3zI68jjF#5%gH)4X%boJN!nN99{U4(*G7TShlzEOW5 zh$2`6qQ+pPUC;ikIJ%^8@qIP$qJ~5@`FwT!#jNSj+7n<eOvQ9T0RelQ& zPJX@?e7tVocl&L>R^KBzSmby1ThhTZkoP_!$WImj^7 zh#|^RIBRpB4=pPA4m~!-^>#j?EaRo(Pb+wvfsSuiu9%JOBic$B3~9c}#h5}psM8fY zWyV^|Qsk5??EQ^5o>Ip0JVKu5!Fuy6)7bMN6TIf3mGVi7xI9X!VRB8B*(iRtT7>zHxgub9b?hB4bxV7_FnmGh! z6E4nB09qQ12TnojnT(T0$J|Zi8_kZDrUK!#?a(r;zOldEGRpxEeDaD;xaoBMhWCM@ zHcr%WtN4t#w!9R9S?%!m`bgyR%SzyzULw43m2BY>FHbp!j4_Pr)XY;EF5`z&1JvSq zn;{Al8n#CB&Hv2D{dA!pHmW^6M+`>JS0(C48bv~+TVdR(2>7LYP?6r`Jkr2nkd1cwO;I1zJ=&CNtY(Rr}Jx@W3`;mnv@u5UO zIsQz!6|pwL!gS!Z*!7_j5k(*)hY4n5gZ$ z>>_>CqbD-=l$Fd+XP}#*+yi}SD20+Qz=bD>j_R|p!ze~TS;&~yuPP^+-0A#Zn4Ovg z#IjjpY;(Nt4~=@n@yhPQQzsZzfd#SnA(!k(amJ5JvJYQ4cb=X!;BPPvrzAD zq_%R-HX9TBv>mZITp+g{3~TeDHUSH4eV+PWq!!4P5 zaI{M5J4W@YuYo!xS0@DO7yqoV;LaTLXrkfvxK{q7NKfCfiYix+;v~tV^U3l2%V{su zoPCeY9cB?+m=3}A=cZnRkuzTd^6T#_MFHyIzNZ72m5tHwi+aPbJx^suy+sB_>h2tU z^D`&eN(f&tARKEQBc^jhewi>hJxoEdK0d79sbvJd;+n33V9*WOsdJ1_Zv=^!k>R5C z6Mo?8lnEn04x~|jK7M>$_7>mK2m7$t8TbYYMj*1`b@QhciPQ2=of@;#{*zoO<<fR z`{>4|0{vQeAu;dh-~K@Dz%_kSzIfeCQFfD5t4=R}1p`VqUrSE9!=gJg$0mc~_w3@< z(p}cqx6;iRZ6|PlqGL??gL|bt(daS%?u`hySH+aM6&__~Fy& z@{~iAULL86dZt`{K`D*lh=+QW!FrN%eL(2Riz9`95BMmU$HGq~uJ)%Q2G$t@gvbW# zQ6EM5M_SL2g{c_7pVc-s<`?z3UpEhFkK4i$w?_tlavv=T+L!#GWVWf>Ib}rUE+&rq zm;6Y;GYjA&*=D_ADKoh^HsJtD(&1lXGj9v!!;>)2(4Ehb`I`yV(4(p6PT$DO=Eo)> z{|szW*0P$lcX|p@MtZVb=U#Kzo|t}h+rDuT^36)dMx+~5iKCb1u`kyXr{+ff!t5@| zV0*TRH&E2k5p~LEBZnV_sIfsQ-Ld6yHooC=YSwExbWXa1>$ydFDP^ml@2VhVoR zZjwp-=c$h3)_~cT8lm#M-t@P`zA-c}uso-)HLJF()3BB(IpV-bfj|o&yzec4&EcAk zL5xj)`Kl5B6`v_YUb!?b^@6jG@|zaoHbdNtxV8xFek81_)H$ZuI3W2L2TDA=8l-Ll za_vrzmuc!b_}Pwf8?mDSj%Q`FyETI`*DvLqhg6T%GZQH`jI1U{9%`uLd9C;;W$SJd zzBzs|ikA%0kQ-2!8<*-ZRW8s&{^&(sI$dX)febb!p~SG41QkX2w2?xK90;JXEGE!gw@Z#o)4XFeDZI5seQ&`o!-muqJ%|k#oFyp0u0@aeKb) z0*{Kv6W?~~w84a`mgVyExhC!jet1jm%_5ch0*Nq_c2-Js(_4FYy$%%++fvJ&WEErh zOmidg`*68=jZVq5E(j*^@y`?spCHn6=c6JG)>)eq*{Tqj=RsIzJu-@E`d?8r66L<9 z?#mlI`tos`2=D?KFo`V1WO_Y2^z6?;;_3WWD}=s`eWwXkK|V%PJ>ZU&N7Ru>tNDDW zX+~F3LH!Z@(Jb9aIrRgkG_t{wI%jL|$YYW9;Xg7XDHO^uZ~yX_sAI_DN)J&`XO%;f zzJ7R<>z>W*)x*3*+aT@!J{H5rN3`ZC0g)y-Lb{o<5B_-xKYG~i5rB6?Kzi%S(I~|I zpQ0*@*E*Pf^M5Mb<6avyZp3}aD6BEttS}edo!g~;kP<0z2EP9s_YkpBpiHup0D!Wt z8-jknJ)ZA1&xqs)s7cC(_j~ubs|+_|kyQ%nkjt3p5aURIZ~#v$ZYpEJzck zJDNLJ8M-N{Wj61PhNSc3w4S9Y+L-~j{HY^Z0K12)yAiXyjQjUF|0wnKQXY3S-B;)%9CdX0tCdJm91tUZV954g30975Ah$rfH+KP%SErPETY)!SQ!? zV9`G8!~VuMen;ntC6h73jQd>Ffp3eZnq?PP{C%X5hZ>oPV>_sdgiO+#duV4tAam^K z-@jQXaFEr{p21-yxKdHxEYUWOeEvNkCoF!3^%B#0@9A_9+x4XnY(5{~Z@$`C7Fw{Z z>LoNjyO3A#H?W^DHB#2`dN9WgxdxrYN)V<-9}e{{;!V}JIi9R67llvrqs5;rp6{TD za-4zR+B-nd@1Xi@-D7A{_&)h9W~prDtelRs(Cs0gQtNIAYg*J?_Ovac^?eVx!&PzdOR%BMyXMHv)Hz;Mi>-SD z7lLkRh1LF>@GORD>%t_CIae;_5a|Z^{;b>8OGz@@vnG;3UTc3M2R>yr%Lkf^YN5x&Hj>RqkFpbTO;(+K z`NpR)YjB3NzJ4*XB8AEF+z+p`nRY zC8wjk^o=O+gJAtS_*ZtqbEfA)r~$w8D22RxupZV^`k87tob?v1GV2y|d#s#LdOAm| ztQVCULY4i7{hDI6O5u#U`O==5lTX;A<=AmDj$S;ixTO7f1%9~&I-;1IO`W#)F|F=~ zA5l(@y{+{QQUH)(<6#2yn~zToRfRu!h`2XpWpqkN)DQfFYUKr8)+R2^EoOs1zmGV} zD?YRLj-B3mABygPiF&saEo1x3BW^*;pjJj&skwo#c^q5u>|=&KPaW&IqwzdXiHl?f zYJgUIdQTnCEqpV%``X#z_^Hq4jJZq=#CcR@v8=!4?%*_{&NRsMccV*3*U!wPSi=c7&?WN;ASv+S>liygg7a@apqqDxb0PT6AO}b(gq`uN8!08}Stx zHuD7OIxaNeH}lu`3)`}@_#OLt;f-3irUuu*!Yy&TqCTGiTuccdeBa}G>hTwlrohHz zKW;7XO#foNPDUW9(XH} zTXuRJOlg$9a&h#e_O#`5*|D*~)6f1P@10~E|JrY^S42>E7YCA5Ap$xK@&c*re1f#X zdkJPG1GkFfz}?MM;>6lpdO25p_M-9r2AXlp4I0oVJDZY^$MO3+H^)0Bccdw#Le3F+}$joMxN?-F=qbiA7T;r-kZ@dU!o8~S5 zp|&g0W0U)X_qfw~e!3?--J3(O#pTcxc6$fMBvy-UH>Or4*9Sd!3H1oW*1?iw@N8x| zhXP(4wnefjq6V!`&ysX?TA`FGo2Od^s%D(2eT`SP=a`e{0kvU>9#s2}@9yBF5kJwJ zn8O!NyMvi>{zf8$r>h}D&_2#)A3W;m6EJ=JDv6b#f{5H125n;tRn@Dg+o;=t>NgCx z*e?7g^%^6^K4cmSkilQ5N26#b{wREy|Ga6PP>-PNX7G73 zH!{oZqJGu%`Is1XPc`8yYY)>)=@(V2Ycy)o>|MN>RS3T|!}+6}NiokT`0JQNy_gaRG^a@MCfi{j%7jKI9&5{p zxJMaM85!usHE1ci?fq!-;ON_Y^D}3ld9EXQ$%po;)j>w69XBg1^{FcV5 zH7}s?uulzP5h8~jaL5k0ZGC__hS|ESkM}Zx9{_X!Bth)M25e7GHAHv5MQnd3P2{Rw zc*uZg!h_OMl&()@1nh6!7RENhpY<{UoBE+l$BOp)h$#o@-HJu9H zuek2(EB&CFO94E8mwZZ_JPUHs(qn`E9DiA!pcJo{oqQw?(=S*WsPC>Hzra(ln(;(N zv2v5ukK1isCCBFd!alt^M~`Tu;&5#K+8kJHJ}vpaae;0^K$w0Ef2WWxwqjS$yy!Ib zgbi6c&hQ(jc_wX87yhHxb2e#1IxjZPw(^;btI`C^vh|B+S2sOa(kNZz23TCPs(gMX zQ0`wgKMm}>e>ztzENH|7PA~u-5;*OmPOGj3NC)+F1noS1vU{Mu+TsX8w%D#**X^uk zy(8hME#E7PYC7~R0YImaCN)N9_uh49=`}GI?SC2G*^Mk%=^`( zlX{K=|BZCjrKikAv`lIZU9Th`qw*>11sxWs#hb!!4N>=J+4(%x@mawtMw14nYxvyK zz}eU2k)!PFsKm{s;t#O}p^gcN0^h!%NYy(+3eSPPiTwjuuuP=|4~vcCn!({=CIhO~ zoC$nWd#q$a8n7`l=jpdazx73Qff;0cK=~9*)Ynj!&jENeJf-mCHv2sBozck>>-Ba@ zIh)oTGrn6HI7c}asFAw!U@(09Bk$8=VW2fKwBpSCT0j`~p@{n)J2ATAubd^@+)-Sy z89+He-xew>t%fW(Y^W9J%g<2`)m>!UbavyO*0&<+d?sW?U?D-3<*7$Ialej>*l&&P zm8s0>>B*ws(I_1J_=&5Aq-Tk=o@M*sfVZ^(^B;>JUzIiOKebv!d<3FUbIUJ=j!L)r z-mJrWJuH4ZBUCocBlYE9WA>Nxl;DD?r5PbZq|QH^VG)$EZ?7%ZF5GdXVPOX2x??KW~VUjINw{Z1|7q zw<-glC%z(~$aC+luGwAjldbK%0G=K#Ng|R#AL0#nm-qrOvGXatqwdJ;sL?V;5b%t= z>MQu!Q(@oe0;uoeN`NvVofHf`NJVvz-*S-Wj;?Z1cU>JKf2WRs9P;a>umd5H;MtMx zrc30+6PhW(oIbsAr;1B9A-=~`lmwek-%m9?e!W4o-ZNTZYk+;28(_oG)oc`^jd_L$ zi?k$_E~E8WT1!PO_lZRZVsqBLAse z-(+tPhAG4E%BV2i!eW?516S57YRi=dd-|du3pFMoRiQLnw&v~aSM&YOt`*a#;cQ7q z%~>kNF%JKyxbOaJYU#cP5fl&+1rZRj0ZK7mq<55#bP^zxs30I!dI?QYQBY72P`c7f z5?bg93Q9GE76PF}dI<^ALJ0}qc<=N64e$9m=QI1v?Ad$InzdKF)*d9?i<01Ib^(Yo zq3xLj?3L_DnTg=TpXUc!uoHb8?VE}#oPX{geU}eMANq}6*qg3vA$@iiT6P0O-EeJ6 zoI9eblH^g?$bWQ_0MB$QTcq`Xbak}LmSMzz_-mlgCIdJ2^7|H%PFAw-` zhnU8P;^ApozgICCKr|$C`npyaLvas6V!G$JkydS^g8YBCb?jH(W#B`vI&}LeK?Z}r zC1({|5!GC9P_K{@*ld}!`^@0QY= zMHmb|q$qKunvLs!$23}41+KfH^Eb5M&794(ie`iE!rzTofUf!}w&fYznTfxURvzyH ze=3NO_foLGqW_q?+1a5B_LVg)@J-UpQ+VFJlvuR;{Mfo&okXNw3?Os~mAp8vXK7Iw*OQWY68R;3=R2t5X&i3P zO9N*SNGaMO<&#}}uFm=^b+pAn^`h);9I?#`^C_T%2oZQfll$+J;Z5Ia;G>bP2qE165p3I?%Rbt2|v7OVZ$XTZpK*oO*#@;#C)i8)=av#5XO&PK!(mO%lRyaPFfB5U#zBQJ-7k(-`?d4XraC^ppRk zU5k&bPSK2YdBnK`g3e(EWvS0+J{r*aA@$2g56SlY)m zn{9c&anCtYx!!m1sprdq>bz^q&4v>}0;~65EKn2%d3R&5c+I(c4|Fm?BdgArElA?q6Q*iHMF3*^5Jj!3DV4&g}s(&n?3Xz z1()v&@8ug)PxSAFHB;~6)z5miEj_O~_u*<7Uhtgsf|kfVZSyU0gOO-rx9T=)y=H3Q z`S)JYX^WOLT%2FkCkLC1;GMHp>!=R!mr>;3vY(mC^+X1W?rn(65t@K=-75hKXFX=^ zTDWHvgt?PMLKyp?mPNh;q`*Vy*Hi@l!wj_}$WNdM%~pbMh?LnXurfI&?VW9j4LI}(bGlF zg+1`I|0}%)If8DgV~2$z7TkTx6C~RF3NKgsXgS+nnM6emC5P;fX_*?0O*=p4WsfJ_2LwOCwn@~*m*f<4Sn8TR%m51F*cV<_x|!B_LjpN@|9Cg z(tu{gCx^ARY*Al^$^#WdIvzo&%AfDQsCw_E?0l)njH~SOYO!Ct9#XSr60)T!0 zhDk~EX-}dT(l1gB(+&;{KJ}7sfNaZzY39|~=+l-n^MVHlhczv3WLr_j-Ics%$k%-) z`|JAu9C3to3Od+#WLXA{*)ZHB>L+}8Lls2&ASJ8~4Myw@))@Opr(D9-`^5dHYc@EF z;922&FHw5>kuIu9rltnFUU`eYsM!(Pt6z)Cfp~0tUgo>^EwBTwM?4WfoU=&^%cx@{ zSOCU%WZZSA>=|%pv~;BLs43D{WMR@Yc;f$gr&7?bQD|mz_)7${5GJq{c|VySw&jPf zRB#Ue`8IK4S*EeM9#HEWJd2dF4lvIszOTy0479~gkg=LY&(mOOQ^yQ2WAy3fG@43G z7Z;2^c98EJB%>t%e7dHK=7EZOZNA>ukMxvya|dBdD%o@-lx}D?S>?3dPkQ`UhNu^- zY_Cf0GrQQ+HJ=H!L|J^uQ!)2pE1`O36sL9V3%jkGFpDW>8OS=tWHWj{neH0}OY3zi zlTS!l{{)7*n07T)5q}Gl8x7~yEr%;IvTmHN<^9(4sT1osN(9FYML6lF&Mmlmt|dP} zq-qcWA%vv?h17?;v{&F)SFV+cF@s2akI(4PRH7#Gyhip2e)#*BTFv=D^1%Mv)C~VP zrU+IFXm0KGh~(k6FiZ z9B6E+)IZ6-lvN9>8Pb#W8Bjqv1wR-2OZ`|??}SsvsAn+~wz2_}8U-L>1uBx^=yqm) zQ+e{z0Nt{$02Qyh>n*~`SSkrT<+*#TsgnT<9E~5Y_xwn{l?)qc5noV?8{g4Et$idb z`dRKG;Kd)~n$63q&_j@{))&mejEP_#Yi3@XdZPSn0^_cI_AG~r5pAx?@>oye42_vr z)Iq{O(fxsPT}Jq_x7Q&v++L(7(xUS*>O+9gS(wh@0=FM-tDef*A!V}F4apDT z8-z)Tmy6bBO^{M#bpQiI9i+#kfgQ5?T!i?d76KVn6u#w2_Mj$n^n*tcEv=V*L=H^^ z1s(+}ybUx94a8tX@QE=dM`&@A3txM}H=_oFoMF84KZ9ImID+gG5uu>TD4Q@Q7HwR( zhi~DKV>VP~wsvp(@8a}SNtgMJri*qikif~k^%sm`q4xtL3Nnpv7TCg6^%EmKi94?a z0^1d&*hB0Xa9pN-Va8|QR**pTtyHY((%H9ZtKficZq&=B$?~V)wj7BYz$T(hu#5J( z??8RIRiJW)n}?8sCn=Y_1#r?)OjRK0=lWTC)j%Ay>xsg@Om1+#eiyKQV6nyh2{upciZKIxAfG!HV?h34NfON~RS1BA0@x z+!XOM!OU>f)=Pvlbth}TRUdcbBYH3p3cS_)HWZSDAZ3+*wgEUg_wF*b&$h?WTlpPs z4o}1{9EQyk?z0~k-F_{DHw)|Ktxe8s(jvX+t>{}j z%p>S~qVP!HwL4gl0)|2Se5)%UNE?q@$Pel+>1BEa{!8)eRY=EYFfI7rtt6t@6P!{F zVal;gDzg$N=;5kSvxdwGzv5=p@PJmX({|zg8G`LO#3=~4HJjYrwWjGplGNlW7%cAy zd)%nOh?|l*(=M36~qPMhfrV5q%x@?=b280<<*y2=nM}v+2MU{ z{lu7$Qz}SF!+W(jVTwo=#~snhU))9WL@OS}+UVS}9iq?o?^AITlx+hJ{2AZd1O3PDKSiSp3LubYCq~!@Y1?Q?dlt*#T@k)Bjf%xH=ch~D?NVfJe`RND}@4tDrcHi z&+OjEr-mXUDq|Id($Fv5RDe0FvQ(d0v=jxh!eL ztyr_K|G1Cja#WKmZ1Ab$(MXf`4bf)R5|SOm6}DkO$dWsm2~iRqz`?J*c1hwt3%0vu$CDdK~;Zru0<7rRR!wTyIsSRWm3yij*bFSS)DL4!k5Bmv3EI_%LK`p5YN&D0Pq|c zV70>h7B36l&?ugu5bj2=$0M>S6>WN^B%7(eVA#HOLI2qUQmu-F&`hI52j%<3hz&4j zg1@Kw(6A#2%PS{j+Iyq>#l%%%eIdNzhsYSsj(uu|!ce5iI{1kLS-Gn9s%PG#)lUYH z#=Y82QD2H*LbNAw%Y!DquUb<6M=|h7?%V({t{N_=KvjgzI8uN$=a0a5-0j`WU!)G# z-ad~*1JFDwr>Tpq4Qg4BH8<)obUIq75No3}J>;$ch}O6i;8 zyVbKZbUhl~w)E!3Jf((qI37iz&@;!4~{XUMAiFLDmHrKoF44c;BvI!lzDi_F{Zwt=!~)ciDTUE=_-;R%7(|R4Xzi_0hY25pV4Z+>dMQ z#r~QZ)M2!^IRTntc@9$UHOI;0St1yYx^_Uzv3Cd;_zpVVXD9$r)o$4O(o=l2!*wfq zq5ql0rYD9f9+k!7^U^N}@0%neo@HUtOEXB!RW>0AcjjSi$IN#4>!h4?MLKah+ZEg) z>Nk9kMXF9{)JL#33w)L-vLkO0PDR1O@**MBC0RMfPN04T0aBr_9G@ylbhoFSJ!xr(-c&CvGTr&fjF}mTP-A zGADu3Ydg?iqtlMSXSyKDHr=rt-3Kb60!~qmOIxos@rvD31ze+e`!5|osSvO>We6_f zpYIYAdUiffv7l1|mMgT3HiHpJQR;Ta{(X0kCAm~o(zCc8Ga90b0|iyG-AS)5CBub8 zY5UP)5fw`L`0320Ku>$+OzjD)5d|CWPOO#Zc2c4By~SNu*;8WuDRSsP3gAtyX0d2- z61~KjwYg7`n~M^|peJ`wr`k(-SuE_I09UYKnD&X!GB#^#RowFjj)uKf!vdA$Q78OvQg&6+v4b_OhcCHP zdxQkF?=SC(t_IYsR>9LGZ5!Gl7e@R8D-O%M*A@CEi4zXr9ttVKJGIX!1Vy4Y!$=#biYXas>kdOXe@Xg zgnlq(kt&LilFe6~Nu#12-MS0mAG`pLZFD_gQ^=HJ+~sC$pKa;-`#!k=Dl>I$wS0b1 z+jB*R;1Np z&*+RkZRgZUR+gxxp_lZ%-JPO+W*@fLkl=C-gX8vV! z-@e09;kXd!&k_js7E%$&=u*XtjfA6}Z;tI=uW0%Ln_W~EtKYmBQ#-osST~}DfPxeZ{_6c=K5g<%fFB}tHB>$)rCnT#ckD{Js0gBUDSFx@;%>}6 zdlj9wq^M%;k!0*}aEmNNkG@y>ShTQgEBU5fn^7ABiSD>nf&AJw@?*JVX9+Oz;CaZct;cS+P2*$XK>Y5A!wg{oojd@Ht;gkj1G;J5 zj&(s3d43~Hv`kLKT|KtVN}r6%DXkp|i(<%F)Ci!U+q8Ek!4;ivD*xn1r(+9+9O6)I zjlRcyH#fL**+in`mR?2FZs6gFSyBx%qPaCu;>bk6RnD^J{ zq7%!)hvaM8kogPa)1>P!H;t6+HWCpheJTvWDwc#|@;?+uC4ODR#ckwFLe2hQm#4se zLCs)4be8ToJpYhRryRFn2O%CRdqCiGRk-IW>~Qh(A*Yr;n)#M>w7jDC8v>lTjX4KQ zWQ1{Tzi+Fr!Ckzj(kkCh{OB4!*kU`_nXBh1-Y>b|yuv8j-FfgzSo{g!eNnBQumJzwjpQo@sBI?%JF}MU4{i>+J zqqbADyCVD6cWo8|88Ohm|xnfyCkKs~MGH+0w7deOOJ3P_suTx(|{Df6UXi!%=-) ztORW4@%h0^(v2l~H1306=%PyKqwmrLs833kv@nyJG4XqnDo=youvn0K;h^`3XP{wB z6Z8FIR#$WicA6O#>r4N~yQD6FVVl4?%j=yG6!fLBq8mOnm{jJHH zvtiXcs<;5tQ80&COkk~=eDab(xoSO$-^;P}w_)CznRP_8jHXBpniSgQPwXC*7R98; z1SP?Se*6?n1-8D`>-VP{1#S&z*#5nm>>>}Ixn4ncJAx5mr<)+hHJmHo`^qc%8*bUkWLdqD#|%3$^w z$HMI&USV&ZlWGpS?v?BYL~3{>pW}$_>h(yjGt@imFp|E^qiE1>%dhIs_aoVErffeZ z{i%}enOLc6qmDvD=dk=N->XKL57eLB8W3>4UroLdZbhoDh6xmumbz4^d+m(8Jsqs_ zEn*sI2&z`}`d+N_+mx#pQPi&ds)QP@lckyUlF9i9XTZt48*c0x znTs;ab&$!QPC!^%w6rBYODj?;2Ra_!^lHEbXI7TlR{b z)^Bk(oQ7~DqhgxYnMt(2BR>=kW2bcOLI{^O!MCH+kxz%(nyk`h#mpQoU~+x)!>1S2 zoZErN^SNZ^Bq1NnO%2O=rdo*tnB`Yjsb5Hp1Acd=zQzMIYlaw_UPt31uhakdleV07 z*B?lO3V}OVaaw1=(m@MEBiot<4Imq}0mz?QiKfDPqcjILhqjg;HdwY+$**T3jR`C^ zFDWJttC(L7X-P$_d)Ky3EN^&{_3~sMs104qzR6s|aJKE`5QoRk55ymXo;6vGPl)t- zJPw(8tQOOJJ_ufG^DBbLwsZHAHNWaH3xWDg*zbndED=Let$Bxs>HhPeu`TnD(>;HC z??1)!H1g*Yec1=hjCDpBn|oTG*OHHP$JZbJ8}!CB^Z3K0E8m%qCkvVSM!uCksSUK_ zYNnVNB&@vUn^s=Gu6<|n;~f;ev|fZR>(0%bfh&Y-aMtmq;oMnY#QxJehuUq#S5hb2 z%n&FAo{1ZfB1Fr z5k@oSMskBCc*8OJ@N{)qwqb@dD^8xtS(1ap;o>Yh`&9R7P<#jq`6i+lC^Se}=8AxGZKjLz|8VH@!3 zGVHNU?TOgdX}JTO7^d|(9F$oRw>;%UOf~3?R-Dk>ep-J?cYV(LuV1q*CD%jBfol$q zgcdO>i~yZ-2E0Zro?dZ&?u2G$>4}*MEXCL}ox!g7l|BIhWTBg< zkCr_nK0C&?)j?4a8PwV>;8kbg*U{Mm_RuSqW;60g;d0s)6piA+iX_9mOZ{h=1Iq1A zL~pxvz?N$w?l5XH3Y|RtTqEU8Vw}BL3%hvE9|pRz%837sqW$%}s4ZR;Ivo#9puLb# zhjjltw$AkS^oAJqIhFmqt29q^7I&l1e8Pbwsr)VL}1tC}>;@}t1g_`6x=|Lij*t(f!SKN39K z@x-f}q6Vz{8XCMc>6PW;J{n=Kfe*xseCe`hE)NS!rFIu6Tqi6mp%b$`;OUe1SWuQ) znI2q-+d?c8vB9=TjcG&>&HSn6-ygF`gUG8GfJJDc+D8hyE#vNIX1P<|v(bAluWx9W z6ulQhpHgZu^4U!R?z2%3P*htcX2aZ7LPN$8we(O0=~v@X#s}GgcK={JtaPZi5JH+c zHr~l4(B)9y)MHuwm*}g!{!AVd^Dzw9i9{b;oHAB9GFz7&i-^AOz^4N0|JUYE@xUjD zeR451Q>#K?gZ}vVqUQ#6=kJN;qR+oCn-wT-?s22^mvW3DG2LVp-q|>n=bQHI3#rC$ zh#)^*zlG($${j54zyEo)_ZX>v(F40j<{E8-#X^nKh>}CNKTYf0KjM~KMxB`gc$yP= taH7`j$<@}-cf@c31E# literal 0 HcmV?d00001 diff --git a/previews/PR50/.documenter/constraints/comparison_constraints.md b/previews/PR50/.documenter/constraints/comparison_constraints.md new file mode 100644 index 0000000..2b84cf7 --- /dev/null +++ b/previews/PR50/.documenter/constraints/comparison_constraints.md @@ -0,0 +1,178 @@ + +# Constraints.jl: Streamlining Constraint Definition and Integration in Julia {#Constraints.jl:-Streamlining-Constraint-Definition-and-Integration-in-Julia} + + + +### Comparison-based Constraints {#Comparison-based-Constraints} + +
+
+# Constraints.xcsp_all_equalFunction. + + + + +```julia +xcsp_all_equal(list::Vector{Int}, val::Int) +``` + + +Return `true` if all the values of `list` are equal to `val`, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `val::Int`: value to compare to. + + +**Variants** +- `:all_equal`: Global constraint ensuring that all the values of `x` are all equal. + + +```julia +concept(:all_equal, x; val=nothing, pair_vars=zeros(x), op=+) +concept(:all_equal)(x; val=nothing, pair_vars=zeros(x), op=+) +``` + + +**Examples** + +```julia +c = concept(:all_equal) + +c([0, 0, 0, 0]) +c([1, 2, 3, 4]) +c([3, 2, 1, 0]; pair_vars=[0, 1, 2, 3]) +c([0, 1, 2, 3]; pair_vars=[0, 1, 2, 3]) +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]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/all_equal.jl#L9-L36) + +
+
+
+# Constraints.xcsp_orderedFunction. + + + + +```julia +xcsp_ordered(list::Vector{Int}, operator, lengths) +``` + + +Return `true` if all the values of `list` are in an increasing order, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `operator`: comparison operator to use. + +- `lengths`: list of lengths to use. Defaults to `nothing`. + + +**Variants** +- `:ordered`: Global constraint ensuring that all the values of `x` are in an increasing order. + + +```julia +concept(:ordered, x; op=≤, pair_vars=nothing) +concept(:ordered)(x; op=≤, pair_vars=nothing) +``` + +- `:increasing`: Global constraint ensuring that all the values of `x` are in an increasing order. + + +```julia +concept(:increasing, x; op=≤, pair_vars=nothing) +concept(:increasing)(x; op=≤, pair_vars=nothing) +``` + +- `:decreasing`: Global constraint ensuring that all the values of `x` are in a decreasing order. + + +```julia +concept(:decreasing, x; op=≥, pair_vars=nothing) +concept(:decreasing)(x; op=≥, pair_vars=nothing) +``` + +- `:strictly_increasing`: Global constraint ensuring that all the values of `x` are in a strictly increasing order. + + +```julia +concept(:strictly_increasing, x; op=<, pair_vars=nothing) +concept(:strictly_increasing)(x; op=<, pair_vars=nothing) +``` + +- `:strictly_decreasing`: Global constraint ensuring that all the values of `x` are in a strictly decreasing order. + + +```julia +concept(:strictly_decreasing, x; op=>, pair_vars=nothing) +concept(:strictly_decreasing)(x; op=>, pair_vars=nothing) +``` + + +**Examples** + +```julia +c = concept(:ordered) + +c([1, 2, 3, 4, 4]; op=≤) +c([1, 2, 3, 4, 5]; op=<) +!c([1, 2, 3, 4, 3]; op=≤) +!c([1, 2, 3, 4, 3]; op=<) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/ordered.jl#L21-L67) + +
+
diff --git a/previews/PR50/.documenter/constraints/connection_constraints.md b/previews/PR50/.documenter/constraints/connection_constraints.md new file mode 100644 index 0000000..edee165 --- /dev/null +++ b/previews/PR50/.documenter/constraints/connection_constraints.md @@ -0,0 +1,189 @@ + +# Constraints.jl: Streamlining Constraint Definition and Integration in Julia {#Constraints.jl:-Streamlining-Constraint-Definition-and-Integration-in-Julia} + + + +### Connection Constraints {#Connection-Constraints} +
+# Constraints.xcsp_maximumFunction. + + + + +```julia +xcsp_maximum(; list, condition) +``` + + +Return `true` if the maximum constraint is satisfied, `false` otherwise. The maximum constraint is a global constraint used in constraint programming that specifies that a certain condition should hold for the maximum value in a list of variables. + +**Arguments** +- `list::Union{AbstractVector, Tuple}`: list of values to check. + +- `condition::Tuple`: condition to check. + + +**Variants** +- `:maximum`: The maximum constraint is a global constraint used in constraint programming that specifies that a certain condition should hold for the maximum value in a list of variables. + + +```julia +concept(:maximum, x; op, val) +concept(:maximum)(x; op, val) +``` + + +**Examples** + +```julia +c = concept(:maximum) + +c([1, 2, 3, 4, 5]; op = ==, val = 5) +c([1, 2, 3, 4, 5]; op = ==, val = 6) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/maximum.jl#L5-L28) + +
+
+
+# Constraints.xcsp_minimumFunction. + + + + +```julia +xcsp_minimum(; list, condition) +``` + + +Return `true` if the minimum constraint is satisfied, `false` otherwise. The minimum constraint is a global constraint used in constraint programming that specifies that a certain condition should hold for the minimum value in a list of variables. + +**Arguments** +- `list::Union{AbstractVector, Tuple}`: list of values to check. + +- `condition::Tuple`: condition to check. + + +**Variants** +- `:minimum`: The minimum constraint is a global constraint used in constraint programming that specifies that a certain condition should hold for the minimum value in a list of variables. + + +```julia +concept(:minimum, x; op, val) +concept(:minimum)(x; op, val) +``` + + +**Examples** + +```julia +c = concept(:minimum) + +c([1, 2, 3, 4, 5]; op = ==, val = 1) +c([1, 2, 3, 4, 5]; op = ==, val = 0) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/minimum.jl#L5-L28) + +
+
+
+# Constraints.xcsp_elementFunction. + + + + +```julia +xcsp_element(; list, index, condition) +``` + + +Return `true` if the element constraint is satisfied, `false` otherwise. The element constraint is a global constraint used in constraint programming that specifies that the value of a variable should be equal to the value of another variable indexed by a third variable. + +**Arguments** +- `list::Union{AbstractVector, Tuple}`: list of values to check. + +- `index::Int`: index of the value to check. + +- `condition::Tuple`: condition to check. + + +**Variants** +- `:element`: The element constraint is a global constraint used in constraint programming that specifies that the value of a variable should be equal to the value of another variable indexed by a third variable. + + +```julia +concept(:element, x; id=nothing, op===, val=nothing) +concept(:element)(x; id=nothing, op===, val=nothing) +``` + + +**Examples** + +```julia +c = concept(:element) + +c([1, 2, 3, 4, 5]; id=1, val=1) +c([1, 2, 3, 4, 5]; id=1, val=2) +c([1, 2, 3, 4, 2]) +c([1, 2, 3, 4, 1]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/element.jl#L5-L31) + +
+
+
+# Constraints.xcsp_channelFunction. + + + + +```julia +xcsp_channel(; list) +``` + + +Return `true` if the channel constraint is satisfied, `false` otherwise. The channel constraint establishes a bijective correspondence between two sets of variables. This means that each value in the first set of variables corresponds to a unique value in the second set, and vice versa. + +**Arguments** +- `list::Union{AbstractVector, Tuple}`: list of values to check. + + +**Variants** +- `:channel`: The channel constraint establishes a bijective correspondence between two sets of variables. This means that each value in the first set of variables corresponds to a unique value in the second set, and vice versa. + + +```julia +concept(:channel, x; dim=1, id=nothing) +concept(:channel)(x; dim=1, id=nothing) +``` + + +**Examples** + +```julia +c = concept(:channel) + +c([2, 1, 4, 3]) +c([1, 2, 3, 4]) +c([2, 3, 1, 4]) +c([2, 1, 5, 3, 4, 2, 1, 4, 5, 3]; dim=2) +c([2, 1, 4, 3, 5, 2, 1, 4, 5, 3]; dim=2) +c([false, false, true, false]; id=3) +c([false, false, true, false]; id=1) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/channel.jl#L5-L32) + +
+
diff --git a/previews/PR50/.documenter/constraints/constraint_commons.md b/previews/PR50/.documenter/constraints/constraint_commons.md new file mode 100644 index 0000000..2b3ecb2 --- /dev/null +++ b/previews/PR50/.documenter/constraints/constraint_commons.md @@ -0,0 +1,333 @@ + +# ConstraintCommons.jl + +_ConstraintCommons.jl_ is an essential package within the _Julia Constraints_ ecosystem designed to facilitate the development and interoperability of constraint programming solutions in Julia. It serves as a foundational layer that provides shared structures, abstract types, functions, and generic methods utilized by both basic feature packages and learning-oriented packages. + + + +## Key Features and Functionalities {#Key-Features-and-Functionalities} +- **Shared Structures and Abstract Types**: ConstraintCommons.jl offers a collection of shared data structures and abstract types. This standardization is crucial for ensuring that packages such as ConstraintDomains, Constraints, ConstraintLearning, etc. can seamlessly interact and integrate, fostering a cohesive development environment. + +- **Generic Functions and Methods**: The package includes a set of generic functions and methods that are common across the JuliaConstraints ecosystem. This approach minimizes duplication and facilitates the extension of functionalities across different packages without requiring redundant code. + +- **Interface for Learning and Application Transition**: One of the pivotal roles of ConstraintCommons.jl is to provide a shared interface that bridges the gap between learning packages (e.g., CompositionalNetworks, QUBOConstraints, and ConstraintTranslator) and basic functionality packages. This interface ensures that once a learning process is complete, the resulting models or solutions can be directly utilized with the basic packages, eliminating the need for users to manage multiple package dependencies actively. + +- **Simplifying the User Experience**: By ensuring that learning outcomes are compatible with the fundamental packages for constraint programming, ConstraintCommons.jl simplifies the workflow for end-users. Once the learning aspect of problem modeling is completed, users can proceed with their projects relying solely on the basic packages, streamlining the development process and enhancing usability. + +- **Impact on the JuliaConstraints Ecosystem**: ConstraintCommons.jl plays a critical role in the JuliaConstraints ecosystem by providing the foundational elements that enable package interoperability and efficient development workflows. Its design emphasizes ease of use and seamless transition between the learning phase of constraint programming and practical application, thereby enhancing productivity and reducing the complexity of developing constraint-based solutions. + + +## Parameters + +This section of the package list or extract parameters based on the _XCSP3-core_ specifications. Note that, for the forseeable future, the default constraints specification will follow the XCSP3 format. +
+# ConstraintCommons.USUAL_CONSTRAINT_PARAMETERSConstant. + + + + +```julia +const USUAL_CONSTRAINT_PARAMETERS +``` + + +List of usual constraints parameters (based on XCSP3-core constraints). + +```julia +const USUAL_CONSTRAINT_PARAMETERS = [ + :bool, + :dim, + :id, + :language, + :op, + :pair_vars, + :val, + :vals, +] +``` + + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/parameters.jl#L1-L17) + +
+
+
+# ConstraintCommons.extract_parametersFunction. + + + + +```julia +extract_parameters(m::Union{Method, Function}; parameters) +``` + + +Extracts the intersection between the `kargs` of `m` and `parameters` (defaults to `USUAL_CONSTRAINT_PARAMETERS`). + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/parameters.jl#L21-L25) + + + +```julia +extract_parameters(s::Symbol, constraints_dict=USUAL_CONSTRAINTS; parameters=ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS) +``` + + +Return the parameters of the constraint `s` in `constraints_dict`. + +**Arguments** +- `s::Symbol`: the constraint name. + +- `constraints_dict::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + +- `parameters::Vector{Symbol}`: vector of parameters. Default is `ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS`. + + +**Example** + +```julia +extract_parameters(:all_different) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L44-L58) + +
+
+ +### Performances – TODO {#Performances-–-TODO} + +## Languages + +_XCSP3_ considers two kinds of structure to recognize languages as core constraints: Automata, Multivalued Decision Diagrams (MMDs). +
+# ConstraintCommons.AbstractMultivaluedDecisionDiagramType. + + + + +```julia +AbstractMultivaluedDecisionDiagram +``` + + +An abstract interface for Multivalued Decision Diagrams (MDD) used in Julia Constraints packages. Requirements: +- `accept(a<:AbstractMultivaluedDecisionDiagram, word)`: return `true` if `a` accepts `word`. + + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/diagrams.jl#L1-L6) + +
+
+
+# ConstraintCommons.MDDType. + + + + +```julia +MDD{S,T} <: AbstractMultivaluedDecisionDiagram +``` + + +A minimal implementation of a multivalued decision diagram structure. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/diagrams.jl#L9-L13) + +
+
+
+# ConstraintCommons.AbstractAutomatonType. + + + + +```julia +AbstractAutomaton +``` + + +An abstract interface for automata used in Julia Constraints packages. Requirements: +- `accept(a<:AbstractAutomaton, word)`: return `true` if `a` accepts `word`. + + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L1-L6) + +
+
+
+# ConstraintCommons.AutomatonType. + + + + +```julia +Automaton{S, T, F <: Union{S, Vector{S}, Set{S}}} <: AbstractAutomaton +``` + + +A minimal implementation of a deterministic automaton structure. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L9-L13) + +
+
+ +::: warning Missing docstring. + +Missing docstring for `Automaton(a::MDD)`. Check Documenter's build log for details. + +::: +
+# ConstraintCommons.acceptFunction. + + + + +```julia +accept(a::Union{Automaton, MDD}, w) +``` + + +Return `true` if `a` accepts the word `w` and `false` otherwise. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L29-L33) + + + +```julia +ConstraintCommons.accept(fa::FakeAutomaton, word) +``` + + +Implement the `accept` methods for `FakeAutomaton`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L41-L45) + +
+
+
+# ConstraintCommons.at_endFunction. + + + + +```julia +at_end(a::Automaton, s) +``` + + +Internal method used by `accept` with `Automaton`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L20-L24) + +
+
+ +### Performances – TODO {#Performances-–-TODO-2} + +## Extensions + +We extended some operations for `Nothing` and `Symbol`. + +::: warning Missing docstring. + +Missing docstring for `Base.:*`. Check Documenter's build log for details. + +::: + +::: warning Missing docstring. + +Missing docstring for `Base.in(::Any, ::Nothing)`. Check Documenter's build log for details. + +::: + +::: warning Missing docstring. + +Missing docstring for `Base.isempty(::Nothing)`. Check Documenter's build log for details. + +::: + +### Performances – TODO {#Performances-–-TODO-3} + +## Sampling + +During our constraint learning processes, we use sampling to efficiently make partial exploration of search spaces. Follows some sampling utilities. +
+# ConstraintCommons.oversampleFunction. + + + + +```julia +oversample(X, f) +``` + + +Oversample elements of `X` until the boolean function `f` has as many `true` and `false` configurations. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/sampling.jl#L1-L5) + +
+
+ +### Performances – TODO {#Performances-–-TODO-4} + +## Extrema + +We need to compute the difference between extrema of various kind of collections in several situations. +
+# ConstraintCommons.δ_extremaFunction. + + + + +```julia +δ_extrema(X...) +``` + + +Compute both the difference between the maximum and the minimum of over all the collections of `X`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/extrema.jl#L1-L4) + +
+
+ +### Performances – TODO {#Performances-–-TODO-5} + +## Dictionaries + +We provide the everuseful `incsert!` function for dictionaries. +
+# ConstraintCommons.incsert!Function. + + + + +```julia +incsert!(d::Union{AbstractDict, AbstractDictionary}, ind, val = 1) +``` + + +Increase or insert a counter in a dictionary-based collection. The counter insertion defaults to `val = 1`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/dictionaries.jl#L2-L6) + +
+
+ +### Performances – TODO {#Performances-–-TODO-6} diff --git a/previews/PR50/.documenter/constraints/constraint_domains.md b/previews/PR50/.documenter/constraints/constraint_domains.md new file mode 100644 index 0000000..7b22526 --- /dev/null +++ b/previews/PR50/.documenter/constraints/constraint_domains.md @@ -0,0 +1,1736 @@ + +# ConstraintDomains.jl: Defining and Exploring Variable Domains within JuliaConstraints {#ConstraintDomains.jl:-Defining-and-Exploring-Variable-Domains-within-JuliaConstraints} + + + +_ConstraintDomains.jl_ stands as a critical package within the _Julia Constraints_ ecosystem, focusing on the definition and manipulation of variable domains that underpin the search spaces of constraint programming problems. This package provides the infrastructure necessary for specifying both discrete and continuous domains, thereby enabling a broad range of constraint programming applications. + +## Key Features and Functionalities {#Key-Features-and-Functionalities} +- **AbstractDomain Super Type**: At the foundation of ConstraintDomains.jl is the AbstractDomain type, an abstract supertype for all domain types. Implementations of AbstractDomain must provide methods for checking membership (∈), generating random elements (rand), and determining the domain's size or range (length). These functionalities are essential for defining the behavior and properties of variable domains within constraint models. + +- **Domain Types**: The package distinguishes between various domain types to cater to different needs: + - _ContinuousDomain_: A supertype for domains representing continuous ranges of real numbers. + + - _DiscreteDomain_: Serves as a supertype for domains defined by discrete sets or ranges of numbers. + + - _EmptyDomain_: Handles yet-to-be-defined domains, facilitating dynamic problem formulation. + + - _Intervals and RangeDomain_: Represent continuous intervals and discrete ranges, respectively, providing flexible domain specification options. + + +- **Dynamic Domain Manipulation**: ConstraintDomains.jl supports dynamic changes to domains, allowing for the addition (add!) and deletion (delete!) of elements, crucial for problems where domain definitions evolve based on the search process or external inputs. + +- **Exploration Settings and Methods**: The package offers ExploreSettings to configure the exploration of search spaces, including parameters for complete searches, maximum samplings, and solution limits. This feature is pivotal for tailoring the search process to the problem's characteristics and the computational resources available. + +- **Support for Advanced Modeling**: Beyond basic domain definition and manipulation, ConstraintDomains.jl integrates with learning and parameter exploration tools. For instance, FakeAutomaton facilitates the generation of pseudo-automata for parameter exploration, while the package also provides functions for generating random parameters (generate_parameters), accessing domain internals (get_domain), and merging or intersecting domains (merge_domains, intersect_domains). + + +## Empowering Constraint Programming in Julia {#Empowering-Constraint-Programming-in-Julia} + +ConstraintDomains.jl embodies the versatility and power of the JuliaConstraints ecosystem, offering users a comprehensive toolkit for defining and exploring variable domains. By abstracting complex domain manipulations and providing a rich set of functionalities, ConstraintDomains.jl enhances the ease and efficiency of modeling constraint programming problems. Whether for educational purposes, research, or practical applications, this package lays the groundwork for advanced problem-solving strategies in the realm of constraint programming. + +## Commons +
+# ConstraintDomains.AbstractDomainType. + + + + +```julia +AbstractDomain +``` + + +An abstract super type for any domain type. A domain type `D <: AbstractDomain` must implement the following methods to properly interface `AbstractDomain`. +- `Base.∈(val, ::D)` + +- `Base.rand(::D)` + +- `Base.length(::D)` that is the number of elements in a discrete domain, and the distance between bounds or similar for a continuous domain + + +Additionally, if the domain is used in a dynamic context, it can extend +- `add!(::D, args)` + +- `delete!(::D, args)` + + +where `args` depends on `D`'s structure + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L1-L11) + +
+
+
+# ConstraintDomains.EmptyDomainType. + + + + +```julia +EmptyDomain +``` + + +A struct to handle yet to be defined domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L14-L17) + +
+
+
+# ConstraintDomains.domainFunction. + + + + +```julia +domain() +``` + + +Construct an `EmptyDomain`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L20-L23) + + + +```julia +domain(a::Tuple{T, Bool}, b::Tuple{T, Bool}) where {T <: Real} +domain(intervals::Vector{Tuple{Tuple{T, Bool},Tuple{T, Bool}}}) where {T <: Real} +``` + + +Construct a domain of continuous interval(s). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L15-L19) + + + +```julia +domain(values) +domain(range::R) where {T <: Real, R <: AbstractRange{T}} +``` + + +Construct either a `SetDomain` or a `RangeDomain``. + +```julia +d1 = domain(1:5) +d2 = domain([53.69, 89.2, 0.12]) +d3 = domain([2//3, 89//123]) +d4 = domain(4.3) +d5 = domain(1,42,86.9) +``` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L31-L42) + +
+
+
+# ConstraintDomains.domain_sizeFunction. + + + + +```julia +domain_size(d <: AbstractDomain) +``` + + +Fallback method for `domain_size(d)` that return `length(d)`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L46-L49) + + + +```julia +domain_size(itv::Intervals) +``` + + +Return the difference between the highest and lowest values in `itv`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L61-L64) + + + +```julia +domain_size(d::D) where D <: DiscreteDomain +``` + + +Return the maximum distance between two points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L64-L67) + +
+
+
+# ConstraintDomains.get_domainFunction. + + + + +```julia +get_domain(::AbstractDomain) +``` + + +Access the internal structure of any domain type. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L52-L55) + +
+
+
+# ConstraintDomains.to_domainsFunction. + + + + +```julia +to_domains(args...) +``` + + +Convert various arguments into valid domains format. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L58-L62) + +
+
+ +### Extension to Base module {#Extension-to-Base-module} +
+# Base.inFunction. + + + + +```julia +x::Variable ∈ constraint +value ∈ x::Variable +``` + + +Check if a variable `x` is restricted by a `constraint::Int`, or if a `value` belongs to the domain of `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L52-L56) + + + +```julia +var::Int ∈ c::Constraint +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L43-L45) + + + +```julia +Base.in(value, d <: AbstractDomain) +``` + + +Fallback method for `value ∈ d` that returns `false`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L28-L31) + + + +```julia +Base.in(x, itv::Intervals) +``` + + +Return `true` if `x ∈ I` for any 'I ∈ itv`, false otherwise.`x ∈ I` is equivalent to +- `a < x < b` if `I = (a, b)` + +- `a < x ≤ b` if `I = (a, b]` + +- `a ≤ x < b` if `I = [a, b)` + +- `a ≤ x ≤ b` if `I = [a, b]` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L51-L58) + + + +```julia +Base.in(value, d::D) where D <: DiscreteDomain +``` + + +Return `true` if `value` is a point of `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L58-L61) + +
+
+
+# Base.randFunction. + + + + +```julia +Base.rand(d::Union{Vector{D},Set{D}, D}) where {D<:AbstractDomain} +``` + + +Extends `Base.rand` to (a collection of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L72-L76) + + + +```julia +Base.rand(itv::Intervals) +Base.rand(itv::Intervals, i) +``` + + +Return a random value from `itv`, specifically from the `i`th interval if `i` is specified. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L32-L36) + + + +```julia +Base.rand(d::D) where D <: DiscreteDomain +``` + + +Draw randomly a point in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L52-L55) + + + +```julia +Base.rand(fa::FakeAutomaton) +``` + + +Extends `Base.rand`. Currently simply returns `fa`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L135-L139) + +
+
+
+# Base.isemptyFunction. + + + + +```julia +Base.isempty(d <: AbstractDomain) +``` + + +Fallback method for `isempty(d)` that return `length(d) == 0` which default to `0`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L40-L43) + +
+
+
+# Base.randFunction. + + + + +```julia +Base.rand(d::Union{Vector{D},Set{D}, D}) where {D<:AbstractDomain} +``` + + +Extends `Base.rand` to (a collection of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L72-L76) + + + +```julia +Base.rand(itv::Intervals) +Base.rand(itv::Intervals, i) +``` + + +Return a random value from `itv`, specifically from the `i`th interval if `i` is specified. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L32-L36) + + + +```julia +Base.rand(d::D) where D <: DiscreteDomain +``` + + +Draw randomly a point in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L52-L55) + + + +```julia +Base.rand(fa::FakeAutomaton) +``` + + +Extends `Base.rand`. Currently simply returns `fa`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L135-L139) + +
+
+
+# Base.stringFunction. + + + + +```julia +Base.string(D::Vector{<:AbstractDomain}) +Base.string(d<:AbstractDomain) +``` + + +Extends the `string` method to (a vector of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L87-L92) + +
+
+ +### Performances + +## Continuous +
+# ConstraintDomains.ContinuousDomainType. + + + + +```julia +ContinuousDomain{T <: Real} <: AbstractDomain +``` + + +An abstract supertype for all continuous domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L1-L4) + +
+
+
+# ConstraintDomains.IntervalsType. + + + + +```julia +Intervals{T <: Real} <: ContinuousDomain{T} +``` + + +An encapsuler to store a vector of `PatternFolds.Interval`. Dynamic changes to `Intervals` are not handled yet. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L7-L10) + +
+
+
+# ConstraintDomains.domainFunction. + + + + +```julia +domain() +``` + + +Construct an `EmptyDomain`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L20-L23) + + + +```julia +domain(a::Tuple{T, Bool}, b::Tuple{T, Bool}) where {T <: Real} +domain(intervals::Vector{Tuple{Tuple{T, Bool},Tuple{T, Bool}}}) where {T <: Real} +``` + + +Construct a domain of continuous interval(s). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L15-L19) + + + +```julia +domain(values) +domain(range::R) where {T <: Real, R <: AbstractRange{T}} +``` + + +Construct either a `SetDomain` or a `RangeDomain``. + +```julia +d1 = domain(1:5) +d2 = domain([53.69, 89.2, 0.12]) +d3 = domain([2//3, 89//123]) +d4 = domain(4.3) +d5 = domain(1,42,86.9) +``` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L31-L42) + +
+
+
+# ConstraintDomains.domain_sizeFunction. + + + + +```julia +domain_size(d <: AbstractDomain) +``` + + +Fallback method for `domain_size(d)` that return `length(d)`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L46-L49) + + + +```julia +domain_size(itv::Intervals) +``` + + +Return the difference between the highest and lowest values in `itv`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L61-L64) + + + +```julia +domain_size(d::D) where D <: DiscreteDomain +``` + + +Return the maximum distance between two points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L64-L67) + +
+
+
+# ConstraintDomains.merge_domainsFunction. + + + + +```julia +merge_domains(d₁::AbstractDomain, d₂::AbstractDomain) +``` + + +Merge two domains of same nature (discrete/contiuous). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L83-L87) + +
+
+
+# ConstraintDomains.intersect_domainsFunction. + + + + +```julia +intersect_domains(d₁, d₂) +``` + + +Compute the intersections of two domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L72-L76) + +
+
+
+# ConstraintDomains.intersect_domains!Function. + + + + +```julia +intersect_domains!(is, i, new_itvls) +``` + + +Compute the intersections of a domain with an interval and store the results in `new_itvls`. + +**Arguments** +- `is::IS`: a collection of intervals. + +- `i::I`: an interval. + +- `new_itvls::Vector{I}`: a vector to store the results. + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L89-L98) + +
+
+
+# ConstraintDomains.sizeFunction. + + + + +```julia +Base.size(i::I) where {I <: Interval} +``` + + +Defines the size of an interval as its `span`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L118-L122) + +
+
+ +### Extension to Base module {#Extension-to-Base-module-2} +
+# Base.lengthFunction. + + + + +```julia +length(layer) +``` + + +Return the number of operations in a layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L17-L20) + + + +```julia +Base.length(icn) +``` + + +Return the total number of operations of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L37-L40) + + + +```julia +Base.rand(d <: AbstractDomain) +``` + + +Fallback method for `length(d)` that return `0`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L34-L37) + + + +```julia +Base.length(itv::Intervals) +``` + + +Return the sum of the length of each interval in `itv`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L26-L29) + + + +```julia +Base.length(d::D) where D <: DiscreteDomain +``` + + +Return the number of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L46-L49) + +
+
+
+# Base.randFunction. + + + + +```julia +Base.rand(d::Union{Vector{D},Set{D}, D}) where {D<:AbstractDomain} +``` + + +Extends `Base.rand` to (a collection of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L72-L76) + + + +```julia +Base.rand(itv::Intervals) +Base.rand(itv::Intervals, i) +``` + + +Return a random value from `itv`, specifically from the `i`th interval if `i` is specified. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L32-L36) + + + +```julia +Base.rand(d::D) where D <: DiscreteDomain +``` + + +Draw randomly a point in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L52-L55) + + + +```julia +Base.rand(fa::FakeAutomaton) +``` + + +Extends `Base.rand`. Currently simply returns `fa`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L135-L139) + +
+
+
+# Base.inFunction. + + + + +```julia +x::Variable ∈ constraint +value ∈ x::Variable +``` + + +Check if a variable `x` is restricted by a `constraint::Int`, or if a `value` belongs to the domain of `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L52-L56) + + + +```julia +var::Int ∈ c::Constraint +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L43-L45) + + + +```julia +Base.in(value, d <: AbstractDomain) +``` + + +Fallback method for `value ∈ d` that returns `false`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L28-L31) + + + +```julia +Base.in(x, itv::Intervals) +``` + + +Return `true` if `x ∈ I` for any 'I ∈ itv`, false otherwise.`x ∈ I` is equivalent to +- `a < x < b` if `I = (a, b)` + +- `a < x ≤ b` if `I = (a, b]` + +- `a ≤ x < b` if `I = [a, b)` + +- `a ≤ x ≤ b` if `I = [a, b]` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L51-L58) + + + +```julia +Base.in(value, d::D) where D <: DiscreteDomain +``` + + +Return `true` if `value` is a point of `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L58-L61) + +
+
+
+# Base.stringFunction. + + + + +```julia +Base.string(D::Vector{<:AbstractDomain}) +Base.string(d<:AbstractDomain) +``` + + +Extends the `string` method to (a vector of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L87-L92) + +
+
+ +## Discrete +
+# ConstraintDomains.DiscreteDomainType. + + + + +```julia +DiscreteDomain{T <: Number} <: AbstractDomain +``` + + +An abstract supertype for discrete domains (set, range). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L1-L4) + +
+
+
+# ConstraintDomains.SetDomainType. + + + + +```julia +SetDomain{T <: Number} <: DiscreteDomain{T} +``` + + +Domain that stores discrete values as a set of (unordered) points. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L7-L10) + +
+
+
+# ConstraintDomains.RangeDomainType. + + + + +```julia +RangeDomain +``` + + +A discrete domain defined by a `range <: AbstractRange{Real}`. As ranges are immutable in Julia, changes in `RangeDomain` must use `set_domain!`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L16-L19) + +
+
+
+# ConstraintDomains.ArbitraryDomainFunction. + + + + +```julia +ArbitraryDomain{T} <: DiscreteDomain{T} +``` + + +A domain type that stores arbitrary values, possibly non numeric, of type `T`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L24-L28) + +
+
+
+# ConstraintDomains.domainFunction. + + + + +```julia +domain() +``` + + +Construct an `EmptyDomain`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L20-L23) + + + +```julia +domain(a::Tuple{T, Bool}, b::Tuple{T, Bool}) where {T <: Real} +domain(intervals::Vector{Tuple{Tuple{T, Bool},Tuple{T, Bool}}}) where {T <: Real} +``` + + +Construct a domain of continuous interval(s). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L15-L19) + + + +```julia +domain(values) +domain(range::R) where {T <: Real, R <: AbstractRange{T}} +``` + + +Construct either a `SetDomain` or a `RangeDomain``. + +```julia +d1 = domain(1:5) +d2 = domain([53.69, 89.2, 0.12]) +d3 = domain([2//3, 89//123]) +d4 = domain(4.3) +d5 = domain(1,42,86.9) +``` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L31-L42) + +
+
+
+# ConstraintDomains.domain_sizeFunction. + + + + +```julia +domain_size(d <: AbstractDomain) +``` + + +Fallback method for `domain_size(d)` that return `length(d)`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L46-L49) + + + +```julia +domain_size(itv::Intervals) +``` + + +Return the difference between the highest and lowest values in `itv`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L61-L64) + + + +```julia +domain_size(d::D) where D <: DiscreteDomain +``` + + +Return the maximum distance between two points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L64-L67) + +
+
+
+# ConstraintDomains.add!Function. + + + + +```julia +add!(d::SetDomain, value) +``` + + +Add `value` to the list of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L70-L73) + +
+
+
+# ConstraintDomains.merge_domainsFunction. + + + + +```julia +merge_domains(d₁::AbstractDomain, d₂::AbstractDomain) +``` + + +Merge two domains of same nature (discrete/contiuous). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L83-L87) + +
+
+
+# ConstraintDomains.intersect_domainsFunction. + + + + +```julia +intersect_domains(d₁, d₂) +``` + + +Compute the intersections of two domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L72-L76) + +
+
+
+# ConstraintDomains.sizeFunction. + + + + +```julia +Base.size(i::I) where {I <: Interval} +``` + + +Defines the size of an interval as its `span`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L118-L122) + +
+
+ +### Extension to Base module {#Extension-to-Base-module-3} +
+# Base.delete!Function. + + + + +```julia +Base.delete!(d::SetDomain, value)(d::SetDomain, value) +``` + + +Delete `value` from the list of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L76-L79) + +
+
+
+# Base.lengthFunction. + + + + +```julia +length(layer) +``` + + +Return the number of operations in a layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L17-L20) + + + +```julia +Base.length(icn) +``` + + +Return the total number of operations of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L37-L40) + + + +```julia +Base.rand(d <: AbstractDomain) +``` + + +Fallback method for `length(d)` that return `0`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L34-L37) + + + +```julia +Base.length(itv::Intervals) +``` + + +Return the sum of the length of each interval in `itv`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L26-L29) + + + +```julia +Base.length(d::D) where D <: DiscreteDomain +``` + + +Return the number of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L46-L49) + +
+
+
+# Base.randFunction. + + + + +```julia +Base.rand(d::Union{Vector{D},Set{D}, D}) where {D<:AbstractDomain} +``` + + +Extends `Base.rand` to (a collection of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L72-L76) + + + +```julia +Base.rand(itv::Intervals) +Base.rand(itv::Intervals, i) +``` + + +Return a random value from `itv`, specifically from the `i`th interval if `i` is specified. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L32-L36) + + + +```julia +Base.rand(d::D) where D <: DiscreteDomain +``` + + +Draw randomly a point in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L52-L55) + + + +```julia +Base.rand(fa::FakeAutomaton) +``` + + +Extends `Base.rand`. Currently simply returns `fa`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L135-L139) + +
+
+
+# Base.inFunction. + + + + +```julia +x::Variable ∈ constraint +value ∈ x::Variable +``` + + +Check if a variable `x` is restricted by a `constraint::Int`, or if a `value` belongs to the domain of `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L52-L56) + + + +```julia +var::Int ∈ c::Constraint +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L43-L45) + + + +```julia +Base.in(value, d <: AbstractDomain) +``` + + +Fallback method for `value ∈ d` that returns `false`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L28-L31) + + + +```julia +Base.in(x, itv::Intervals) +``` + + +Return `true` if `x ∈ I` for any 'I ∈ itv`, false otherwise.`x ∈ I` is equivalent to +- `a < x < b` if `I = (a, b)` + +- `a < x ≤ b` if `I = (a, b]` + +- `a ≤ x < b` if `I = [a, b)` + +- `a ≤ x ≤ b` if `I = [a, b]` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L51-L58) + + + +```julia +Base.in(value, d::D) where D <: DiscreteDomain +``` + + +Return `true` if `value` is a point of `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L58-L61) + +
+
+
+# Base.stringFunction. + + + + +```julia +Base.string(D::Vector{<:AbstractDomain}) +Base.string(d<:AbstractDomain) +``` + + +Extends the `string` method to (a vector of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L87-L92) + +
+
+ +## General +
+# Base.eltypeFunction. + + + + +```julia +Base.eltype(::AbstractDomain) +``` + + +Extend `eltype` for domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/general.jl#L1-L5) + +
+
+
+# Base.convertFunction. + + + + +```julia +Base.convert(::Type{Union{Intervals, RangeDomain}}, d::Union{Intervals, RangeDomain}) +``` + + +Extends `Base.convert` for domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/general.jl#L9-L13) + +
+
+ +## Exploration +
+# ConstraintDomains.ExploreSettingsType. + + + + +```julia +ExploreSettings( + domains; + complete_search_limit = 10^6, + max_samplings = sum(domain_size, domains), + search = :flexible, + solutions_limit = floor(Int, sqrt(max_samplings)), +) +``` + + +Settings for the exploration of a search space composed by a collection of domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/explore.jl#L8-L18) + +
+
+
+# ConstraintDomains._exploreFunction. + + + + +```julia +_explore(args...) +``` + + +Internals of the `explore` function. Behavior is automatically adjusted on the kind of exploration: `:flexible`, `:complete`, `:partial`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/explore.jl#L29-L33) + +
+
+
+# ConstraintDomains.exploreFunction. + + + + +```julia +explore(domains, concept, param = nothing; search_limit = 1000, solutions_limit = 100) +``` + + +Search (a part of) a search space and returns a pair of vector of configurations: `(solutions, non_solutions)`. If the search space size is over `search_limit`, then both `solutions` and `non_solutions` are limited to `solutions_limit`. + +Beware that if the density of the solutions in the search space is low, `solutions_limit` needs to be reduced. This process will be automatic in the future (simple reinforcement learning). + +**Arguments:** +- `domains`: a collection of domains + +- `concept`: the concept of the targeted constraint + +- `param`: an optional parameter of the constraint + +- `sol_number`: the required number of solutions (half of the number of configurations), default to `100` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/explore.jl#L66-L78) + +
+
+ +## Parameters +
+# ConstraintDomains.BoolParameterDomainType. + + + + +```julia +BoolParameterDomain <: AbstractDomain +``` + + +A domain to store boolean values. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L1-L5) + +
+
+
+# ConstraintDomains.DimParameterDomainType. + + + + +```julia +DimParameterDomain <: AbstractDomain +``` + + +A domain to store dimensions. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L10-L14) + +
+
+
+# ConstraintDomains.IdParameterDomainType. + + + + +```julia +IdParameterDomain <: AbstractDomain +``` + + +A domain to store ids. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L21-L25) + +
+
+
+# ConstraintDomains.FakeAutomatonType. + + + + +```julia +FakeAutomaton{T} <: ConstraintCommons.AbstractAutomaton +``` + + +A structure to generate pseudo automaton enough for parameter exploration. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L32-L36) + +
+
+
+# ConstraintCommons.acceptFunction. + + + + +```julia +accept(a::Union{Automaton, MDD}, w) +``` + + +Return `true` if `a` accepts the word `w` and `false` otherwise. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L29-L33) + + + +```julia +ConstraintCommons.accept(fa::FakeAutomaton, word) +``` + + +Implement the `accept` methods for `FakeAutomaton`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L41-L45) + +
+
+
+# ConstraintDomains.fake_automatonFunction. + + + + +```julia +fake_automaton(d) +``` + + +Construct a `FakeAutomaton`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L48-L52) + +
+
+
+# ConstraintDomains.LanguageParameterDomainType. + + + + +```julia +LanguageParameterDomain <: AbstractDomain +``` + + +A domain to store languages. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L62-L66) + +
+
+
+# ConstraintDomains.OpParameterDomainType. + + + + +```julia +OpParameterDomain{T} <: AbstractDomain +``` + + +A domain to store operators. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L75-L79) + +
+
+
+# ConstraintDomains.PairVarsParameterDomainType. + + + + +```julia +PairVarsParameterDomain{T} <: AbstractDomain +``` + + +A domain to store values paired with variables. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L86-L90) + +
+
+
+# ConstraintDomains.ValParameterDomainType. + + + + +```julia +ValParameterDomain{T} <: AbstractDomain +``` + + +A domain to store one value. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L99-L103) + +
+
+
+# ConstraintDomains.ValsParameterDomainType. + + + + +```julia +ValsParameterDomain{T} <: AbstractDomain +``` + + +A domain to store values. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L110-L114) + +
+
+
+# Base.randFunction. + + + + +```julia +Base.rand(d::Union{Vector{D},Set{D}, D}) where {D<:AbstractDomain} +``` + + +Extends `Base.rand` to (a collection of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L72-L76) + + + +```julia +Base.rand(itv::Intervals) +Base.rand(itv::Intervals, i) +``` + + +Return a random value from `itv`, specifically from the `i`th interval if `i` is specified. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L32-L36) + + + +```julia +Base.rand(d::D) where D <: DiscreteDomain +``` + + +Draw randomly a point in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L52-L55) + + + +```julia +Base.rand(fa::FakeAutomaton) +``` + + +Extends `Base.rand`. Currently simply returns `fa`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L135-L139) + +
+
+
+# ConstraintDomains.generate_parametersFunction. + + + + +```julia +generate_parameters(d<:AbstractDomain, param) +``` + + +Generates random parameters based on the domain `d` and the kind of parameters `param`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L128-L132) + +
+
diff --git a/previews/PR50/.documenter/constraints/constraint_models.md b/previews/PR50/.documenter/constraints/constraint_models.md new file mode 100644 index 0000000..fc1891a --- /dev/null +++ b/previews/PR50/.documenter/constraints/constraint_models.md @@ -0,0 +1,425 @@ + +# ConstraintModels.jl + +Documentation for `ConstraintModels.jl`. +
+# ConstraintModels.SudokuInstanceType. + + + + +```julia +mutable struct SudokuInstance{T <: Integer} <: AbstractMatrix{T} +``` + + +**A `struct` for SudokuInstances, which is a subtype of `AbstractMatrix`.** + +```julia +SudokuInstance(A::AbstractMatrix{T}) +SudokuInstance(::Type{T}, n::Int) # fill in blank sudoku of type T +SudokuInstance(n::Int) # fill in blank sudoku of type Int +SudokuInstance(::Type{T}) # fill in "standard" 9×9 sudoku of type T +SudokuInstance() # fill in "standard" 9×9 sudoku of type Int +SudokuInstance(n::Int, P::Pair{Tuple{Int, Int}, T}...) where {T <: Integer} # construct a sudoku given pairs of coordinates and values +SudokuInstance(P::Pair{Tuple{Int, Int}, T}...) # again, default to 9×9 sudoku, constructing given pairs +``` + + +Constructor functions for the `SudokuInstance` `struct`. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L124-L140) + +
+
+
+# ConstraintModels.SudokuInstanceMethod. + + + + +```julia +SudokuInstance(X::Dictionary) +``` + + +Construct a `SudokuInstance` with the values `X` of a solver as input. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L167-L171) + +
+
+
+# Base.Multimedia.displayMethod. + + + + +```julia +display(io::IO, S::SudokuInstance) +display(S::SudokuInstance) # default to stdout +``` + + +Displays an $n\times n$ SudokuInstance. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L314-L320) + +
+
+
+# Base.Multimedia.displayMethod. + + + + +```julia +Base.display(X, Val(:sudoku)) +``` + + +Extends `Base.display` to a sudoku configuration. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L350-L354) + +
+
+
+# Base.Multimedia.displayMethod. + + + + +```julia +Base.display(S::SudokuInstance) +``` + + +Extends `Base.display` to `SudokuInstance`. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L336-L340) + +
+
+
+# Base.Multimedia.displayMethod. + + + + +```julia +Base.display(X::Dictionary) +``` + + +Extends `Base.display` to a sudoku configuration. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L343-L347) + +
+
+
+# Base.sizeMethod. + + + + +```julia +Base.size(S::SudokuInstance) +``` + + +Extends `Base.size` for `SudokuInstance`. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L183-L187) + +
+
+
+# ConstraintModels._format_lineMethod. + + + + +```julia +_format_line(r, M) +``` + + +Format line of a sudoku grid. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L251-L255) + +
+
+
+# ConstraintModels._format_line_segmentMethod. + + + + +```julia +_format_line_segment(r, col_pos, M) +``` + + +Format line segment of a sudoku grid. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L230-L234) + +
+
+
+# ConstraintModels._format_valMethod. + + + + +```julia +_format_val(a) +``` + + +Format an integer `a` into a string for SudokuInstance. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L223-L227) + +
+
+
+# ConstraintModels._get_sep_lineMethod. + + + + +```julia +_get_sep_line(s, pos_row, M) +``` + + +Return a line separator. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L268-L272) + +
+
+
+# ConstraintModels.chemical_equilibriumMethod. + + + + +```julia +chemical_equilibrium(atoms_compounds, elements_weights, standard_free_energy; modeler = :JuMP) +``` + + +::: warning Warning + +Even the structure to model problems with continuous domains is available, the default solver is not yet equiped to solve such problems efficiently. + +::: + +**From Wikipedia** + +In a chemical reaction, chemical equilibrium is the state in which both the reactants and products are present in concentrations which have no further tendency to change with time, so that there is no observable change in the properties of the system. This state results when the forward reaction proceeds at the same rate as the reverse reaction. The reaction rates of the forward and backward reactions are generally not zero, but they are equal. Thus, there are no net changes in the concentrations of the reactants and products. Such a state is known as dynamic equilibrium. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/chemical_equilibrium.jl#L30-L40) + +
+
+
+# ConstraintModels.golombFunction. + + + + +```julia +golomb(n, L=n²) +``` + + +Model the Golomb problem of `n` marks on the ruler `0:L`. The `modeler` argument accepts :raw, and :JuMP (default), which refer respectively to the solver internal model, the MathOptInterface model, and the JuMP model. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/golomb.jl#L53-L57) + +
+
+
+# ConstraintModels.magic_squareMethod. + + + + +```julia +magic_square(n; modeler = :JuMP) +``` + + +Create a model for the magic square problem of order `n`. The `modeler` argument accepts :JuMP (default), which refer to the solver the JuMP model. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/magic_square.jl#L19-L23) + +
+
+
+# ConstraintModels.mincutMethod. + + + + +```julia +mincut(graph; source, sink, interdiction =0, modeler = :JuMP) +``` + + +Compute the minimum cut of a graph. + +**Arguments:** +- `graph`: Any matrix <: AbstractMatrix that describes the capacities of the graph + +- `source`: Id of the source node; must be set + +- `sink`: Id of the sink node; must be set + +- `interdiction`: indicates the number of forbidden links + +- `modeler`: Default to `:JuMP`. + + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/cut.jl#L47-L58) + +
+
+
+# ConstraintModels.n_queensMethod. + + + + +```julia +n_queens(n; modeler = :JuMP) +``` + + +Create a model for the n-queens problem with `n` queens. The `modeler` argument accepts :JuMP (default), which refer to the JuMP model. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/n_queens.jl#L16-L20) + +
+
+
+# ConstraintModels.qapMethod. + + + + +```julia +qap(n, weigths, distances; modeler = :JuMP) +``` + + +Modelize an instance of the Quadractic Assignment Problem with +- `n`: number of both facilities and locations + +- `weights`: `Matrix` of the weights of each pair of facilities + +- `distances`: `Matrix` of distances between locations + +- `modeler`: Default to `:JuMP`. No other modeler available for now. + + +**From Wikipedia** + +There are a set of `n` facilities and a set of `n` locations. For each pair of locations, a distance is specified and for each pair of facilities a `weight` or flow is specified (e.g., the amount of supplies transported between the two facilities). The problem is to assign all facilities to different locations with the goal of minimizing the sum of the `distances` multiplied by the corresponding flows. + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/assignment.jl#L14-L25) + +
+
+
+# ConstraintModels.schedulingMethod. + + + + +```julia +scheduling(processing_time, due_date; modeler=:JuMP) +``` + + +Create a model for the n-queens problem with `n` queens. The `modeler` argument accepts :JuMP (default), which refer to the JuMP model. + +::: warning Warning + +The model seems to have a flaw. Needs to be investigated. + +::: + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/scheduling.jl#L46-L55) + +
+
+
+# ConstraintModels.sudokuMethod. + + + + +```julia +sudoku(n; start= Dictionary{Int, Int}(), modeler = :JuMP) +``` + + +Create a model for the sudoku problem of domain `1:n²` with optional starting values. The `modeler` argument accepts :raw, :MOI, and :JuMP (default), which refer respectively to the solver internal model, the MathOptInterface model, and the JuMP model. + +```julia +# Construct a JuMP model `m` and its associated matrix `grid` for sudoku 9×9 +m, grid = sudoku(3) + +# Same with a starting instance +instance = [ + 9 3 0 0 0 0 0 4 0 + 0 0 0 0 4 2 0 9 0 + 8 0 0 1 9 6 7 0 0 + 0 0 0 4 7 0 0 0 0 + 0 2 0 0 0 0 0 6 0 + 0 0 0 0 2 3 0 0 0 + 0 0 8 5 3 1 0 0 2 + 0 9 0 2 8 0 0 0 0 + 0 7 0 0 0 0 0 5 3 +] +m, grid = sudoku(3, start = instance) + +# Run the solver +optimize!(m) + +# Retrieve and display the values +solution = value.(grid) +display(solution, Val(:sudoku)) +``` + + + +[source](https://github.com/JuliaConstraints/ConstraintModels.jl/blob/v0.1.9/src/sudoku.jl#L92-L121) + +
+
diff --git a/previews/PR50/.documenter/constraints/constraints.md b/previews/PR50/.documenter/constraints/constraints.md new file mode 100644 index 0000000..0d876f8 --- /dev/null +++ b/previews/PR50/.documenter/constraints/constraints.md @@ -0,0 +1,528 @@ + +# Constraints.jl: Streamlining Constraint Definition and Integration in Julia {#Constraints.jl:-Streamlining-Constraint-Definition-and-Integration-in-Julia} + + + +_Constraints.jl_ is a pivotal package within the JuliaConstraints ecosystem, designed to facilitate the definition, manipulation, and application of constraints in constraint programming (CP). This package is central to handling both standard and complex constraints, making it an indispensable tool for developers and researchers working in CP. + +## Key Features and Functionalities {#Key-Features-and-Functionalities} +- **Integration of XCSP3-core Constraints**: One of the standout features of Constraints.jl is its incorporation of the XCSP3-core constraints as usual constraints within Julia. This integration ensures that users can define and work with a wide range of standard constraints, following the specifications outlined in the XCSP3-core, directly in Julia. The use of `USUAL_CONSTRAINTS` dictionary allows for straightforward addition and manipulation of these constraints, enhancing the package's utility and flexibility. + +- **Learning Package Integration**: Constraints.jl goes beyond traditional constraint handling by offering the capability to include results from various learning packages within the JuliaConstraints organization. This feature allows for the enhancement of usual constraints and those from the Global Constraints Catalog with learned parameters and behaviors, significantly improving constraint applicability and performance in complex CP problems. + +- **Constraint Definition and Symmetry Handling**: The package provides a simple yet powerful syntax for defining new constraints (`@usual`) and managing their symmetries through the `USUAL_SYMMETRIES` dictionary. This approach simplifies the creation of new constraints and the optimization of constraint search spaces by avoiding redundant explorations. + +- **Advanced Constraint Functionalities**: At the core of Constraints.jl is the `Constraint` type, encapsulating the essential elements of a constraint, including its concept (a Boolean function determining satisfaction) and an error function (providing a preference measure over invalid assignments). These components are crucial for defining how constraints behave and are evaluated within a CP model. + +- **Flexible Constraint Application**: The package supports a range of methods for interacting with constraints, such as `args`, `concept`, `error_f`, `params_length`, `symmetries`, and `xcsp_intension`. These methods offer users the ability to examine constraint properties, apply constraints to variable assignments, and work with intensional constraints defined by predicates. Such flexibility is vital for tailoring constraint behavior to specific problems and contexts. + + +## Enabling Advanced Modeling in Constraint Programming {#Enabling-Advanced-Modeling-in-Constraint-Programming} + +Constraints.jl embodies the JuliaConstraints ecosystem's commitment to providing robust, flexible tools for constraint programming. By integrating standard constraints, facilitating the incorporation of learned behaviors, and offering comprehensive tools for constraint definition and application, Constraints.jl significantly enhances the modeling capabilities available to CP practitioners. Whether for educational purposes, research, or solving practical CP problems, Constraints.jl offers a sophisticated, user-friendly platform for working with constraints in Julia. + +## Basic tools {#Basic-tools} +
+# Constraints.USUAL_SYMMETRIESConstant. + + + + +```julia +USUAL_SYMMETRIES +``` + + +A Dictionary that contains the function to apply for each symmetry to avoid searching a whole space. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L1-L4) + +
+
+
+# Constraints.ConstraintType. + + + + +```julia +Constraint +``` + + +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 assignments. Return `0.0` if the constraint is satisfied, and a strictly positive real otherwise. + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L7-L12) + +
+
+
+# Constraints.conceptFunction. + + + + +```julia +concept(c::Constraint) +``` + + +Return the concept (function) of constraint `c`. concept(c::Constraint, x...; param = nothing) Apply the concept of `c` to values `x` and optionally `param`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L40-L45) + + + +```julia +concept(s::Symbol, args...; kargs...) +``` + + +Return the concept of the constraint `s` applied to `args` and `kargs`. This is a shortcut for `concept(USUAL_CONSTRAINTS[s])(args...; kargs...)`. + +**Arguments** +- `s::Symbol`: the constraint name. + +- `args...`: the arguments to apply the concept to. + +- `kargs...`: the keyword arguments to apply the concept to. + + +**Example** + +```julia +concept(:all_different, [1, 2, 3]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L221-L235) + +
+
+
+# Constraints.error_fFunction. + + + + +```julia +error_f(c::Constraint) +``` + + +Return the error function of constraint `c`. error_f(c::Constraint, x; param = nothing) Apply the error function of `c` to values `x` and optionally `param`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L51-L56) + +
+
+
+# Constraints.argsFunction. + + + + +```julia +args(c::Constraint) +``` + + +Return the expected length restriction of the arguments in a constraint `c`. The value `nothing` indicates that any strictly positive number of value is accepted. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L62-L65) + +
+
+
+# Constraints.params_lengthFunction. + + + + +```julia +params_length(c::Constraint) +``` + + +Return the expected length restriction of the arguments in a constraint `c`. The value `nothing` indicates that any strictly positive number of parameters is accepted. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L68-L71) + +
+
+
+# Constraints.symmetriesFunction. + + + + +```julia +symmetries(c::Constraint) +``` + + +Return the list of symmetries of `c`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L74-L77) + +
+
+
+# Constraints.make_errorFunction. + + + + +```julia +make_error(symb::Symbol) +``` + + +Create a function that returns an error based on the predicate of the constraint identified by the symbol provided. + +**Arguments** +- `symb::Symbol`: The symbol used to determine the error function to be returned. The function first checks if a predicate with the prefix "icn_" exists in the Constraints module. If it does, it returns that function. If it doesn't, it checks for a predicate with the prefix "error_". If that exists, it returns that function. If neither exists, it returns a function that evaluates the predicate with the prefix "concept_" and returns the negation of its result cast to Float64. + + +**Returns** +- Function: A function that takes in a variable `x` and an arbitrary number of parameters `params`. The function returns a Float64. + + +**Examples** + +```julia +e = make_error(:all_different) +e([1, 2, 3]) # Returns 0.0 +e([1, 1, 3]) # Returns 1.0 +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L80-L97) + +
+
+
+# Constraints.shrink_conceptFunction. + + + + +```julia +shrink_concept(s) +``` + + +Simply delete the `concept_` part of symbol or string starting with it. TODO: add a check with a warning if `s` starts with something different. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L104-L108) + +
+
+
+# Constraints.concept_vs_errorFunction. + + + + +```julia +concept_vs_error(c, e, args...; kargs...) +``` + + +Compare the results of a concept function and an error function for the same inputs. It is mainly used for testing purposes. + +**Arguments** +- `c`: The concept function. + +- `e`: The error function. + +- `args...`: Positional arguments to be passed to both the concept and error functions. + +- `kargs...`: Keyword arguments to be passed to both the concept and error functions. + + +**Returns** +- Boolean: Returns true if the result of the concept function is not equal to whether the result of the error function is greater than 0.0. Otherwise, it returns false. + + +**Examples** + +```julia +concept_vs_error(all_different, make_error(:all_different), [1, 2, 3]) # Returns false +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L111-L129) + +
+
+ +## Usual constraints (based on and including XCSP3-core categories) {#Usual-constraints-(based-on-and-including-XCSP3-core-categories)} +
+# Constraints.USUAL_CONSTRAINTSConstant. + + + + +```julia +USUAL_CONSTRAINTS::Dict +``` + + +Dictionary that contains all the usual constraints defined in Constraint.jl. It is based on XCSP3-core specifications available at https://arxiv.org/abs/2009.00514 + +Adding a new constraint is as simple as defining a new function with the same name as the constraint and using the `@usual` macro to define it. The macro will take care of adding the new constraint to the `USUAL_CONSTRAINTS` dictionary. + +**Example** + +```julia +@usual concept_all_different(x; vals=nothing) = xcsp_all_different(list=x, except=vals) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L1-L11) + +
+
+
+# Constraints.describeFunction. + + + + +```julia +describe(constraints::Dict{Symbol,Constraint}=USUAL_CONSTRAINTS; width=150) +``` + + +Return a pretty table with the description of the constraints in `constraints`. + +**Arguments** +- `constraints::Dict{Symbol,Constraint}`: dictionary of constraints to describe. Default is `USUAL_CONSTRAINTS`. + +- `width::Int`: width of the table. + + +**Example** + +```julia +describe() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L14-L27) + +
+
+
+# ConstraintCommons.extract_parametersFunction. + + + + +```julia +extract_parameters(m::Union{Method, Function}; parameters) +``` + + +Extracts the intersection between the `kargs` of `m` and `parameters` (defaults to `USUAL_CONSTRAINT_PARAMETERS`). + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/parameters.jl#L21-L25) + + + +```julia +extract_parameters(s::Symbol, constraints_dict=USUAL_CONSTRAINTS; parameters=ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS) +``` + + +Return the parameters of the constraint `s` in `constraints_dict`. + +**Arguments** +- `s::Symbol`: the constraint name. + +- `constraints_dict::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + +- `parameters::Vector{Symbol}`: vector of parameters. Default is `ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS`. + + +**Example** + +```julia +extract_parameters(:all_different) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L44-L58) + +
+
+
+# Constraints.@usualMacro. + + + + +```julia +usual(ex::Expr) +``` + + +This macro is used to define a new constraint or update an existing one in the USUAL_CONSTRAINTS dictionary. It takes an expression ex as input, which represents the definition of a constraint. + +Here's a step-by-step explanation of what the macro does: +1. It first extracts the symbol of the concept from the input expression. This symbol is expected to be the first argument of the first argument of the expression. For example, if the expression is @usual all_different(x; y=1), the symbol would be :all_different. + +2. It then calls the shrink_concept function on the symbol to get a simplified version of the concept symbol. + +3. It initializes a dictionary defaults to store whether each keyword argument of the concept has a default value or not. + +4. It checks if the expression has more than two arguments. If it does, it means that there are keyword arguments present. It then loops over these keyword arguments. If a keyword argument is a symbol, it means it doesn't have a default value, so it adds an entry to the defaults dictionary with the keyword argument as the key and false as the value. If a keyword argument is not a symbol, it means it has a default value, so it adds an entry to the defaults dictionary with the keyword argument as the key and true as the value. + +5. It calls the make_error function on the simplified concept symbol to generate an error function for the constraint. + +6. It evaluates the input expression to get the concept function. + +7. It checks if the USUAL_CONSTRAINTS dictionary already contains an entry for the simplified concept symbol. If it does, it adds the defaults dictionary to the parameters of the existing constraint. If it doesn't, it creates a new constraint with the concept function, a description, the error function, and the defaults dictionary as the parameters, and adds it to the USUAL_CONSTRAINTS dictionary. + + +This macro is used to make it easier to define and update constraints in a consistent and possibly automated way. + +**Arguments** +- `ex::Expr`: expression to parse. + + +**Example** + +```julia +@usual concept_all_different(x; vals=nothing) = xcsp_all_different(list=x, except=vals) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L67-L90) + +
+
+
+# Constraints.constraints_parametersFunction. + + + + +```julia +constraints_parameters(C=USUAL_CONSTRAINTS) +``` + + +Return a pretty table with the parameters of the constraints in `C`. + +**Arguments** +- `C::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + + +**Example** + +```julia +constraints_parameters() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L127-L139) + +
+
+
+# Constraints.constraints_descriptionsFunction. + + + + +```julia +constraints_descriptions(C=USUAL_CONSTRAINTS) +``` + + +Return a pretty table with the descriptions of the constraints in `C`. + +**Arguments** +- `C::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + + +**Example** + +```julia +constraints_descriptions() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L180-L192) + +
+
+
+# Constraints.conceptFunction. + + + + +```julia +concept(c::Constraint) +``` + + +Return the concept (function) of constraint `c`. concept(c::Constraint, x...; param = nothing) Apply the concept of `c` to values `x` and optionally `param`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L40-L45) + + + +```julia +concept(s::Symbol, args...; kargs...) +``` + + +Return the concept of the constraint `s` applied to `args` and `kargs`. This is a shortcut for `concept(USUAL_CONSTRAINTS[s])(args...; kargs...)`. + +**Arguments** +- `s::Symbol`: the constraint name. + +- `args...`: the arguments to apply the concept to. + +- `kargs...`: the keyword arguments to apply the concept to. + + +**Example** + +```julia +concept(:all_different, [1, 2, 3]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L221-L235) + +
+
diff --git a/previews/PR50/.documenter/constraints/counting_summing_constraints.md b/previews/PR50/.documenter/constraints/counting_summing_constraints.md new file mode 100644 index 0000000..0c48299 --- /dev/null +++ b/previews/PR50/.documenter/constraints/counting_summing_constraints.md @@ -0,0 +1,249 @@ + +# Constraints.jl: Streamlining Constraint Definition and Integration in Julia {#Constraints.jl:-Streamlining-Constraint-Definition-and-Integration-in-Julia} + + + +### Counting and Summing Constraints {#Counting-and-Summing-Constraints} +
+# Constraints.xcsp_sumFunction. + + + + +```julia +xcsp_sum(list, coeffs, condition) +``` + + +Return `true` if the sum of the variables in `list` satisfies the given condition, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `coeffs::Vector{Int}`: list of coefficients to use. + +- `condition`: condition to satisfy. + + +**Variants** +- `:sum`: Global constraint ensuring that the sum of the variables in `x` satisfies a given condition. + + +```julia +concept(:sum, x; op===, pair_vars=ones(x), val) +concept(:sum)(x; op===, pair_vars=ones(x), val) +``` + + +**Examples** + +```julia +c = concept(:sum) + +c([1, 2, 3, 4, 5]; op===, val=15) +c([1, 2, 3, 4, 5]; op===, val=2) +c([1, 2, 3, 4, 3]; op=≤, val=15) +c([1, 2, 3, 4, 3]; op=≤, val=3) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/sum.jl#L5-L31) + +
+
+
+# Constraints.xcsp_countFunction. + + + + +```julia +xcsp_count(list, values, condition) +``` + + +Return `true` if the number of occurrences of the values in `values` in `list` satisfies the given condition, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `values::Vector{Int}`: list of values to check. + +- `condition`: condition to satisfy. + + +**Variants** +- `:count`: Constraint ensuring that the number of occurrences of the values in `vals` in `x` satisfies the given condition. + + +```julia +concept(:count, x; vals, op, val) +concept(:count)(x; vals, op, val) +``` + +- `:at_least`: Constraint ensuring that the number of occurrences of the values in `vals` in `x` is at least `val`. + + +```julia +concept(:at_least, x; vals, val) +concept(:at_least)(x; vals, val) +``` + +- `:at_most`: Constraint ensuring that the number of occurrences of the values in `vals` in `x` is at most `val`. + + +```julia +concept(:at_most, x; vals, val) +concept(:at_most)(x; vals, val) +``` + +- `:exactly`: Constraint ensuring that the number of occurrences of the values in `vals` in `x` is exactly `val`. + + +```julia +concept(:exactly, x; vals, val) +concept(:exactly)(x; vals, val) +``` + + +**Examples** + +```julia +c = concept(:count) + +c([2, 1, 4, 3]; vals=[1, 2, 3, 4], op=≥, val=2) +c([1, 2, 3, 4]; vals=[1, 2], op==, val=2) +c([2, 1, 4, 3]; vals=[1, 2], op=≤, val=1) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/count.jl#L17-L57) + +
+
+
+# Constraints.xcsp_nvaluesFunction. + + + + +```julia +xcsp_nvalues(list, condition, except) +``` + + +Return `true` if the number of distinct values in `list` satisfies the given condition, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `condition`: condition to satisfy. + +- `except::Union{Nothing, Vector{Int}}`: list of values to exclude. Default is `nothing`. + + +**Variants** +- `:nvalues`: The nValues constraint specifies that the number of distinct values in the list of variables x is equal to a given value. The constraint is defined by the following expression: nValues(x, op, val) where x is a list of variables, op is a comparison operator, and val is an integer value. + + +```julia +concept(:nvalues, x; op, val) +concept(:nvalues)(x; op, val) +``` + + +**Examples** + +```julia +c = concept(:nvalues) + +c([1, 2, 3, 4, 5]; op = ==, val = 5) +c([1, 2, 3, 4, 5]; op = ==, val = 2) +c([1, 2, 3, 4, 3]; op = <=, val = 5) +c([1, 2, 3, 4, 3]; op = <=, val = 3) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/n_values.jl#L7-L33) + +
+
+
+# Constraints.xcsp_cardinalityFunction. + + + + +```julia +xcsp_cardinality(list, values, occurs, closed) +``` + + +Return `true` if the number of occurrences of the values in `values` in `list` satisfies the given condition, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `values::Vector{Int}`: list of values to check. + +- `occurs::Vector{Int}`: list of occurrences to check. + +- `closed::Bool`: whether the constraint is closed or not. + + +**Variants** +- `:cardinality`: The cardinality constraint, also known as the global cardinality constraint (GCC), is a constraint in constraint programming that restricts the number of times a value can appear in a set of variables. + + +```julia +concept(:cardinality, x; bool=false, vals) +concept(:cardinality)(x; bool=false, vals) +``` + +- `:cardinality_closed`: The closed cardinality constraint, also known as the global cardinality constraint (GCC), is a constraint in constraint programming that restricts the number of times a value can appear in a set of variables. It is closed, meaning that all values in the domain of the variables must be considered. + + +```julia +concept(:cardinality_closed, x; vals) +concept(:cardinality_closed)(x; vals) +``` + +- `:cardinality_open`: The open cardinality constraint, also known as the global cardinality constraint (GCC), is a constraint in constraint programming that restricts the number of times a value can appear in a set of variables. It is open, meaning that only the values in the list of values must be considered. + + +```julia +concept(:cardinality_open, x; vals) +concept(:cardinality_open)(x; vals) +``` + + +**Examples** + +```julia +c = concept(:cardinality) + +c([2, 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) +c([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3], bool=true) +c([2, 5, 10, 10]; vals=[2 1; 5 1; 10 2]) +c([2, 5, 10, 10]; vals=[2 0 1 42; 5 1 3 7; 10 2 3 -4]) +c([2, 5, 5, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) +c([2, 5, 10, 8]; vals=[2 1; 5 1; 10 2]) +c([5, 5, 5, 10]; vals=[2 0 1 42; 5 1 3 7; 10 2 3 -4]) + +cc = concept(:cardinality_closed) +cc([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) + +co = concept(:cardinality_open) +co([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/cardinality.jl#L14-L61) + +
+
diff --git a/previews/PR50/.documenter/constraints/elementary_constraints.md b/previews/PR50/.documenter/constraints/elementary_constraints.md new file mode 100644 index 0000000..76f13e7 --- /dev/null +++ b/previews/PR50/.documenter/constraints/elementary_constraints.md @@ -0,0 +1,50 @@ + +# Constraints.jl: Streamlining Constraint Definition and Integration in Julia {#Constraints.jl:-Streamlining-Constraint-Definition-and-Integration-in-Julia} + + + +### Elementary Constraints {#Elementary-Constraints} +
+# Constraints.xcsp_instantiationFunction. + + + + +```julia +xcsp_instantiation(; list, values) +``` + + +Return `true` if the instantiation constraint is satisfied, `false` otherwise. The instantiation constraint is a global constraint used in constraint programming that ensures that a list of variables takes on a specific set of values in a specific order. + +**Arguments** +- `list::AbstractVector`: list of values to check. + +- `values::AbstractVector`: list of values to check against. + + +**Variants** +- `:instantiation`: The instantiation constraint is a global constraint used in constraint programming that ensures that a list of variables takes on a specific set of values in a specific order. + + +```julia +concept(:instantiation, x; pair_vars) +concept(:instantiation)(x; pair_vars) +``` + + +**Examples** + +```julia +c = concept(:instantiation) + +c([1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 5]) +c([1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 6]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/instantiation.jl#L5-L28) + +
+
diff --git a/previews/PR50/.documenter/constraints/generic_constraints.md b/previews/PR50/.documenter/constraints/generic_constraints.md new file mode 100644 index 0000000..a63589e --- /dev/null +++ b/previews/PR50/.documenter/constraints/generic_constraints.md @@ -0,0 +1,244 @@ + +# Generic Constraints {#Generic-Constraints} + + + +In the [XCSP³-core](https://arxiv.org/abs/2009.00514) standard, generic constraints are categorized into two main types: _intention_ and _extension_ constraints. + +## Intention Constraints {#Intention-Constraints} + +These are constraints that are defined by a logical expression or a function. They are called intentional because they are defined by the property they satisfy. For example, a constraint that specifies that a variable $x$ must be less than a variable $y$ could be defined intentionally as $x < y$. + +Note that the _intention_ constraint is not directly available through the JC-API in Constraints.jl. It is designed as such since defining a constraint through a _predicate_ is the natural way. + +We provide a straightforward example through the `:dist_different` constraint on how to define and add such a constraint in the `USUAL_CONSTRAINTS` collection. + +Higher level modeling language such as `JuMP` should provide a `Intention` interface. + +### Defining an intention constraint in JC-API {#Defining-an-intention-constraint-in-JC-API} + +We use the `dist_different` constraint to illustrate how to define an intention constraint in _Constraints.jl_. The `dist_different` constraint ensures that the distances between marks $x$ on a ruler are unique. + +$$|x[1] - x[2]| \ne |x[3] - x[4]|$$ + +The constraint is then added to the usual constraints collection. + +```julia +const description_dist_different = """ +Ensures that the distances between marks on the ruler are unique. +""" + +# Define the predicate +predicate_dist_different(x) = abs(x[1] - x[2]) ≠ abs(x[3] - x[4]) + +# Add it to usual constraints +@usual concept_dist_different(x) = xcsp_intension( + list = x, + predicate = predicate_dist_different +) +``` + + +Please check the section dedicated to the Golomb Ruler problem to see a use for this constraint. <!– TODO: Golomb Ruler –> + +### APIs + +Note that the _intension_ constraint is not directly available through the JC-API in Constraints.jl. It is designed as such since defining a constraint through a _predicate_ is the natural way. + +We provide here a usage example for the `:dist_different` constraint, previously added to the `USUAL_CONSTRAINTS` collection. + +Higher level modeling language such as `JuMP` should provide an `Intension` interface. + +::: code-group + +```julia [JC-API] +concept(:dist_different, x) +concept(:dist_different)(x) +``` + + +```julia [XCSP] +# Defines the DistDifferent constraint +c = x -> xcsp_intension( + list = x, + predicate = y -> abs(y[1] - y[2]) ≠ abs(y[3] - y[4]) +) + +c([1, 2, 3, 3]) # true +c([1, 2, 3, 4]) # false +``` + + +```julia [JuMP] +# TODO: How to handle intention in JuMP/MOI +``` + + +```julia [MOI] +# TODO: How to handle intention in JuMP/MOI +``` + + +::: + +### Test for DocumenterVitePress Issue {#Test-for-DocumenterVitePress-Issue} + +```julia +c = concept(:dist_different) +c([1, 2, 3, 3]) && !c([1, 2, 3, 4]) +``` + + +``` +true +``` + + +```julia +c = concept(:dist_different) +c([1, 2, 3, 3]) && !c([1, 2, 3, 4]) +``` + + +``` +true +``` + + +### Specific documentation {#Specific-documentation} +
+# Constraints.xcsp_intensionFunction. + + + + +```julia +xcsp_intension(list, predicate) +``` + + +An intensional constraint is usually defined from a `predicate` over `list`. As such it encompass any generic constraint. + +**Arguments** +- `list::Vector{Int}`: A list of variables + +- `predicate::Function`: A predicate over `list` + + +**Variants** +- `:dist_different`: A constraint ensuring that the distances between marks on the ruler are unique. Specifically, it checks that the distance between `x[1]` and `x[2]`, and the distance between `x[3]` and `x[4]`, are different. This constraint is fundamental in ensuring the validity of a Golomb ruler, where no two pairs of marks should have the same distance between them. + + +```julia +concept(:dist_different, x) +concept(:dist_different)(x) +``` + + +**Examples** + +```@example debug2 +2 + 2 +``` + + +```@example debug1 +2 + 2 +``` + + +```@example intention1 +using Constraints # hide +c = concept(:dist_different) +c([1, 2, 3, 3]) && !c([1, 2, 3, 4]) +``` + + +```@example intention2 +using Constraints # hide +c = concept(:dist_different) +c([1, 2, 3, 3]) && !c([1, 2, 3, 4]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/intention.jl#L9-L47) + +
+
+ +## Extension Constraints {#Extension-Constraints} + +These are constraints that are defined by explicitly listing all the tuples of values that satisfy the constraint. They are called extensional because they are defined by the set of values they allow. For example, a binary constraint that specifies that a variable X must be either 1 or 2 and a variable Y must be either 3 or 4 could be defined extensionally by the set of tuples {(1,3), (1,4), (2,3), (2,4)}. + +These two types of constraints provide a flexible way to define complex relationships between variables in constraint programming. + +### [XCSP](https://arxiv.org/abs/2009.00514) in Constraints.jl {#[XCSP](https://arxiv.org/abs/2009.00514)-in-Constraints.jl} +
+# Constraints.xcsp_extensionFunction. + + + + +```julia +xcsp_extension(; list, supports=nothing, conflicts=nothing) +``` + + +Global constraint enforcing that the tuple `x` matches a configuration within the supports set `pair_vars[1]` or does not match any configuration within the conflicts set `pair_vars[2]`. It embodies the logic: `x ∈ pair_vars[1] || x ∉ pair_vars[2]`, providing a comprehensive way to define valid (supported) and invalid (conflicted) tuples for constraint satisfaction problems. This constraint is versatile, allowing for the explicit delineation of both acceptable and unacceptable configurations. + +**Arguments** +- `list::Vector{Int}`: A list of variables + +- `supports::Vector{Vector{Int}}`: A set of supported tuples. Default to nothing. + +- `conflicts::Vector{Vector{Int}}`: A set of conflicted tuples. Default to nothing. + + +**Variants** +- `:extension`: Global constraint enforcing that the tuple `x` matches a configuration within the supports set `pair_vars[1]` or does not match any configuration within the conflicts set `pair_vars[2]`. It embodies the logic: `x ∈ pair_vars[1] || x ∉ pair_vars[2]`, providing a comprehensive way to define valid (supported) and invalid (conflicted) tuples for constraint satisfaction problems. This constraint is versatile, allowing for the explicit delineation of both acceptable and unacceptable configurations. + + +```julia +concept(:extension, x; pair_vars) +concept(:extension)(x; pair_vars) +``` + +- `:supports`: Global constraint ensuring that the tuple `x` matches a configuration listed within the support set `pair_vars`. This constraint is derived from the extension model, specifying that `x` must be one of the explicitly defined supported configurations: `x ∈ pair_vars`. It is utilized to directly declare the tuples that are valid and should be included in the solution space. + + +```julia +concept(:supports, x; pair_vars) +concept(:supports)(x; pair_vars) +``` + +- `:conflicts`: Global constraint ensuring that the tuple `x` does not match any configuration listed within the conflict set `pair_vars`. This constraint, originating from the extension model, stipulates that `x` must avoid all configurations defined as conflicts: `x ∉ pair_vars`. It is useful for specifying tuples that are explicitly forbidden and should be excluded from the solution space. + + +```julia +concept(:conflicts, x; pair_vars) +concept(:conflicts)(x; pair_vars) +``` + + +**Examples** + +```julia +c = concept(:extension) +c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) +c([1, 2, 3, 4, 5]; pair_vars=([[1, 2, 3, 4, 5]], [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]])) +c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) + +c = concept(:supports) +c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) + +c = concept(:conflicts) +c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/extension.jl#L20-L60) + +
+
diff --git a/previews/PR50/.documenter/constraints/graph_constraints.md b/previews/PR50/.documenter/constraints/graph_constraints.md new file mode 100644 index 0000000..76b1459 --- /dev/null +++ b/previews/PR50/.documenter/constraints/graph_constraints.md @@ -0,0 +1,52 @@ + +# Constraints.jl: Streamlining Constraint Definition and Integration in Julia {#Constraints.jl:-Streamlining-Constraint-Definition-and-Integration-in-Julia} + + + +### Constraints on Graphs {#Constraints-on-Graphs} +
+# Constraints.xcsp_circuitFunction. + + + + +```julia +xcsp_circuit(; list, size) +``` + + +Return `true` if the circuit constraint is satisfied, `false` otherwise. The circuit constraint is a global constraint used in constraint programming, often in routing problems. It ensures that the values of a list of variables form a circuit, i.e., a sequence where each value is the index of the next value in the sequence, and the sequence eventually loops back to the start. + +**Arguments** +- `list::AbstractVector`: list of values to check. + +- `size::Int`: size of the circuit. + + +**Variants** +- `:circuit`: The circuit constraint is a global constraint used in constraint programming, often in routing problems. It ensures that the values of a list of variables form a circuit, i.e., a sequence where each value is the index of the next value in the sequence, and the sequence eventually loops back to the start. + + +```julia +concept(:circuit, x; op, val) +concept(:circuit)(x; op, val) +``` + + +**Examples** + +```julia +c = concept(:circuit) + +c([1, 2, 3, 4]) +c([2, 3, 4, 1]) +c([2, 3, 1, 4]; op = ==, val = 3) +c([4, 3, 1, 3]; op = >, val = 0) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/circuit.jl#L5-L30) + +
+
diff --git a/previews/PR50/.documenter/constraints/intro.md b/previews/PR50/.documenter/constraints/intro.md new file mode 100644 index 0000000..57244b0 --- /dev/null +++ b/previews/PR50/.documenter/constraints/intro.md @@ -0,0 +1,4 @@ + +# Introduction to basics cosntraints related tools {#Introduction-to-basics-cosntraints-related-tools} + +About constraints. diff --git a/previews/PR50/.documenter/constraints/language_constraints.md b/previews/PR50/.documenter/constraints/language_constraints.md new file mode 100644 index 0000000..9206bc3 --- /dev/null +++ b/previews/PR50/.documenter/constraints/language_constraints.md @@ -0,0 +1,132 @@ + +# Constraints.jl: Streamlining Constraint Definition and Integration in Julia {#Constraints.jl:-Streamlining-Constraint-Definition-and-Integration-in-Julia} + + + +### Constraints defined from Languages {#Constraints-defined-from-Languages} +
+# Constraints.xcsp_regularFunction. + + + + +```julia +xcsp_regular(; list, automaton) + +Ensures that a sequence `x` (interpreted as a word) is accepted by the regular language represented by a given automaton. This constraint verifies the compliance of `x` with the language rules encoded within the `automaton` parameter, which must be an instance of `<:AbstractAutomaton`. +``` + + +**Arguments** +- `list::Vector{Int}`: A list of variables + +- `automaton<:AbstractAutomaton`: An automaton representing the regular language + + +**Variants** +- `:regular`: Ensures that a sequence `x` (interpreted as a word) is accepted by the regular language represented by a given automaton. This constraint verifies the compliance of `x` with the language rules encoded within the `automaton` parameter, which must be an instance of `<:AbstractAutomaton`. + + +```julia +concept(:regular, x; language) +concept(:regular)(x; language) +``` + + +**Examples** + +```julia +c = concept(:regular) + +states = Dict( + (:a, 0) => :a, + (:a, 1) => :b, + (:b, 1) => :c, + (:c, 0) => :d, + (:d, 0) => :d, + (:d, 1) => :e, + (:e, 0) => :e, +) +start = :a +finish = :e + +a = Automaton(states, start, finish) + +c([0,0,1,1,0,0,1,0,0]; language = a) +c([1,1,1,0,1]; language = a) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/regular.jl#L5-L42) + +
+
+
+# Constraints.xcsp_mddFunction. + + + + +```julia +xcsp_mdd(; list, diagram) +``` + + +Return a function that checks if the list of values `list` satisfies the MDD `diagram`. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `diagram::MDD`: MDD to check. + + +**Variants** +- `:mdd`: Multi-valued Decision Diagram (MDD) constraint. + The MDD constraint is a constraint that can be used to model a wide range of problems. It is a directed graph where each node is labeled with a value and each edge is labeled with a value. The constraint is satisfied if there is a path from the first node to the last node such that the sequence of edge labels is a valid sequence of the value labels. + + +```julia +concept(:mdd, x; language) +concept(:mdd)(x; language) +``` + + +**Examples** + +```julia +c = concept(:mdd) + +states = [ + Dict( # level x1 + (:r, 0) => :n1, + (:r, 1) => :n2, + (:r, 2) => :n3, + ), + Dict( # level x2 + (:n1, 2) => :n4, + (:n2, 2) => :n4, + (:n3, 0) => :n5, + ), + Dict( # level x3 + (:n4, 0) => :t, + (:n5, 0) => :t, + ), +] + +a = MDD(states) + +c([0,2,0]; language = a) +c([1,2,0]; language = a) +c([2,0,0]; language = a) +c([2,1,2]; language = a) +c([1,0,2]; language = a) +c([0,1,2]; language = a) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/mdd.jl#L9-L55) + +
+
diff --git a/previews/PR50/.documenter/constraints/packing_scheduling_constraints.md b/previews/PR50/.documenter/constraints/packing_scheduling_constraints.md new file mode 100644 index 0000000..abd9669 --- /dev/null +++ b/previews/PR50/.documenter/constraints/packing_scheduling_constraints.md @@ -0,0 +1,123 @@ + +# Constraints.jl: Streamlining Constraint Definition and Integration in Julia {#Constraints.jl:-Streamlining-Constraint-Definition-and-Integration-in-Julia} + + + +### Packing and Scheduling Constraints {#Packing-and-Scheduling-Constraints} +
+# Constraints.xcsp_cumulativeFunction. + + + + +```julia +xcsp_cumulative(; origins, lengths, heights, condition) +``` + + +Return `true` if the cumulative constraint is satisfied, `false` otherwise. The cumulative constraint is a global constraint used in constraint programming that is often used in scheduling problems. It ensures that for any point in time, the sum of the "heights" of tasks that are ongoing at that time does not exceed a certain limit. + +**Arguments** +- `origins::AbstractVector`: list of origins of the tasks. + +- `lengths::AbstractVector`: list of lengths of the tasks. + +- `heights::AbstractVector`: list of heights of the tasks. + +- `condition::Tuple`: condition to check. + + +**Variants** +- `:cumulative`: The cumulative constraint is a global constraint used in constraint programming that is often used in scheduling problems. It ensures that for any point in time, the sum of the "heights" of tasks that are ongoing at that time does not exceed a certain limit. + + +```julia +concept(:cumulative, x; pair_vars, op, val) +concept(:cumulative)(x; pair_vars, op, val) +``` + + +**Examples** + +```julia +c = concept(:cumulative) + +c([1, 2, 3, 4, 5]; val = 1) +c([1, 2, 2, 4, 5]; val = 1) +c([1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = ≤, val = 5) +c([1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = <, val = 5) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/cumulative.jl#L5-L32) + +
+
+
+# Constraints.xcsp_no_overlapFunction. + + + + +```julia +xcsp_no_overlap(; origins, lengths, zero_ignored) +``` + + +Return `true` if the no_overlap constraint is satisfied, `false` otherwise. The no_overlap constraint is a global constraint used in constraint programming, often in scheduling problems. It ensures that tasks do not overlap in time, i.e., for any two tasks, either the first task finishes before the second task starts, or the second task finishes before the first task starts. + +**Arguments** +- `origins::AbstractVector`: list of origins of the tasks. + +- `lengths::AbstractVector`: list of lengths of the tasks. + +- `zero_ignored::Bool`: whether to ignore zero-length tasks. + + +**Variants** +- `:no_overlap`: The no_overlap constraint is a global constraint used in constraint programming, often in scheduling problems. It ensures that tasks do not overlap in time, i.e., for any two tasks, either the first task finishes before the second task starts, or the second task finishes before the first task starts. + + +```julia +concept(:no_overlap, x; pair_vars, bool) +concept(:no_overlap)(x; pair_vars, bool) +``` + +- `:no_overlap_no_zero`: The no_overlap constraint is a global constraint used in constraint programming, often in scheduling problems. It ensures that tasks do not overlap in time, i.e., for any two tasks, either the first task finishes before the second task starts, or the second task finishes before the first task starts. This variant ignores zero-length tasks. + + +```julia +concept(:no_overlap_no_zero, x; pair_vars) +concept(:no_overlap_no_zero)(x; pair_vars) +``` + +- `:no_overlap_with_zero`: The no_overlap constraint is a global constraint used in constraint programming, often in scheduling problems. It ensures that tasks do not overlap in time, i.e., for any two tasks, either the first task finishes before the second task starts, or the second task finishes before the first task starts. This variant includes zero-length tasks. + + +```julia +concept(:no_overlap_with_zero, x; pair_vars) +concept(:no_overlap_with_zero)(x; pair_vars) +``` + + +**Examples** + +```julia +c = concept(:no_overlap) + +c([1, 2, 3, 4, 5]) +c([1, 2, 3, 4, 1]) +c([1, 2, 4, 6, 3]; pair_vars = [1, 1, 1, 1, 1]) +c([1, 2, 4, 6, 3]; pair_vars = [1, 1, 1, 3, 1]) +c([1, 2, 4, 6, 3]; pair_vars = [1, 1, 3, 1, 1]) +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) +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) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/no_overlap.jl#L13-L52) + +
+
diff --git a/previews/PR50/.documenter/cp/advanced.md b/previews/PR50/.documenter/cp/advanced.md new file mode 100644 index 0000000..8eae20c --- /dev/null +++ b/previews/PR50/.documenter/cp/advanced.md @@ -0,0 +1,10 @@ + +# Advanced Constraint Programming Techniques {#Advanced-Constraint-Programming-Techniques} + +## Global Constraints and Their Uses {#Global-Constraints-and-Their-Uses} +- Dive deeper into global constraints and how they simplify complex problems. + + +## Search Strategies and Optimization {#Search-Strategies-and-Optimization} +- Discuss various search strategies and their impact on solving CP problems. + diff --git a/previews/PR50/.documenter/cp/applications.md b/previews/PR50/.documenter/cp/applications.md new file mode 100644 index 0000000..21c001b --- /dev/null +++ b/previews/PR50/.documenter/cp/applications.md @@ -0,0 +1,10 @@ + +# Applying Optimization Methods {#Applying-Optimization-Methods} + +## Case Studies and Real-World Applications {#Case-Studies-and-Real-World-Applications} +- Showcase studies where CP and optimization have been successfully applied. + + +## From Theory to Practice {#From-Theory-to-Practice} +- Guide readers through the process of formulating and solving an optimization problem from a real-world scenario. + diff --git a/previews/PR50/.documenter/cp/contribution.md b/previews/PR50/.documenter/cp/contribution.md new file mode 100644 index 0000000..f11f508 --- /dev/null +++ b/previews/PR50/.documenter/cp/contribution.md @@ -0,0 +1,10 @@ + +# Community and Contribution {#Community-and-Contribution} + +## Joining the JuliaConstraint Community {#Joining-the-JuliaConstraint-Community} +- Encourage readers to join the community, highlighting how they can contribute and collaborate. + + +## Future Directions {#Future-Directions} +- Share the vision for JuliaConstraint and upcoming projects or areas of research. + diff --git a/previews/PR50/.documenter/cp/cp101.md b/previews/PR50/.documenter/cp/cp101.md new file mode 100644 index 0000000..a8f15da --- /dev/null +++ b/previews/PR50/.documenter/cp/cp101.md @@ -0,0 +1,14 @@ + +# Constraint Programming 101 {#Constraint-Programming-101} + +## What is Constraint Programming? {#What-is-Constraint-Programming?} +- Define CP and its significance in solving combinatorial problems. + + +## Basic Concepts and Terminology {#Basic-Concepts-and-Terminology} +- Introduce key concepts such as constraints, domains, and variables. + + +## How CP differs from other optimization techniques {#How-CP-differs-from-other-optimization-techniques} +- Contrast with other methods like linear programming and metaheuristics. + diff --git a/previews/PR50/.documenter/cp/ecosystem.md b/previews/PR50/.documenter/cp/ecosystem.md new file mode 100644 index 0000000..a0cb216 --- /dev/null +++ b/previews/PR50/.documenter/cp/ecosystem.md @@ -0,0 +1,10 @@ + +# Exploring JuliaConstraint Packages {#Exploring-JuliaConstraint-Packages} + +## Package Overviews {#Package-Overviews} +- Introduce each package within the JuliaConstraint organization, its purpose, and primary features. + + +# Installation and Getting Started Guides {#Installation-and-Getting-Started-Guides} +- Provide step-by-step instructions for installing and getting started with each package. + diff --git a/previews/PR50/.documenter/cp/getting_started.md b/previews/PR50/.documenter/cp/getting_started.md new file mode 100644 index 0000000..e713381 --- /dev/null +++ b/previews/PR50/.documenter/cp/getting_started.md @@ -0,0 +1,141 @@ + +# Getting Started with Julia for CP and Optimization {#Getting-Started-with-Julia-for-CP-and-Optimization} + +## Why Julia? {#Why-Julia?} +- Discuss the advantages of Julia for computational science and optimization, highlighting its performance and ease of use. + + +## Setting Up Your Julia Environment {#Setting-Up-Your-Julia-Environment} + +We encourage users to install Julia through `juliaup`, a version manager for the Julia language. Please look at the official Julia language download page for further information. Once installed, Julia can be used through various editors (`Visual Studio Code`), notebooks (`Pluto.jl`), or command-line (`REPL`). + +Although a part of the CP solvers available within the Julia ecosystem have their own interface, we encourage users to use the JuMP modeling language if possible. + +Julia Constraints host several solvers(' interfaces). Due to its flexibility in modeling and solving, we will use LocalSearchSolvers.jl through its JuMP interface CBLS.jl as the basic example. Note that depending on the targeted instances, available hardware, and expectations, it is not necessarily the best choice. + +All along the documentation, we will try to provide syntax examples for different setup. + +::: code-group + +```julia [LocalSearchSolvers] +using LocalSearchSolvers +``` + + +```julia [CBLS] +using JuMP, CBLS +``` + + +```julia [TODO] +# TODO: Add other solvers +``` + + +::: + +## Your First Julia CP Model {#Your-First-Julia-CP-Model} + +We will start with a classic puzzle game and some of its not that simple variants: the Sudoku. + +(From Wikipedia) In classic Sudoku, the objective is to fill a 9 × 9 grid with digits so that each column, each row, and each of the nine 3 × 3 subgrids that compose the grid (also called "boxes", "blocks", or "regions") contains all of the digits from 1 to 9. The puzzle setter provides a partially completed grid, which for a well-posed puzzle has a single solution. + +Constraint Programming follows the _model-and-solve_ approach. We first need to model our Sudoku problem. + +::: code-group + +```julia [CBLS] +m = JuMP.Model(CBLS.Optimizer) +``` + + +```julia [TODO] +# TODO: Add other solvers +``` + + +::: + +But what are the basis of CP models? It is quite simple: +1. A collection $X = X_1, \cdots, X_n$ of variables with each an associated domain. + + +::: code-group + +```julia [CBLS] +@variable(m, 1 ≤ X[1:9, 1:9] ≤ 9, Int) +``` + + +```julia [TODO] +# TODO: Add other solvers +``` + + +::: +1. A collection of predicates (called constraints) $C = C_1, \cdots, C_n$ over (subsets of) $X$. + + +When modeling problems as CP, one might define and use their own predicates. However, a large collection of already defined constraints exists. One, if not the most, iconic global constraint is called AllDifferent. It ensures that all variables take distinct values. + +Sudoku puzzles can be defined using only this one constraint applied to different subsets of variables. + +::: code-group + +```julia [CBLS] +for i in 1:9 + @constraint(m, X[i,:] in AllDifferent()) # rows + @constraint(m, X[:,i] in AllDifferent()) # columns +end +``` + + +```julia [TODO] +# TODO: Add other solvers +``` + + +::: + +The last series of AllDifferent constraint is less straight forward. We need to ensure that each 3 × 3 subgrid (block) is filled with distinct values. + +::: code-group + +```julia [CBLS] +for i in 0:2, j in 0:2 # blocks + @constraint( + m, + vec(X[(3i+1):(3(i+1)), (3j+1):(3(j+1))]) in AllDifferent(), + ) +end +``` + + +```julia [TODO] +# TODO: Add other solvers +``` + + +::: + +We can now simply run our solver to look for a feasible solution. + +::: code-group + +```julia [CBLS] +optimize!(m) +``` + + +::: + +Note that this is heuristic solver, we might not get a feasible solution! Let's check it out. The value function print the value of a JuMP variable. We can cast it over a collection with the `value.` syntax. + +::: code-group + +```julia [CBLS] +value.(X) +``` + + +::: diff --git a/previews/PR50/.documenter/cp/intro.md b/previews/PR50/.documenter/cp/intro.md new file mode 100644 index 0000000..87348e1 --- /dev/null +++ b/previews/PR50/.documenter/cp/intro.md @@ -0,0 +1,4 @@ + +# Welcome to Julia Constraints {#Welcome-to-Julia-Constraints} + +An introductory post/chapter that provides an overview of the JuliaConstraint organization, its mission, and what readers can expect to learn from the content. Highlight the importance of Constraint Programming (CP) and optimization in solving real-world problems. diff --git a/previews/PR50/.documenter/cp/models.md b/previews/PR50/.documenter/cp/models.md new file mode 100644 index 0000000..5a5a707 --- /dev/null +++ b/previews/PR50/.documenter/cp/models.md @@ -0,0 +1,10 @@ + +# Building and Analyzing Models {#Building-and-Analyzing-Models} + +## Modeling Best Practices {#Modeling-Best-Practices} +- Share best practices and tips for building efficient CP and optimization models. + + +## Performance Analysis and Improvement {#Performance-Analysis-and-Improvement} +- Teach how to analyze and improve the performance of models. + diff --git a/previews/PR50/.documenter/cp/opt.md b/previews/PR50/.documenter/cp/opt.md new file mode 100644 index 0000000..5ad850c --- /dev/null +++ b/previews/PR50/.documenter/cp/opt.md @@ -0,0 +1,14 @@ + +# Dive into Optimization {#Dive-into-Optimization} + +## Understanding Optimization {#Understanding-Optimization} +- Explanation of optimization, types of optimization problems (e.g., linear, nonlinear, integer programming). + + +## Metaheuristics Overview {#Metaheuristics-Overview} +- Introduce concepts like Genetic Algorithms, Simulated Annealing, and Tabu Search. + + +## Mathematical Programming Basics {#Mathematical-Programming-Basics} +- Cover the fundamentals of mathematical programming and its role in optimization. + diff --git a/previews/PR50/.documenter/cp/tuto_xp.md b/previews/PR50/.documenter/cp/tuto_xp.md new file mode 100644 index 0000000..1a1f449 --- /dev/null +++ b/previews/PR50/.documenter/cp/tuto_xp.md @@ -0,0 +1,10 @@ + +# Tutorials and Experiments {#Tutorials-and-Experiments} + +## Hands-On Tutorials {#Hands-On-Tutorials} +- Provide step-by-step tutorials covering various topics and complexity levels. + + +## Experimental Analysis {#Experimental-Analysis} +- Discuss the importance of experimental analysis in CP and how to conduct meaningful experiments. + diff --git a/previews/PR50/.documenter/full_api.md b/previews/PR50/.documenter/full_api.md new file mode 100644 index 0000000..fdace88 --- /dev/null +++ b/previews/PR50/.documenter/full_api.md @@ -0,0 +1,4441 @@ + +# Full API {#Full-API} +
+# ConstraintCommons.USUAL_CONSTRAINT_PARAMETERSConstant. + + + + +```julia +const USUAL_CONSTRAINT_PARAMETERS +``` + + +List of usual constraints parameters (based on XCSP3-core constraints). + +```julia +const USUAL_CONSTRAINT_PARAMETERS = [ + :bool, + :dim, + :id, + :language, + :op, + :pair_vars, + :val, + :vals, +] +``` + + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/parameters.jl#L1-L17) + +
+
+
+# ConstraintCommons.AbstractAutomatonType. + + + + +```julia +AbstractAutomaton +``` + + +An abstract interface for automata used in Julia Constraints packages. Requirements: +- `accept(a<:AbstractAutomaton, word)`: return `true` if `a` accepts `word`. + + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L1-L6) + +
+
+
+# ConstraintCommons.AbstractMultivaluedDecisionDiagramType. + + + + +```julia +AbstractMultivaluedDecisionDiagram +``` + + +An abstract interface for Multivalued Decision Diagrams (MDD) used in Julia Constraints packages. Requirements: +- `accept(a<:AbstractMultivaluedDecisionDiagram, word)`: return `true` if `a` accepts `word`. + + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/diagrams.jl#L1-L6) + +
+
+
+# ConstraintCommons.AutomatonType. + + + + +```julia +Automaton{S, T, F <: Union{S, Vector{S}, Set{S}}} <: AbstractAutomaton +``` + + +A minimal implementation of a deterministic automaton structure. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L9-L13) + +
+
+
+# ConstraintCommons.MDDType. + + + + +```julia +MDD{S,T} <: AbstractMultivaluedDecisionDiagram +``` + + +A minimal implementation of a multivalued decision diagram structure. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/diagrams.jl#L9-L13) + +
+
+
+# ConstraintCommons.acceptMethod. + + + + +```julia +accept(a::Union{Automaton, MDD}, w) +``` + + +Return `true` if `a` accepts the word `w` and `false` otherwise. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L29-L33) + +
+
+
+# ConstraintCommons.at_endMethod. + + + + +```julia +at_end(a::Automaton, s) +``` + + +Internal method used by `accept` with `Automaton`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L20-L24) + +
+
+
+# ConstraintCommons.consinMethod. + + + + +```julia +Base.in(::Any, ::Nothing) +``` + + +Extends `Base.in` (or `∈`) when the set is `nothing`. Returns `false`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/nothing.jl#L1-L5) + +
+
+
+# ConstraintCommons.extract_parametersMethod. + + + + +```julia +extract_parameters(m::Union{Method, Function}; parameters) +``` + + +Extracts the intersection between the `kargs` of `m` and `parameters` (defaults to `USUAL_CONSTRAINT_PARAMETERS`). + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/parameters.jl#L21-L25) + +
+
+
+# ConstraintCommons.incsert!Function. + + + + +```julia +incsert!(d::Union{AbstractDict, AbstractDictionary}, ind, val = 1) +``` + + +Increase or insert a counter in a dictionary-based collection. The counter insertion defaults to `val = 1`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/dictionaries.jl#L2-L6) + +
+
+
+# ConstraintCommons.oversampleMethod. + + + + +```julia +oversample(X, f) +``` + + +Oversample elements of `X` until the boolean function `f` has as many `true` and `false` configurations. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/sampling.jl#L1-L5) + +
+
+
+# ConstraintCommons.symconFunction. + + + + +```julia +Base.:*(s1::Symbol, s2::Symbol, connector::AbstractString="_") +``` + + +Extends `*` to `Symbol`s multiplication by connecting the symbols by an `_`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/symbols.jl#L1-L5) + +
+
+
+# ConstraintCommons.δ_extremaMethod. + + + + +```julia +δ_extrema(X...) +``` + + +Compute both the difference between the maximum and the minimum of over all the collections of `X`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/extrema.jl#L1-L4) + +
+
+
+# ConstraintDomains.AbstractDomainType. + + + + +```julia +AbstractDomain +``` + + +An abstract super type for any domain type. A domain type `D <: AbstractDomain` must implement the following methods to properly interface `AbstractDomain`. +- `Base.∈(val, ::D)` + +- `Base.rand(::D)` + +- `Base.length(::D)` that is the number of elements in a discrete domain, and the distance between bounds or similar for a continuous domain + + +Additionally, if the domain is used in a dynamic context, it can extend +- `add!(::D, args)` + +- `delete!(::D, args)` + + +where `args` depends on `D`'s structure + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L1-L11) + +
+
+
+# ConstraintDomains.BoolParameterDomainType. + + + + +```julia +BoolParameterDomain <: AbstractDomain +``` + + +A domain to store boolean values. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L1-L5) + +
+
+
+# ConstraintDomains.ContinuousDomainType. + + + + +```julia +ContinuousDomain{T <: Real} <: AbstractDomain +``` + + +An abstract supertype for all continuous domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L1-L4) + +
+
+
+# ConstraintDomains.DimParameterDomainType. + + + + +```julia +DimParameterDomain <: AbstractDomain +``` + + +A domain to store dimensions. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L10-L14) + +
+
+
+# ConstraintDomains.DiscreteDomainType. + + + + +```julia +DiscreteDomain{T <: Number} <: AbstractDomain +``` + + +An abstract supertype for discrete domains (set, range). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L1-L4) + +
+
+
+# ConstraintDomains.EmptyDomainType. + + + + +```julia +EmptyDomain +``` + + +A struct to handle yet to be defined domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L14-L17) + +
+
+
+# ConstraintDomains.ExploreSettingsMethod. + + + + +```julia +ExploreSettings( + domains; + complete_search_limit = 10^6, + max_samplings = sum(domain_size, domains), + search = :flexible, + solutions_limit = floor(Int, sqrt(max_samplings)), +) +``` + + +Settings for the exploration of a search space composed by a collection of domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/explore.jl#L8-L18) + +
+
+
+# ConstraintDomains.FakeAutomatonType. + + + + +```julia +FakeAutomaton{T} <: ConstraintCommons.AbstractAutomaton +``` + + +A structure to generate pseudo automaton enough for parameter exploration. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L32-L36) + +
+
+
+# ConstraintDomains.IdParameterDomainType. + + + + +```julia +IdParameterDomain <: AbstractDomain +``` + + +A domain to store ids. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L21-L25) + +
+
+
+# ConstraintDomains.IntervalsType. + + + + +```julia +Intervals{T <: Real} <: ContinuousDomain{T} +``` + + +An encapsuler to store a vector of `PatternFolds.Interval`. Dynamic changes to `Intervals` are not handled yet. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L7-L10) + +
+
+
+# ConstraintDomains.LanguageParameterDomainType. + + + + +```julia +LanguageParameterDomain <: AbstractDomain +``` + + +A domain to store languages. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L62-L66) + +
+
+
+# ConstraintDomains.OpParameterDomainType. + + + + +```julia +OpParameterDomain{T} <: AbstractDomain +``` + + +A domain to store operators. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L75-L79) + +
+
+
+# ConstraintDomains.PairVarsParameterDomainType. + + + + +```julia +PairVarsParameterDomain{T} <: AbstractDomain +``` + + +A domain to store values paired with variables. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L86-L90) + +
+
+
+# ConstraintDomains.RangeDomainType. + + + + +```julia +RangeDomain +``` + + +A discrete domain defined by a `range <: AbstractRange{Real}`. As ranges are immutable in Julia, changes in `RangeDomain` must use `set_domain!`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L16-L19) + +
+
+
+# ConstraintDomains.SetDomainType. + + + + +```julia +SetDomain{T <: Number} <: DiscreteDomain{T} +``` + + +Domain that stores discrete values as a set of (unordered) points. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L7-L10) + +
+
+
+# ConstraintDomains.ValParameterDomainType. + + + + +```julia +ValParameterDomain{T} <: AbstractDomain +``` + + +A domain to store one value. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L99-L103) + +
+
+
+# ConstraintDomains.ValsParameterDomainType. + + + + +```julia +ValsParameterDomain{T} <: AbstractDomain +``` + + +A domain to store values. It is used to generate random parameters. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L110-L114) + +
+
+
+# Base.convertMethod. + + + + +```julia +Base.convert(::Type{Union{Intervals, RangeDomain}}, d::Union{Intervals, RangeDomain}) +``` + + +Extends `Base.convert` for domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/general.jl#L9-L13) + +
+
+
+# Base.delete!Method. + + + + +```julia +Base.delete!(d::SetDomain, value)(d::SetDomain, value) +``` + + +Delete `value` from the list of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L76-L79) + +
+
+
+# Base.eltypeMethod. + + + + +```julia +Base.eltype(::AbstractDomain) +``` + + +Extend `eltype` for domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/general.jl#L1-L5) + +
+
+
+# Base.inMethod. + + + + +```julia +Base.in(x, itv::Intervals) +``` + + +Return `true` if `x ∈ I` for any 'I ∈ itv`, false otherwise.`x ∈ I` is equivalent to +- `a < x < b` if `I = (a, b)` + +- `a < x ≤ b` if `I = (a, b]` + +- `a ≤ x < b` if `I = [a, b)` + +- `a ≤ x ≤ b` if `I = [a, b]` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L51-L58) + +
+
+
+# Base.inMethod. + + + + +```julia +Base.in(value, d <: AbstractDomain) +``` + + +Fallback method for `value ∈ d` that returns `false`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L28-L31) + +
+
+
+# Base.inMethod. + + + + +```julia +Base.in(value, d::D) where D <: DiscreteDomain +``` + + +Return `true` if `value` is a point of `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L58-L61) + +
+
+
+# Base.isemptyMethod. + + + + +```julia +Base.isempty(d <: AbstractDomain) +``` + + +Fallback method for `isempty(d)` that return `length(d) == 0` which default to `0`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L40-L43) + +
+
+
+# Base.lengthMethod. + + + + +```julia +Base.length(itv::Intervals) +``` + + +Return the sum of the length of each interval in `itv`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L26-L29) + +
+
+
+# Base.lengthMethod. + + + + +```julia +Base.rand(d <: AbstractDomain) +``` + + +Fallback method for `length(d)` that return `0`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L34-L37) + +
+
+
+# Base.lengthMethod. + + + + +```julia +Base.length(d::D) where D <: DiscreteDomain +``` + + +Return the number of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L46-L49) + +
+
+
+# Base.randMethod. + + + + +```julia +Base.rand(d::Union{Vector{D},Set{D}, D}) where {D<:AbstractDomain} +``` + + +Extends `Base.rand` to (a collection of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L72-L76) + +
+
+
+# Base.randMethod. + + + + +```julia +Base.rand(fa::FakeAutomaton) +``` + + +Extends `Base.rand`. Currently simply returns `fa`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L135-L139) + +
+
+
+# Base.randMethod. + + + + +```julia +Base.rand(itv::Intervals) +Base.rand(itv::Intervals, i) +``` + + +Return a random value from `itv`, specifically from the `i`th interval if `i` is specified. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L32-L36) + +
+
+
+# Base.randMethod. + + + + +```julia +Base.rand(d::D) where D <: DiscreteDomain +``` + + +Draw randomly a point in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L52-L55) + +
+
+
+# Base.stringMethod. + + + + +```julia +Base.string(D::Vector{<:AbstractDomain}) +Base.string(d<:AbstractDomain) +``` + + +Extends the `string` method to (a vector of) domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L87-L92) + +
+
+
+# ConstraintCommons.acceptMethod. + + + + +```julia +ConstraintCommons.accept(fa::FakeAutomaton, word) +``` + + +Implement the `accept` methods for `FakeAutomaton`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L41-L45) + +
+
+
+# ConstraintDomains.ArbitraryDomainMethod. + + + + +```julia +ArbitraryDomain{T} <: DiscreteDomain{T} +``` + + +A domain type that stores arbitrary values, possibly non numeric, of type `T`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L24-L28) + +
+
+
+# ConstraintDomains._exploreMethod. + + + + +```julia +_explore(args...) +``` + + +Internals of the `explore` function. Behavior is automatically adjusted on the kind of exploration: `:flexible`, `:complete`, `:partial`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/explore.jl#L29-L33) + +
+
+
+# ConstraintDomains.add!Method. + + + + +```julia +add!(d::SetDomain, value) +``` + + +Add `value` to the list of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L70-L73) + +
+
+
+# ConstraintDomains.domainMethod. + + + + +```julia +domain(values) +domain(range::R) where {T <: Real, R <: AbstractRange{T}} +``` + + +Construct either a `SetDomain` or a `RangeDomain``. + +```julia +d1 = domain(1:5) +d2 = domain([53.69, 89.2, 0.12]) +d3 = domain([2//3, 89//123]) +d4 = domain(4.3) +d5 = domain(1,42,86.9) +``` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L31-L42) + +
+
+
+# ConstraintDomains.domainMethod. + + + + +```julia +domain() +``` + + +Construct an `EmptyDomain`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L20-L23) + +
+
+
+# ConstraintDomains.domainMethod. + + + + +```julia +domain(a::Tuple{T, Bool}, b::Tuple{T, Bool}) where {T <: Real} +domain(intervals::Vector{Tuple{Tuple{T, Bool},Tuple{T, Bool}}}) where {T <: Real} +``` + + +Construct a domain of continuous interval(s). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L15-L19) + +
+
+
+# ConstraintDomains.domain_sizeMethod. + + + + +```julia +domain_size(itv::Intervals) +``` + + +Return the difference between the highest and lowest values in `itv`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L61-L64) + +
+
+
+# ConstraintDomains.domain_sizeMethod. + + + + +```julia +domain_size(d <: AbstractDomain) +``` + + +Fallback method for `domain_size(d)` that return `length(d)`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L46-L49) + +
+
+
+# ConstraintDomains.domain_sizeMethod. + + + + +```julia +domain_size(d::D) where D <: DiscreteDomain +``` + + +Return the maximum distance between two points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L64-L67) + +
+
+
+# ConstraintDomains.exploreMethod. + + + + +```julia +explore(domains, concept, param = nothing; search_limit = 1000, solutions_limit = 100) +``` + + +Search (a part of) a search space and returns a pair of vector of configurations: `(solutions, non_solutions)`. If the search space size is over `search_limit`, then both `solutions` and `non_solutions` are limited to `solutions_limit`. + +Beware that if the density of the solutions in the search space is low, `solutions_limit` needs to be reduced. This process will be automatic in the future (simple reinforcement learning). + +**Arguments:** +- `domains`: a collection of domains + +- `concept`: the concept of the targeted constraint + +- `param`: an optional parameter of the constraint + +- `sol_number`: the required number of solutions (half of the number of configurations), default to `100` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/explore.jl#L66-L78) + +
+
+
+# ConstraintDomains.fake_automatonMethod. + + + + +```julia +fake_automaton(d) +``` + + +Construct a `FakeAutomaton`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L48-L52) + +
+
+
+# ConstraintDomains.generate_parametersMethod. + + + + +```julia +generate_parameters(d<:AbstractDomain, param) +``` + + +Generates random parameters based on the domain `d` and the kind of parameters `param`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L128-L132) + +
+
+
+# ConstraintDomains.get_domainMethod. + + + + +```julia +get_domain(::AbstractDomain) +``` + + +Access the internal structure of any domain type. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L52-L55) + +
+
+
+# ConstraintDomains.intersect_domains!Method. + + + + +```julia +intersect_domains!(is, i, new_itvls) +``` + + +Compute the intersections of a domain with an interval and store the results in `new_itvls`. + +**Arguments** +- `is::IS`: a collection of intervals. + +- `i::I`: an interval. + +- `new_itvls::Vector{I}`: a vector to store the results. + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L89-L98) + +
+
+
+# ConstraintDomains.intersect_domainsMethod. + + + + +```julia +intersect_domains(d₁, d₂) +``` + + +Compute the intersections of two domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L72-L76) + +
+
+
+# ConstraintDomains.merge_domainsMethod. + + + + +```julia +merge_domains(d₁::AbstractDomain, d₂::AbstractDomain) +``` + + +Merge two domains of same nature (discrete/contiuous). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L83-L87) + +
+
+
+# ConstraintDomains.sizeMethod. + + + + +```julia +Base.size(i::I) where {I <: Interval} +``` + + +Defines the size of an interval as its `span`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L118-L122) + +
+
+
+# ConstraintDomains.to_domainsMethod. + + + + +```julia +to_domains(args...) +``` + + +Convert various arguments into valid domains format. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L58-L62) + +
+
+
+# Constraints.USUAL_CONSTRAINTSConstant. + + + + +```julia +USUAL_CONSTRAINTS::Dict +``` + + +Dictionary that contains all the usual constraints defined in Constraint.jl. It is based on XCSP3-core specifications available at https://arxiv.org/abs/2009.00514 + +Adding a new constraint is as simple as defining a new function with the same name as the constraint and using the `@usual` macro to define it. The macro will take care of adding the new constraint to the `USUAL_CONSTRAINTS` dictionary. + +**Example** + +```julia +@usual concept_all_different(x; vals=nothing) = xcsp_all_different(list=x, except=vals) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L1-L11) + +
+
+
+# Constraints.USUAL_SYMMETRIESConstant. + + + + +```julia +USUAL_SYMMETRIES +``` + + +A Dictionary that contains the function to apply for each symmetry to avoid searching a whole space. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L1-L4) + +
+
+
+# Constraints.ConstraintType. + + + + +```julia +Constraint +``` + + +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 assignments. Return `0.0` if the constraint is satisfied, and a strictly positive real otherwise. + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L7-L12) + +
+
+
+# ConstraintCommons.extract_parametersFunction. + + + + +```julia +extract_parameters(s::Symbol, constraints_dict=USUAL_CONSTRAINTS; parameters=ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS) +``` + + +Return the parameters of the constraint `s` in `constraints_dict`. + +**Arguments** +- `s::Symbol`: the constraint name. + +- `constraints_dict::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + +- `parameters::Vector{Symbol}`: vector of parameters. Default is `ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS`. + + +**Example** + +```julia +extract_parameters(:all_different) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L44-L58) + +
+
+
+# Constraints.argsMethod. + + + + +```julia +args(c::Constraint) +``` + + +Return the expected length restriction of the arguments in a constraint `c`. The value `nothing` indicates that any strictly positive number of value is accepted. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L62-L65) + +
+
+
+# Constraints.conceptMethod. + + + + +```julia +concept(c::Constraint) +``` + + +Return the concept (function) of constraint `c`. concept(c::Constraint, x...; param = nothing) Apply the concept of `c` to values `x` and optionally `param`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L40-L45) + +
+
+
+# Constraints.conceptMethod. + + + + +```julia +concept(s::Symbol, args...; kargs...) +``` + + +Return the concept of the constraint `s` applied to `args` and `kargs`. This is a shortcut for `concept(USUAL_CONSTRAINTS[s])(args...; kargs...)`. + +**Arguments** +- `s::Symbol`: the constraint name. + +- `args...`: the arguments to apply the concept to. + +- `kargs...`: the keyword arguments to apply the concept to. + + +**Example** + +```julia +concept(:all_different, [1, 2, 3]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L221-L235) + +
+
+
+# Constraints.concept_vs_errorMethod. + + + + +```julia +concept_vs_error(c, e, args...; kargs...) +``` + + +Compare the results of a concept function and an error function for the same inputs. It is mainly used for testing purposes. + +**Arguments** +- `c`: The concept function. + +- `e`: The error function. + +- `args...`: Positional arguments to be passed to both the concept and error functions. + +- `kargs...`: Keyword arguments to be passed to both the concept and error functions. + + +**Returns** +- Boolean: Returns true if the result of the concept function is not equal to whether the result of the error function is greater than 0.0. Otherwise, it returns false. + + +**Examples** + +```julia +concept_vs_error(all_different, make_error(:all_different), [1, 2, 3]) # Returns false +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L111-L129) + +
+
+
+# Constraints.constraints_descriptionsFunction. + + + + +```julia +constraints_descriptions(C=USUAL_CONSTRAINTS) +``` + + +Return a pretty table with the descriptions of the constraints in `C`. + +**Arguments** +- `C::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + + +**Example** + +```julia +constraints_descriptions() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L180-L192) + +
+
+
+# Constraints.constraints_parametersFunction. + + + + +```julia +constraints_parameters(C=USUAL_CONSTRAINTS) +``` + + +Return a pretty table with the parameters of the constraints in `C`. + +**Arguments** +- `C::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + + +**Example** + +```julia +constraints_parameters() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L127-L139) + +
+
+
+# Constraints.describeFunction. + + + + +```julia +describe(constraints::Dict{Symbol,Constraint}=USUAL_CONSTRAINTS; width=150) +``` + + +Return a pretty table with the description of the constraints in `constraints`. + +**Arguments** +- `constraints::Dict{Symbol,Constraint}`: dictionary of constraints to describe. Default is `USUAL_CONSTRAINTS`. + +- `width::Int`: width of the table. + + +**Example** + +```julia +describe() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L14-L27) + +
+
+
+# Constraints.error_fMethod. + + + + +```julia +error_f(c::Constraint) +``` + + +Return the error function of constraint `c`. error_f(c::Constraint, x; param = nothing) Apply the error function of `c` to values `x` and optionally `param`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L51-L56) + +
+
+
+# Constraints.make_errorMethod. + + + + +```julia +make_error(symb::Symbol) +``` + + +Create a function that returns an error based on the predicate of the constraint identified by the symbol provided. + +**Arguments** +- `symb::Symbol`: The symbol used to determine the error function to be returned. The function first checks if a predicate with the prefix "icn_" exists in the Constraints module. If it does, it returns that function. If it doesn't, it checks for a predicate with the prefix "error_". If that exists, it returns that function. If neither exists, it returns a function that evaluates the predicate with the prefix "concept_" and returns the negation of its result cast to Float64. + + +**Returns** +- Function: A function that takes in a variable `x` and an arbitrary number of parameters `params`. The function returns a Float64. + + +**Examples** + +```julia +e = make_error(:all_different) +e([1, 2, 3]) # Returns 0.0 +e([1, 1, 3]) # Returns 1.0 +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L80-L97) + +
+
+
+# Constraints.params_lengthMethod. + + + + +```julia +params_length(c::Constraint) +``` + + +Return the expected length restriction of the arguments in a constraint `c`. The value `nothing` indicates that any strictly positive number of parameters is accepted. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L68-L71) + +
+
+
+# Constraints.shrink_conceptMethod. + + + + +```julia +shrink_concept(s) +``` + + +Simply delete the `concept_` part of symbol or string starting with it. TODO: add a check with a warning if `s` starts with something different. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L104-L108) + +
+
+
+# Constraints.symmetriesMethod. + + + + +```julia +symmetries(c::Constraint) +``` + + +Return the list of symmetries of `c`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L74-L77) + +
+
+
+# Constraints.xcsp_all_differentMethod. + + + + +```julia +xcsp_all_different(list::Vector{Int}) +``` + + +Return `true` if all the values of `list` are different, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + + +**Variants** +- `:all_different`: Global constraint ensuring that all the values of `x` are all different. + + +```julia +concept(:all_different, x; vals) +concept(:all_different)(x; vals) +``` + + +**Examples** + +```julia +c = concept(:all_different) + +c([1, 2, 3, 4]) +c([1, 2, 3, 1]) +c([1, 0, 0, 4]; vals=[0]) +c([1, 0, 0, 1]; vals=[0]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/all_different.jl#L7-L31) + +
+
+
+# Constraints.xcsp_all_equalMethod. + + + + +```julia +xcsp_all_equal(list::Vector{Int}, val::Int) +``` + + +Return `true` if all the values of `list` are equal to `val`, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `val::Int`: value to compare to. + + +**Variants** +- `:all_equal`: Global constraint ensuring that all the values of `x` are all equal. + + +```julia +concept(:all_equal, x; val=nothing, pair_vars=zeros(x), op=+) +concept(:all_equal)(x; val=nothing, pair_vars=zeros(x), op=+) +``` + + +**Examples** + +```julia +c = concept(:all_equal) + +c([0, 0, 0, 0]) +c([1, 2, 3, 4]) +c([3, 2, 1, 0]; pair_vars=[0, 1, 2, 3]) +c([0, 1, 2, 3]; pair_vars=[0, 1, 2, 3]) +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]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/all_equal.jl#L9-L36) + +
+
+
+# Constraints.xcsp_cardinalityMethod. + + + + +```julia +xcsp_cardinality(list, values, occurs, closed) +``` + + +Return `true` if the number of occurrences of the values in `values` in `list` satisfies the given condition, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `values::Vector{Int}`: list of values to check. + +- `occurs::Vector{Int}`: list of occurrences to check. + +- `closed::Bool`: whether the constraint is closed or not. + + +**Variants** +- `:cardinality`: The cardinality constraint, also known as the global cardinality constraint (GCC), is a constraint in constraint programming that restricts the number of times a value can appear in a set of variables. + + +```julia +concept(:cardinality, x; bool=false, vals) +concept(:cardinality)(x; bool=false, vals) +``` + +- `:cardinality_closed`: The closed cardinality constraint, also known as the global cardinality constraint (GCC), is a constraint in constraint programming that restricts the number of times a value can appear in a set of variables. It is closed, meaning that all values in the domain of the variables must be considered. + + +```julia +concept(:cardinality_closed, x; vals) +concept(:cardinality_closed)(x; vals) +``` + +- `:cardinality_open`: The open cardinality constraint, also known as the global cardinality constraint (GCC), is a constraint in constraint programming that restricts the number of times a value can appear in a set of variables. It is open, meaning that only the values in the list of values must be considered. + + +```julia +concept(:cardinality_open, x; vals) +concept(:cardinality_open)(x; vals) +``` + + +**Examples** + +```julia +c = concept(:cardinality) + +c([2, 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) +c([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3], bool=true) +c([2, 5, 10, 10]; vals=[2 1; 5 1; 10 2]) +c([2, 5, 10, 10]; vals=[2 0 1 42; 5 1 3 7; 10 2 3 -4]) +c([2, 5, 5, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) +c([2, 5, 10, 8]; vals=[2 1; 5 1; 10 2]) +c([5, 5, 5, 10]; vals=[2 0 1 42; 5 1 3 7; 10 2 3 -4]) + +cc = concept(:cardinality_closed) +cc([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) + +co = concept(:cardinality_open) +co([8, 5, 10, 10]; vals=[2 0 1; 5 1 3; 10 2 3]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/cardinality.jl#L14-L61) + +
+
+
+# Constraints.xcsp_channelMethod. + + + + +```julia +xcsp_channel(; list) +``` + + +Return `true` if the channel constraint is satisfied, `false` otherwise. The channel constraint establishes a bijective correspondence between two sets of variables. This means that each value in the first set of variables corresponds to a unique value in the second set, and vice versa. + +**Arguments** +- `list::Union{AbstractVector, Tuple}`: list of values to check. + + +**Variants** +- `:channel`: The channel constraint establishes a bijective correspondence between two sets of variables. This means that each value in the first set of variables corresponds to a unique value in the second set, and vice versa. + + +```julia +concept(:channel, x; dim=1, id=nothing) +concept(:channel)(x; dim=1, id=nothing) +``` + + +**Examples** + +```julia +c = concept(:channel) + +c([2, 1, 4, 3]) +c([1, 2, 3, 4]) +c([2, 3, 1, 4]) +c([2, 1, 5, 3, 4, 2, 1, 4, 5, 3]; dim=2) +c([2, 1, 4, 3, 5, 2, 1, 4, 5, 3]; dim=2) +c([false, false, true, false]; id=3) +c([false, false, true, false]; id=1) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/channel.jl#L5-L32) + +
+
+
+# Constraints.xcsp_circuitMethod. + + + + +```julia +xcsp_circuit(; list, size) +``` + + +Return `true` if the circuit constraint is satisfied, `false` otherwise. The circuit constraint is a global constraint used in constraint programming, often in routing problems. It ensures that the values of a list of variables form a circuit, i.e., a sequence where each value is the index of the next value in the sequence, and the sequence eventually loops back to the start. + +**Arguments** +- `list::AbstractVector`: list of values to check. + +- `size::Int`: size of the circuit. + + +**Variants** +- `:circuit`: The circuit constraint is a global constraint used in constraint programming, often in routing problems. It ensures that the values of a list of variables form a circuit, i.e., a sequence where each value is the index of the next value in the sequence, and the sequence eventually loops back to the start. + + +```julia +concept(:circuit, x; op, val) +concept(:circuit)(x; op, val) +``` + + +**Examples** + +```julia +c = concept(:circuit) + +c([1, 2, 3, 4]) +c([2, 3, 4, 1]) +c([2, 3, 1, 4]; op = ==, val = 3) +c([4, 3, 1, 3]; op = >, val = 0) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/circuit.jl#L5-L30) + +
+
+
+# Constraints.xcsp_countMethod. + + + + +```julia +xcsp_count(list, values, condition) +``` + + +Return `true` if the number of occurrences of the values in `values` in `list` satisfies the given condition, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `values::Vector{Int}`: list of values to check. + +- `condition`: condition to satisfy. + + +**Variants** +- `:count`: Constraint ensuring that the number of occurrences of the values in `vals` in `x` satisfies the given condition. + + +```julia +concept(:count, x; vals, op, val) +concept(:count)(x; vals, op, val) +``` + +- `:at_least`: Constraint ensuring that the number of occurrences of the values in `vals` in `x` is at least `val`. + + +```julia +concept(:at_least, x; vals, val) +concept(:at_least)(x; vals, val) +``` + +- `:at_most`: Constraint ensuring that the number of occurrences of the values in `vals` in `x` is at most `val`. + + +```julia +concept(:at_most, x; vals, val) +concept(:at_most)(x; vals, val) +``` + +- `:exactly`: Constraint ensuring that the number of occurrences of the values in `vals` in `x` is exactly `val`. + + +```julia +concept(:exactly, x; vals, val) +concept(:exactly)(x; vals, val) +``` + + +**Examples** + +```julia +c = concept(:count) + +c([2, 1, 4, 3]; vals=[1, 2, 3, 4], op=≥, val=2) +c([1, 2, 3, 4]; vals=[1, 2], op==, val=2) +c([2, 1, 4, 3]; vals=[1, 2], op=≤, val=1) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/count.jl#L17-L57) + +
+
+
+# Constraints.xcsp_cumulativeMethod. + + + + +```julia +xcsp_cumulative(; origins, lengths, heights, condition) +``` + + +Return `true` if the cumulative constraint is satisfied, `false` otherwise. The cumulative constraint is a global constraint used in constraint programming that is often used in scheduling problems. It ensures that for any point in time, the sum of the "heights" of tasks that are ongoing at that time does not exceed a certain limit. + +**Arguments** +- `origins::AbstractVector`: list of origins of the tasks. + +- `lengths::AbstractVector`: list of lengths of the tasks. + +- `heights::AbstractVector`: list of heights of the tasks. + +- `condition::Tuple`: condition to check. + + +**Variants** +- `:cumulative`: The cumulative constraint is a global constraint used in constraint programming that is often used in scheduling problems. It ensures that for any point in time, the sum of the "heights" of tasks that are ongoing at that time does not exceed a certain limit. + + +```julia +concept(:cumulative, x; pair_vars, op, val) +concept(:cumulative)(x; pair_vars, op, val) +``` + + +**Examples** + +```julia +c = concept(:cumulative) + +c([1, 2, 3, 4, 5]; val = 1) +c([1, 2, 2, 4, 5]; val = 1) +c([1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = ≤, val = 5) +c([1, 2, 3, 4, 5]; pair_vars = [3 2 5 4 2; 1 2 1 1 3], op = <, val = 5) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/cumulative.jl#L5-L32) + +
+
+
+# Constraints.xcsp_elementMethod. + + + + +```julia +xcsp_element(; list, index, condition) +``` + + +Return `true` if the element constraint is satisfied, `false` otherwise. The element constraint is a global constraint used in constraint programming that specifies that the value of a variable should be equal to the value of another variable indexed by a third variable. + +**Arguments** +- `list::Union{AbstractVector, Tuple}`: list of values to check. + +- `index::Int`: index of the value to check. + +- `condition::Tuple`: condition to check. + + +**Variants** +- `:element`: The element constraint is a global constraint used in constraint programming that specifies that the value of a variable should be equal to the value of another variable indexed by a third variable. + + +```julia +concept(:element, x; id=nothing, op===, val=nothing) +concept(:element)(x; id=nothing, op===, val=nothing) +``` + + +**Examples** + +```julia +c = concept(:element) + +c([1, 2, 3, 4, 5]; id=1, val=1) +c([1, 2, 3, 4, 5]; id=1, val=2) +c([1, 2, 3, 4, 2]) +c([1, 2, 3, 4, 1]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/element.jl#L5-L31) + +
+
+
+# Constraints.xcsp_extensionMethod. + + + + +```julia +xcsp_extension(; list, supports=nothing, conflicts=nothing) +``` + + +Global constraint enforcing that the tuple `x` matches a configuration within the supports set `pair_vars[1]` or does not match any configuration within the conflicts set `pair_vars[2]`. It embodies the logic: `x ∈ pair_vars[1] || x ∉ pair_vars[2]`, providing a comprehensive way to define valid (supported) and invalid (conflicted) tuples for constraint satisfaction problems. This constraint is versatile, allowing for the explicit delineation of both acceptable and unacceptable configurations. + +**Arguments** +- `list::Vector{Int}`: A list of variables + +- `supports::Vector{Vector{Int}}`: A set of supported tuples. Default to nothing. + +- `conflicts::Vector{Vector{Int}}`: A set of conflicted tuples. Default to nothing. + + +**Variants** +- `:extension`: Global constraint enforcing that the tuple `x` matches a configuration within the supports set `pair_vars[1]` or does not match any configuration within the conflicts set `pair_vars[2]`. It embodies the logic: `x ∈ pair_vars[1] || x ∉ pair_vars[2]`, providing a comprehensive way to define valid (supported) and invalid (conflicted) tuples for constraint satisfaction problems. This constraint is versatile, allowing for the explicit delineation of both acceptable and unacceptable configurations. + + +```julia +concept(:extension, x; pair_vars) +concept(:extension)(x; pair_vars) +``` + +- `:supports`: Global constraint ensuring that the tuple `x` matches a configuration listed within the support set `pair_vars`. This constraint is derived from the extension model, specifying that `x` must be one of the explicitly defined supported configurations: `x ∈ pair_vars`. It is utilized to directly declare the tuples that are valid and should be included in the solution space. + + +```julia +concept(:supports, x; pair_vars) +concept(:supports)(x; pair_vars) +``` + +- `:conflicts`: Global constraint ensuring that the tuple `x` does not match any configuration listed within the conflict set `pair_vars`. This constraint, originating from the extension model, stipulates that `x` must avoid all configurations defined as conflicts: `x ∉ pair_vars`. It is useful for specifying tuples that are explicitly forbidden and should be excluded from the solution space. + + +```julia +concept(:conflicts, x; pair_vars) +concept(:conflicts)(x; pair_vars) +``` + + +**Examples** + +```julia +c = concept(:extension) +c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) +c([1, 2, 3, 4, 5]; pair_vars=([[1, 2, 3, 4, 5]], [[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]])) +c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) + +c = concept(:supports) +c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 3, 4, 5]]) + +c = concept(:conflicts) +c([1, 2, 3, 4, 5]; pair_vars=[[1, 2, 1, 4, 5], [1, 2, 3, 5, 5]]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/extension.jl#L20-L60) + +
+
+
+# Constraints.xcsp_instantiationMethod. + + + + +```julia +xcsp_instantiation(; list, values) +``` + + +Return `true` if the instantiation constraint is satisfied, `false` otherwise. The instantiation constraint is a global constraint used in constraint programming that ensures that a list of variables takes on a specific set of values in a specific order. + +**Arguments** +- `list::AbstractVector`: list of values to check. + +- `values::AbstractVector`: list of values to check against. + + +**Variants** +- `:instantiation`: The instantiation constraint is a global constraint used in constraint programming that ensures that a list of variables takes on a specific set of values in a specific order. + + +```julia +concept(:instantiation, x; pair_vars) +concept(:instantiation)(x; pair_vars) +``` + + +**Examples** + +```julia +c = concept(:instantiation) + +c([1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 5]) +c([1, 2, 3, 4, 5]; pair_vars=[1, 2, 3, 4, 6]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/instantiation.jl#L5-L28) + +
+
+
+# Constraints.xcsp_intensionMethod. + + + + +```julia +xcsp_intension(list, predicate) +``` + + +An intensional constraint is usually defined from a `predicate` over `list`. As such it encompass any generic constraint. + +**Arguments** +- `list::Vector{Int}`: A list of variables + +- `predicate::Function`: A predicate over `list` + + +**Variants** +- `:dist_different`: A constraint ensuring that the distances between marks on the ruler are unique. Specifically, it checks that the distance between `x[1]` and `x[2]`, and the distance between `x[3]` and `x[4]`, are different. This constraint is fundamental in ensuring the validity of a Golomb ruler, where no two pairs of marks should have the same distance between them. + + +```julia +concept(:dist_different, x) +concept(:dist_different)(x) +``` + + +**Examples** + +```@example debug2 +2 + 2 +``` + + +```@example debug1 +2 + 2 +``` + + +```@example intention1 +using Constraints # hide +c = concept(:dist_different) +c([1, 2, 3, 3]) && !c([1, 2, 3, 4]) +``` + + +```@example intention2 +using Constraints # hide +c = concept(:dist_different) +c([1, 2, 3, 3]) && !c([1, 2, 3, 4]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/intention.jl#L9-L47) + +
+
+
+# Constraints.xcsp_maximumMethod. + + + + +```julia +xcsp_maximum(; list, condition) +``` + + +Return `true` if the maximum constraint is satisfied, `false` otherwise. The maximum constraint is a global constraint used in constraint programming that specifies that a certain condition should hold for the maximum value in a list of variables. + +**Arguments** +- `list::Union{AbstractVector, Tuple}`: list of values to check. + +- `condition::Tuple`: condition to check. + + +**Variants** +- `:maximum`: The maximum constraint is a global constraint used in constraint programming that specifies that a certain condition should hold for the maximum value in a list of variables. + + +```julia +concept(:maximum, x; op, val) +concept(:maximum)(x; op, val) +``` + + +**Examples** + +```julia +c = concept(:maximum) + +c([1, 2, 3, 4, 5]; op = ==, val = 5) +c([1, 2, 3, 4, 5]; op = ==, val = 6) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/maximum.jl#L5-L28) + +
+
+
+# Constraints.xcsp_mddMethod. + + + + +```julia +xcsp_mdd(; list, diagram) +``` + + +Return a function that checks if the list of values `list` satisfies the MDD `diagram`. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `diagram::MDD`: MDD to check. + + +**Variants** +- `:mdd`: Multi-valued Decision Diagram (MDD) constraint. + The MDD constraint is a constraint that can be used to model a wide range of problems. It is a directed graph where each node is labeled with a value and each edge is labeled with a value. The constraint is satisfied if there is a path from the first node to the last node such that the sequence of edge labels is a valid sequence of the value labels. + + +```julia +concept(:mdd, x; language) +concept(:mdd)(x; language) +``` + + +**Examples** + +```julia +c = concept(:mdd) + +states = [ + Dict( # level x1 + (:r, 0) => :n1, + (:r, 1) => :n2, + (:r, 2) => :n3, + ), + Dict( # level x2 + (:n1, 2) => :n4, + (:n2, 2) => :n4, + (:n3, 0) => :n5, + ), + Dict( # level x3 + (:n4, 0) => :t, + (:n5, 0) => :t, + ), +] + +a = MDD(states) + +c([0,2,0]; language = a) +c([1,2,0]; language = a) +c([2,0,0]; language = a) +c([2,1,2]; language = a) +c([1,0,2]; language = a) +c([0,1,2]; language = a) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/mdd.jl#L9-L55) + +
+
+
+# Constraints.xcsp_minimumMethod. + + + + +```julia +xcsp_minimum(; list, condition) +``` + + +Return `true` if the minimum constraint is satisfied, `false` otherwise. The minimum constraint is a global constraint used in constraint programming that specifies that a certain condition should hold for the minimum value in a list of variables. + +**Arguments** +- `list::Union{AbstractVector, Tuple}`: list of values to check. + +- `condition::Tuple`: condition to check. + + +**Variants** +- `:minimum`: The minimum constraint is a global constraint used in constraint programming that specifies that a certain condition should hold for the minimum value in a list of variables. + + +```julia +concept(:minimum, x; op, val) +concept(:minimum)(x; op, val) +``` + + +**Examples** + +```julia +c = concept(:minimum) + +c([1, 2, 3, 4, 5]; op = ==, val = 1) +c([1, 2, 3, 4, 5]; op = ==, val = 0) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/minimum.jl#L5-L28) + +
+
+
+# Constraints.xcsp_no_overlapMethod. + + + + +```julia +xcsp_no_overlap(; origins, lengths, zero_ignored) +``` + + +Return `true` if the no_overlap constraint is satisfied, `false` otherwise. The no_overlap constraint is a global constraint used in constraint programming, often in scheduling problems. It ensures that tasks do not overlap in time, i.e., for any two tasks, either the first task finishes before the second task starts, or the second task finishes before the first task starts. + +**Arguments** +- `origins::AbstractVector`: list of origins of the tasks. + +- `lengths::AbstractVector`: list of lengths of the tasks. + +- `zero_ignored::Bool`: whether to ignore zero-length tasks. + + +**Variants** +- `:no_overlap`: The no_overlap constraint is a global constraint used in constraint programming, often in scheduling problems. It ensures that tasks do not overlap in time, i.e., for any two tasks, either the first task finishes before the second task starts, or the second task finishes before the first task starts. + + +```julia +concept(:no_overlap, x; pair_vars, bool) +concept(:no_overlap)(x; pair_vars, bool) +``` + +- `:no_overlap_no_zero`: The no_overlap constraint is a global constraint used in constraint programming, often in scheduling problems. It ensures that tasks do not overlap in time, i.e., for any two tasks, either the first task finishes before the second task starts, or the second task finishes before the first task starts. This variant ignores zero-length tasks. + + +```julia +concept(:no_overlap_no_zero, x; pair_vars) +concept(:no_overlap_no_zero)(x; pair_vars) +``` + +- `:no_overlap_with_zero`: The no_overlap constraint is a global constraint used in constraint programming, often in scheduling problems. It ensures that tasks do not overlap in time, i.e., for any two tasks, either the first task finishes before the second task starts, or the second task finishes before the first task starts. This variant includes zero-length tasks. + + +```julia +concept(:no_overlap_with_zero, x; pair_vars) +concept(:no_overlap_with_zero)(x; pair_vars) +``` + + +**Examples** + +```julia +c = concept(:no_overlap) + +c([1, 2, 3, 4, 5]) +c([1, 2, 3, 4, 1]) +c([1, 2, 4, 6, 3]; pair_vars = [1, 1, 1, 1, 1]) +c([1, 2, 4, 6, 3]; pair_vars = [1, 1, 1, 3, 1]) +c([1, 2, 4, 6, 3]; pair_vars = [1, 1, 3, 1, 1]) +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) +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) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/no_overlap.jl#L13-L52) + +
+
+
+# Constraints.xcsp_nvaluesMethod. + + + + +```julia +xcsp_nvalues(list, condition, except) +``` + + +Return `true` if the number of distinct values in `list` satisfies the given condition, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `condition`: condition to satisfy. + +- `except::Union{Nothing, Vector{Int}}`: list of values to exclude. Default is `nothing`. + + +**Variants** +- `:nvalues`: The nValues constraint specifies that the number of distinct values in the list of variables x is equal to a given value. The constraint is defined by the following expression: nValues(x, op, val) where x is a list of variables, op is a comparison operator, and val is an integer value. + + +```julia +concept(:nvalues, x; op, val) +concept(:nvalues)(x; op, val) +``` + + +**Examples** + +```julia +c = concept(:nvalues) + +c([1, 2, 3, 4, 5]; op = ==, val = 5) +c([1, 2, 3, 4, 5]; op = ==, val = 2) +c([1, 2, 3, 4, 3]; op = <=, val = 5) +c([1, 2, 3, 4, 3]; op = <=, val = 3) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/n_values.jl#L7-L33) + +
+
+
+# Constraints.xcsp_orderedMethod. + + + + +```julia +xcsp_ordered(list::Vector{Int}, operator, lengths) +``` + + +Return `true` if all the values of `list` are in an increasing order, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `operator`: comparison operator to use. + +- `lengths`: list of lengths to use. Defaults to `nothing`. + + +**Variants** +- `:ordered`: Global constraint ensuring that all the values of `x` are in an increasing order. + + +```julia +concept(:ordered, x; op=≤, pair_vars=nothing) +concept(:ordered)(x; op=≤, pair_vars=nothing) +``` + +- `:increasing`: Global constraint ensuring that all the values of `x` are in an increasing order. + + +```julia +concept(:increasing, x; op=≤, pair_vars=nothing) +concept(:increasing)(x; op=≤, pair_vars=nothing) +``` + +- `:decreasing`: Global constraint ensuring that all the values of `x` are in a decreasing order. + + +```julia +concept(:decreasing, x; op=≥, pair_vars=nothing) +concept(:decreasing)(x; op=≥, pair_vars=nothing) +``` + +- `:strictly_increasing`: Global constraint ensuring that all the values of `x` are in a strictly increasing order. + + +```julia +concept(:strictly_increasing, x; op=<, pair_vars=nothing) +concept(:strictly_increasing)(x; op=<, pair_vars=nothing) +``` + +- `:strictly_decreasing`: Global constraint ensuring that all the values of `x` are in a strictly decreasing order. + + +```julia +concept(:strictly_decreasing, x; op=>, pair_vars=nothing) +concept(:strictly_decreasing)(x; op=>, pair_vars=nothing) +``` + + +**Examples** + +```julia +c = concept(:ordered) + +c([1, 2, 3, 4, 4]; op=≤) +c([1, 2, 3, 4, 5]; op=<) +!c([1, 2, 3, 4, 3]; op=≤) +!c([1, 2, 3, 4, 3]; op=<) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/ordered.jl#L21-L67) + +
+
+
+# Constraints.xcsp_regularMethod. + + + + +```julia +xcsp_regular(; list, automaton) + +Ensures that a sequence `x` (interpreted as a word) is accepted by the regular language represented by a given automaton. This constraint verifies the compliance of `x` with the language rules encoded within the `automaton` parameter, which must be an instance of `<:AbstractAutomaton`. +``` + + +**Arguments** +- `list::Vector{Int}`: A list of variables + +- `automaton<:AbstractAutomaton`: An automaton representing the regular language + + +**Variants** +- `:regular`: Ensures that a sequence `x` (interpreted as a word) is accepted by the regular language represented by a given automaton. This constraint verifies the compliance of `x` with the language rules encoded within the `automaton` parameter, which must be an instance of `<:AbstractAutomaton`. + + +```julia +concept(:regular, x; language) +concept(:regular)(x; language) +``` + + +**Examples** + +```julia +c = concept(:regular) + +states = Dict( + (:a, 0) => :a, + (:a, 1) => :b, + (:b, 1) => :c, + (:c, 0) => :d, + (:d, 0) => :d, + (:d, 1) => :e, + (:e, 0) => :e, +) +start = :a +finish = :e + +a = Automaton(states, start, finish) + +c([0,0,1,1,0,0,1,0,0]; language = a) +c([1,1,1,0,1]; language = a) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/regular.jl#L5-L42) + +
+
+
+# Constraints.xcsp_sumMethod. + + + + +```julia +xcsp_sum(list, coeffs, condition) +``` + + +Return `true` if the sum of the variables in `list` satisfies the given condition, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + +- `coeffs::Vector{Int}`: list of coefficients to use. + +- `condition`: condition to satisfy. + + +**Variants** +- `:sum`: Global constraint ensuring that the sum of the variables in `x` satisfies a given condition. + + +```julia +concept(:sum, x; op===, pair_vars=ones(x), val) +concept(:sum)(x; op===, pair_vars=ones(x), val) +``` + + +**Examples** + +```julia +c = concept(:sum) + +c([1, 2, 3, 4, 5]; op===, val=15) +c([1, 2, 3, 4, 5]; op===, val=2) +c([1, 2, 3, 4, 3]; op=≤, val=15) +c([1, 2, 3, 4, 3]; op=≤, val=3) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/sum.jl#L5-L31) + +
+
+
+# Constraints.@usualMacro. + + + + +```julia +usual(ex::Expr) +``` + + +This macro is used to define a new constraint or update an existing one in the USUAL_CONSTRAINTS dictionary. It takes an expression ex as input, which represents the definition of a constraint. + +Here's a step-by-step explanation of what the macro does: +1. It first extracts the symbol of the concept from the input expression. This symbol is expected to be the first argument of the first argument of the expression. For example, if the expression is @usual all_different(x; y=1), the symbol would be :all_different. + +2. It then calls the shrink_concept function on the symbol to get a simplified version of the concept symbol. + +3. It initializes a dictionary defaults to store whether each keyword argument of the concept has a default value or not. + +4. It checks if the expression has more than two arguments. If it does, it means that there are keyword arguments present. It then loops over these keyword arguments. If a keyword argument is a symbol, it means it doesn't have a default value, so it adds an entry to the defaults dictionary with the keyword argument as the key and false as the value. If a keyword argument is not a symbol, it means it has a default value, so it adds an entry to the defaults dictionary with the keyword argument as the key and true as the value. + +5. It calls the make_error function on the simplified concept symbol to generate an error function for the constraint. + +6. It evaluates the input expression to get the concept function. + +7. It checks if the USUAL_CONSTRAINTS dictionary already contains an entry for the simplified concept symbol. If it does, it adds the defaults dictionary to the parameters of the existing constraint. If it doesn't, it creates a new constraint with the concept function, a description, the error function, and the defaults dictionary as the parameters, and adds it to the USUAL_CONSTRAINTS dictionary. + + +This macro is used to make it easier to define and update constraints in a consistent and possibly automated way. + +**Arguments** +- `ex::Expr`: expression to parse. + + +**Example** + +```julia +@usual concept_all_different(x; vals=nothing) = xcsp_all_different(list=x, except=vals) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L67-L90) + +
+
+
+# CompositionalNetworks.CompositionType. + + + + +```julia +struct Composition{F<:Function} +``` + + +Store the all the information of a composition learned by an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L1-L5) + +
+
+
+# CompositionalNetworks.CompositionMethod. + + + + +```julia +Composition(f::F, symbols) where {F<:Function} +``` + + +Construct a `Composition`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L12-L16) + +
+
+
+# CompositionalNetworks.ICNType. + + + + +```julia +ICN(; nvars, dom_size, param, transformation, arithmetic, aggregation, comparison) +``` + + +Construct an Interpretable Compositional Network, with the following arguments: +- `nvars`: number of variable in the constraint + +- `dom_size: maximum domain size of any variable in the constraint` + +- `param`: optional parameter (default to `nothing`) + +- `transformation`: a transformation layer (optional) + +- `arithmetic`: a arithmetic layer (optional) + +- `aggregation`: a aggregation layer (optional) + +- `comparison`: a comparison layer (optional) + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L1-L11) + +
+
+
+# CompositionalNetworks.LayerType. + + + + +```julia +Layer +``` + + +A structure to store a `LittleDict` of operations that can be selected during the learning phase of an ICN. If the layer is exclusive, only one operation can be selected at a time. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L1-L4) + +
+
+
+# Base.lengthMethod. + + + + +```julia +length(layer) +``` + + +Return the number of operations in a layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L17-L20) + +
+
+
+# Base.lengthMethod. + + + + +```julia +Base.length(icn) +``` + + +Return the total number of operations of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L37-L40) + +
+
+
+# CompositionalNetworks._composeMethod. + + + + +```julia +_compose(icn) +``` + + +Internal function called by `compose` and `show_composition`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L112-L115) + +
+
+
+# CompositionalNetworks.ag_count_positiveMethod. + + + + +```julia +ag_count_positive(x) +``` + + +Count the number of strictly positive elements of `x`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/aggregation.jl#L7-L10) + +
+
+
+# CompositionalNetworks.ag_sumMethod. + + + + +```julia +ag_sum(x) +``` + + +Aggregate through `+` a vector into a single scalar. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/aggregation.jl#L1-L4) + +
+
+
+# CompositionalNetworks.aggregation_layerMethod. + + + + +```julia +aggregation_layer() +``` + + +Generate the layer of aggregations of the ICN. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/aggregation.jl#L13-L16) + +
+
+
+# CompositionalNetworks.ar_prodMethod. + + + + +```julia +ar_prod(x) +``` + + +Reduce `k = length(x)` vectors through product to a single vector. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/arithmetic.jl#L7-L10) + +
+
+
+# CompositionalNetworks.ar_sumMethod. + + + + +```julia +ar_sum(x) +``` + + +Reduce `k = length(x)` vectors through sum to a single vector. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/arithmetic.jl#L1-L4) + +
+
+
+# CompositionalNetworks.arithmetic_layerMethod. + + + + +```julia +arithmetic_layer() +``` + + +Generate the layer of arithmetic operations of the ICN. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/arithmetic.jl#L13-L16) + +
+
+
+# CompositionalNetworks.as_bitvectorFunction. + + + + +```julia +as_bitvector(n::Int, max_n::Int = n) +``` + + +Convert an Int to a BitVector of minimal size (relatively to `max_n`). + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L48-L51) + +
+
+
+# CompositionalNetworks.as_intMethod. + + + + +```julia +as_int(v::AbstractVector) +``` + + +Convert a `BitVector` into an `Int`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L65-L68) + +
+
+
+# CompositionalNetworks.co_abs_diff_val_paramMethod. + + + + +```julia +co_abs_diff_val_param(x; param) +``` + + +Return the absolute difference between `x` and `param`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L7-L10) + +
+
+
+# CompositionalNetworks.co_abs_diff_val_varsMethod. + + + + +```julia +co_abs_diff_val_vars(x; nvars) +``` + + +Return the absolute difference between `x` and the number of variables `nvars`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L41-L44) + +
+
+
+# CompositionalNetworks.co_euclideanMethod. + + + + +```julia +co_euclidean(x; dom_size) +``` + + +Compute an euclidean norm with domain size `dom_size` of a scalar. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L33-L36) + +
+
+
+# CompositionalNetworks.co_euclidean_paramMethod. + + + + +```julia +co_euclidean_param(x; param, dom_size) +``` + + +Compute an euclidean norm with domain size `dom_size`, weighted by `param`, of a scalar. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L25-L28) + +
+
+
+# CompositionalNetworks.co_identityMethod. + + + + +```julia +co_identity(x) +``` + + +Identity function. Already defined in Julia as `identity`, specialized for scalars in the `comparison` layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L1-L4) + +
+
+
+# CompositionalNetworks.co_param_minus_valMethod. + + + + +```julia +co_param_minus_val(x; param) +``` + + +Return the difference `param - x` if positive, `0.0` otherwise. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L19-L22) + +
+
+
+# CompositionalNetworks.co_val_minus_paramMethod. + + + + +```julia +co_val_minus_param(x; param) +``` + + +Return the difference `x - param` if positive, `0.0` otherwise. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L13-L16) + +
+
+
+# CompositionalNetworks.co_val_minus_varsMethod. + + + + +```julia +co_val_minus_vars(x; nvars) +``` + + +Return the difference `x - nvars` if positive, `0.0` otherwise, where `nvars` denotes the numbers of variables. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L47-L50) + +
+
+
+# CompositionalNetworks.co_vars_minus_valMethod. + + + + +```julia +co_vars_minus_val(x; nvars) +``` + + +Return the difference `nvars - x` if positive, `0.0` otherwise, where `nvars` denotes the numbers of variables. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L54-L57) + +
+
+
+# CompositionalNetworks.codeFunction. + + + + +```julia +code(c::Composition, lang=:maths; name="composition") +``` + + +Access the code of a composition `c` in a given language `lang`. The name of the generated method is optional. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L22-L26) + +
+
+
+# CompositionalNetworks.comparison_layerFunction. + + + + +```julia +comparison_layer(param = false) +``` + + +Generate the layer of transformations functions of the ICN. Iff `param` value is set, also includes all the parametric comparison with that value. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L85-L88) + +
+
+
+# CompositionalNetworks.composeFunction. + + + + +```julia +compose(icn, weights=nothing) +``` + + +Return a function composed by some of the operations of a given ICN. Can be applied to any vector of variables. If `weights` are given, will assign to `icn`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L45-L48) + +
+
+
+# CompositionalNetworks.compose_to_file!Method. + + + + +```julia +compose_to_file!(concept, name, path; domains, param = nothing, language = :Julia, search = :complete, global_iter = 10, local_iter = 100, metric = hamming, popSize = 200) +``` + + +Explore, learn and compose a function and write it to a file. + +**Arguments:** +- `concept`: the concept to learn + +- `name`: the name to give to the constraint + +- `path`: path of the output file + + +**Keywords arguments:** +- `domains`: domains that defines the search space + +- `param`: an optional parameter of the constraint + +- `language`: the language to export to, default to `:julia` + +- `search`: either `:partial` or `:complete` search + +- `global_iter`: number of learning iteration + +- `local_iter`: number of generation in the genetic algorithm + +- `metric`: the metric to measure the distance between a configuration and known solutions + +- `popSize`: size of the population in the genetic algorithm + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/learn.jl#L77-L95) + +
+
+
+# CompositionalNetworks.compositionMethod. + + + + +```julia +composition(c::Composition) +``` + + +Access the actual method of an ICN composition `c`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L31-L35) + +
+
+
+# CompositionalNetworks.composition_to_file!Function. + + + + +```julia +composition_to_file!(c::Composition, path, name, language=:Julia) +``` + + +Write the composition code in a given `language` into a file at `path`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L97-L101) + +
+
+
+# CompositionalNetworks.excluMethod. + + + + +```julia +exclu(layer) +``` + + +Return `true` if the layer has mutually exclusive operations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L23-L26) + +
+
+
+# CompositionalNetworks.explore_learn_composeMethod. + + + + +```julia +explore_learn_compose(concept; domains, param = nothing, search = :complete, global_iter = 10, local_iter = 100, metric = hamming, popSize = 200, action = :composition) +``` + + +Explore a search space, learn a composition from an ICN, and compose an error function. + +**Arguments:** +- `concept`: the concept of the targeted constraint + +- `domains`: domains of the variables that define the training space + +- `param`: an optional parameter of the constraint + +- `search`: either `flexible`,`:partial` or `:complete` search. Flexible search will use `search_limit` and `solutions_limit` to determine if the search space needs to be partially or completely explored + +- `global_iter`: number of learning iteration + +- `local_iter`: number of generation in the genetic algorithm + +- `metric`: the metric to measure the distance between a configuration and known solutions + +- `popSize`: size of the population in the genetic algorithm + +- `action`: either `:symbols` to have a description of the composition or `:composition` to have the composed function itself + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/learn.jl#L35-L50) + +
+
+
+# CompositionalNetworks.functionsMethod. + + + + +```julia +functions(layer) +``` + + +Access the operations of a layer. The container is ordered. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L11-L14) + +
+
+
+# CompositionalNetworks.generateMethod. + + + + +```julia +generate(c::Composition, name, lang) +``` + + +Generates the code of `c` in a specific language `lang`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L55-L59) + +
+
+
+# CompositionalNetworks.generate_exclusive_operationMethod. + + + + +```julia +generate_exclusive_operation(max_op_number) +``` + + +Generates the operations (weigths) of a layer with exclusive operations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L75-L78) + +
+
+
+# CompositionalNetworks.generate_inclusive_operationsMethod. + + + + +```julia +generate_inclusive_operations(predicate, bits) +generate_exclusive_operation(max_op_number) +``` + + +Generates the operations (weights) of a layer with inclusive/exclusive operations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L61-L65) + +
+
+
+# CompositionalNetworks.generate_weightsMethod. + + + + +```julia +generate_weights(layers) +generate_weights(icn) +``` + + +Generate the weights of a collection of layers or of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L84-L88) + +
+
+
+# CompositionalNetworks.hammingMethod. + + + + +```julia +hamming(x, X) +``` + + +Compute the hamming distance of `x` over a collection of solutions `X`, i.e. the minimal number of variables to switch in `x`to reach a solution. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L1-L4) + +
+
+
+# CompositionalNetworks.is_viableMethod. + + + + +```julia +is_viable(layer, w) +is_viable(icn) +is_viable(icn, w) +``` + + +Assert if a pair of layer/icn and weights compose a viable pattern. If no weights are given with an icn, it will check the current internal value. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L53-L58) + +
+
+
+# CompositionalNetworks.layersMethod. + + + + +```julia +layers(icn) +``` + + +Return the ordered layers of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L31-L34) + +
+
+
+# CompositionalNetworks.lazyMethod. + + + + +```julia +lazy(funcs::Function...) +``` + + +Generate methods extended to a vector instead of one of its components. A function `f` should have the following signature: `f(i::Int, x::V)`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L22-L25) + +
+
+
+# CompositionalNetworks.lazy_paramMethod. + + + + +```julia +lazy_param(funcs::Function...) +``` + + +Generate methods extended to a vector instead of one of its components. A function `f` should have the following signature: `f(i::Int, x::V; param)`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L36-L39) + +
+
+
+# CompositionalNetworks.learn_composeMethod. + + + + +```julia +learn_compose(; + nvars, dom_size, param=nothing, icn=ICN(nvars, dom_size, param), + X, X_sols, global_iter=100, local_iter=100, metric=hamming, popSize=200 +) +``` + + +Create an ICN, optimize it, and return its composition. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/learn.jl#L7-L13) + +
+
+
+# CompositionalNetworks.make_transformationsMethod. + + + + +```julia +make_transformations(param::Symbol) +``` + + +Generates a dictionary of transformation functions based on the specified parameterization. This function facilitates the creation of parametric layers for constraint transformations, allowing for flexible and dynamic constraint manipulation according to the needs of different constraint programming models. + +**Parameters** +- `param::Symbol`: Specifies the type of transformations to generate. It can be `:none` for basic transformations that do not depend on external parameters, or `:val` for transformations that operate with respect to a specific value parameter. + + +**Returns** +- `LittleDict{Symbol, Function}`: A dictionary mapping transformation names (`Symbol`) to their corresponding functions (`Function`). The functions encapsulate various types of transformations, such as counting, comparison, and contiguous value processing. + + +**Transformation Types** +- When `param` is `:none`, the following transformations are available: + - `:identity`: No transformation is applied. + + - `:count_eq`, `:count_eq_left`, `:count_eq_right`: Count equalities under different conditions. + + - `:count_greater`, `:count_lesser`: Count values greater or lesser than a threshold. + + - `:count_g_left`, `:count_l_left`, `:count_g_right`, `:count_l_right`: Count values with greater or lesser comparisons from different directions. + + - `:contiguous_vals_minus`, `:contiguous_vals_minus_rev`: Process contiguous values with subtraction in normal and reverse order. + + +- When `param` is `:val`, the transformations relate to operations involving a parameter value: + - `:count_eq_param`, `:count_l_param`, `:count_g_param`: Count equalities or comparisons against a parameter value. + + - `:count_bounding_param`: Count values bounding a parameter value. + + - `:val_minus_param`, `:param_minus_val`: Subtract a parameter value from values or vice versa. + + + +The function delegates to a version that uses `Val(param)` for dispatch, ensuring compile-time selection of the appropriate transformation set. + +**Examples** + +```julia +# Get basic transformations +basic_transforms = make_transformations(:none) + +# Apply an identity transformation +identity_result = basic_transforms[:identity](data) + +# Get value-based transformations +val_transforms = make_transformations(:val) + +# Apply a count equal to parameter transformation +count_eq_param_result = val_transforms[:count_eq_param](data, param) +``` + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L216-L262) + +
+
+
+# CompositionalNetworks.manhattanMethod. + + + + +```julia +manhattan(x, X) +``` + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L12-L14) + +
+
+
+# CompositionalNetworks.map_tr!Method. + + + + +```julia +map_tr!(f, x, X, param) +``` + + +Return an anonymous function that applies `f` to all elements of `x` and store the result in `X`, with a parameter `param` (which is set to `nothing` for function with no parameter). + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L1-L4) + +
+
+
+# CompositionalNetworks.minkowskiMethod. + + + + +```julia +minkowski(x, X, p) +``` + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L7-L9) + +
+
+
+# CompositionalNetworks.nbitsMethod. + + + + +```julia +nbits(icn) +``` + + +Return the expected number of bits of a viable weight of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L43-L46) + +
+
+
+# CompositionalNetworks.nbits_excluMethod. + + + + +```julia +nbits_exclu(layer) +``` + + +Convert the length of an exclusive layer into a number of bits. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L35-L38) + +
+
+
+# CompositionalNetworks.reduce_symbolsFunction. + + + + +```julia +reduce_symbols(symbols, sep) +``` + + +Produce a formatted string that separates the symbols by `sep`. Used internally for `show_composition`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L77-L80) + +
+
+
+# CompositionalNetworks.regularizationMethod. + + + + +```julia +regularization(icn) +``` + + +Return the regularization value of an ICN weights, which is proportional to the normalized number of operations selected in the icn layers. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L89-L92) + +
+
+
+# CompositionalNetworks.selected_sizeMethod. + + + + +```julia +selected_size(layer, layer_weights) +``` + + +Return the number of operations selected by `layer_weights` in `layer`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L47-L50) + +
+
+
+# CompositionalNetworks.show_layerMethod. + + + + +```julia +show_layer(layer) +``` + + +Return a string that contains the elements in a layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L41-L44) + +
+
+
+# CompositionalNetworks.show_layersMethod. + + + + +```julia +show_layers(icn) +``` + + +Return a formatted string with each layers in the icn. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L81-L84) + +
+
+
+# CompositionalNetworks.symbolMethod. + + + + +```julia +symbol(layer, i) +``` + + +Return the i-th symbols of the operations in a given layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L29-L32) + +
+
+
+# CompositionalNetworks.symbolsMethod. + + + + +```julia +symbols(c::Composition) +``` + + +Output the composition as a layered collection of `Symbol`s. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L38-L42) + +
+
+
+# CompositionalNetworks.tr_contiguous_vals_minusMethod. + + + + +```julia +tr_contiguous_vals_minus(i, x) +tr_contiguous_vals_minus(x) +tr_contiguous_vals_minus(x, X::AbstractVector) +``` + + +Return the difference `x[i] - x[i + 1]` if positive, `0.0` otherwise. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L190-L197) + +
+
+
+# CompositionalNetworks.tr_contiguous_vals_minus_revMethod. + + + + +```julia +tr_contiguous_vals_minus_rev(i, x) +tr_contiguous_vals_minus_rev(x) +tr_contiguous_vals_minus_rev(x, X::AbstractVector) +``` + + +Return the difference `x[i + 1] - x[i]` if positive, `0.0` otherwise. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L201-L208) + +
+
+
+# CompositionalNetworks.tr_count_bounding_paramMethod. + + + + +```julia +tr_count_bounding_param(i, x; param) +tr_count_bounding_param(x; param) +tr_count_bounding_param(x, X::AbstractVector; param) +``` + + +Count the number of elements bounded (not strictly) by `x[i]` and `x[i] + param`. An extended method to vector with sig `(x, param)` is generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L151-L158) + +
+
+
+# CompositionalNetworks.tr_count_eqMethod. + + + + +```julia +tr_count_eq(i, x) +tr_count_eq(x) +tr_count_eq(x, X::AbstractVector) +``` + + +Count the number of elements equal to `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L16-L23) + +
+
+
+# CompositionalNetworks.tr_count_eq_leftMethod. + + + + +```julia +tr_count_eq_left(i, x) +tr_count_eq_left(x) +tr_count_eq_left(x, X::AbstractVector) +``` + + +Count the number of elements to the left of and equal to `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L36-L43) + +
+
+
+# CompositionalNetworks.tr_count_eq_paramMethod. + + + + +```julia +tr_count_eq_param(i, x; param) +tr_count_eq_param(x; param) +tr_count_eq_param(x, X::AbstractVector; param) +``` + + +Count the number of elements equal to `x[i] + param`. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L116-L123) + +
+
+
+# CompositionalNetworks.tr_count_eq_rightMethod. + + + + +```julia +tr_count_eq_right(i, x) +tr_count_eq_right(x) +tr_count_eq_right(x, X::AbstractVector) +``` + + +Count the number of elements to the right of and equal to `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L26-L33) + +
+
+
+# CompositionalNetworks.tr_count_g_leftMethod. + + + + +```julia +tr_count_g_left(i, x) +tr_count_g_left(x) +tr_count_g_left(x, X::AbstractVector) +``` + + +Count the number of elements to the left of and greater than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L71-L78) + +
+
+
+# CompositionalNetworks.tr_count_g_paramMethod. + + + + +```julia +tr_count_g_param(i, x; param) +tr_count_g_param(x; param) +tr_count_g_param(x, X::AbstractVector; param) +``` + + +Count the number of elements greater than `x[i] + param`. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L136-L143) + +
+
+
+# CompositionalNetworks.tr_count_g_rightMethod. + + + + +```julia +tr_count_g_right(i, x) +tr_count_g_right(x) +tr_count_g_right(x, X::AbstractVector) +``` + + +Count the number of elements to the right of and greater than `x[i]`. Extended method to vector with sig `(x)` are generated. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L91-L97) + +
+
+
+# CompositionalNetworks.tr_count_greaterMethod. + + + + +```julia +tr_count_greater(i, x) +tr_count_greater(x) +tr_count_greater(x, X::AbstractVector) +``` + + +Count the number of elements greater than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L51-L58) + +
+
+
+# CompositionalNetworks.tr_count_l_leftMethod. + + + + +```julia +tr_count_l_left(i, x) +tr_count_l_left(x) +tr_count_l_left(x, X::AbstractVector) +``` + + +Count the number of elements to the left of and lesser than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L81-L88) + +
+
+
+# CompositionalNetworks.tr_count_l_paramMethod. + + + + +```julia +tr_count_l_param(i, x; param) +tr_count_l_param(x; param) +tr_count_l_param(x, X::AbstractVector; param) +``` + + +Count the number of elements lesser than `x[i] + param`. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L126-L133) + +
+
+
+# CompositionalNetworks.tr_count_l_rightMethod. + + + + +```julia +tr_count_l_right(i, x) +tr_count_l_right(x) +tr_count_l_right(x, X::AbstractVector) +``` + + +Count the number of elements to the right of and lesser than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L100-L107) + +
+
+
+# CompositionalNetworks.tr_count_lesserMethod. + + + + +```julia +tr_count_lesser(i, x) +tr_count_lesser(x) +tr_count_lesser(x, X::AbstractVector) +``` + + +Count the number of elements lesser than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L61-L68) + +
+
+
+# CompositionalNetworks.tr_identityMethod. + + + + +```julia +tr_identity(i, x) +tr_identity(x) +tr_identity(x, X::AbstractVector) +``` + + +Identity function. Already defined in Julia as `identity`, specialized for vectors. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L3-L10) + +
+
+
+# CompositionalNetworks.tr_in_unrolled_expansion_##225Method. + + + + +```julia +tr_in(tr, X, x, param) +``` + + +Application of an operation from the transformation layer. Used to generate more efficient code for all compositions. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L86-L90) + +
+
+
+# CompositionalNetworks.tr_param_minus_valMethod. + + + + +```julia +tr_param_minus_val(i, x; param) +tr_param_minus_val(x; param) +tr_param_minus_val(x, X::AbstractVector; param) +``` + + +Return the difference `param - x[i]` if positive, `0.0` otherwise. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L176-L183) + +
+
+
+# CompositionalNetworks.tr_val_minus_paramMethod. + + + + +```julia +tr_val_minus_param(i, x; param) +tr_val_minus_param(x; param) +tr_val_minus_param(x, X::AbstractVector; param) +``` + + +Return the difference `x[i] - param` if positive, `0.0` otherwise. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L166-L173) + +
+
+
+# CompositionalNetworks.transformation_layerFunction. + + + + +```julia +transformation_layer(param = false) +``` + + +Generate the layer of transformations functions of the ICN. Iff `param` value is true, also includes all the parametric transformations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L298-L301) + +
+
+
+# CompositionalNetworks.weights!Method. + + + + +```julia +weights!(icn, weights) +``` + + +Set the weights of an ICN with a `BitVector`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L71-L74) + +
+
+
+# CompositionalNetworks.weightsMethod. + + + + +```julia +weights(icn) +``` + + +Access the current set of weights of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L49-L52) + +
+
+
+# CompositionalNetworks.weights_biasMethod. + + + + +```julia +weights_bias(x) +``` + + +A metric that bias `x` towards operations with a lower bit. Do not affect the main metric. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L17-L20) + +
+
+
+# QUBOConstraints.AbstractOptimizerType. + + + + +```julia +AbstractOptimizer +``` + + +An abstract type (interface) used to learn QUBO matrices from constraints. Only a `train` method is required. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/learn.jl#L1-L5) + +
+
+
+# QUBOConstraints.QUBO_baseFunction. + + + + +```julia +QUBO_base(n, weight = 1) +``` + + +A basic QUBO matrix to ensure that binarized variables keep a valid encoding. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/base.jl#L1-L5) + +
+
+
+# QUBOConstraints.QUBO_linear_sumMethod. + + + + +```julia +QUBO_linear_sum(n, σ) +``` + + +One valid QUBO matrix given `n` variables and parameter `σ` for the linear sum constraint. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/handmade/linear_sum.jl#L1-L5) + +
+
+
+# QUBOConstraints.binarizeMethod. + + + + +```julia +binarize(x[, domain]; binarization = :one_hot) +``` + + +Binarize `x` following the `binarization` encoding. If `x` is a vector (instead of a number per say), `domain` is optional. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L12-L16) + +
+
+
+# QUBOConstraints.debinarizeMethod. + + + + +```julia +debinarize(x[, domain]; binarization = :one_hot) +``` + + +Transform a binary vector into a number or a set of number. If `domain` is not given, it will compute a default value based on `binarization` and `x`. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L35-L39) + +
+
+
+# QUBOConstraints.is_validFunction. + + + + +```julia +is_valid(x, encoding::Symbol = :none) +``` + + +Check if `x` has a valid format for `encoding`. + +For instance, if `encoding == :one_hot`, at most one bit of `x` can be set to 1. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L1-L7) + +
+
+
+# QUBOConstraints.trainMethod. + + + + +```julia +train(args...) +``` + + +Default `train` method for any AbstractOptimizer. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/learn.jl#L8-L12) + +
+
diff --git a/previews/PR50/.documenter/index-old.md b/previews/PR50/.documenter/index-old.md new file mode 100644 index 0000000..9186c45 --- /dev/null +++ b/previews/PR50/.documenter/index-old.md @@ -0,0 +1,54 @@ + +## JuliaConstraints + +JuliaConstraints is a collection of packages that help you solve constraint programming problems in Julia. Constraint programming involves modeling problems with constraints, such as "x > 5" or "x + y = 10", and finding solutions that satisfy all of the constraints. It is a part of the [JuMP ecosystem](https://jump.dev/) that focuses on constraint programming in Julia. + +The goal of packages in JuliaConstraints are two-fold: some of them provide a generic interface, others are solvers for CP models (either purely in Julia or wrapping). They make it easy to solve constraint-satisfaction problems (CSPs) and constraint-optimisation problems (COPs) in Julia using industry-standard solvers and mixed-integer solvers. +- [CBLS.jl](https://github.com/JuliaConstraints/CBLS.jl) is a high-level interface for CBLS solvers + +- [ConstraintProgrammingExtensions.jl](https://github.com/JuliaConstraints/ConstraintProgrammingExtensions.jl/) is a common low-level interface for CP solvers. + +- JuliaConstraints hosts several pure-Julia solvers: + +- JuliaConstraints provides wrappers for existing CP solvers: + - [Chuffed](https://github.com/JuliaConstraints/Chuffed.jl) + + - [CPLEX CP Optimizer](https://github.com/JuliaConstraints/CPLEXCP.jl) + + - [JaCoP](https://github.com/JuliaConstraints/JaCoP.jl) + + +- JuliaConstraints makes available packages to help write new CP solvers: + - [Constraints.jl](https://github.com/JuliaConstraints/Constraints.jl) supplies metadata about constraints + + - [ConstraintDomains.jl](https://github.com/JuliaConstraints/ConstraintDomains.jl) helps with storing the domain of variables + + - [LocalSearchSolvers.jl](https://github.com/JuliaConstraints/LocalSearchSolvers.jl) is a framework to build CBLS solvers + + +- JuliaConstraints holds repositories of CP models: + - [ConstraintModels.jl](https://github.com/JuliaConstraints/ConstraintModels.jl) + + + +Other packages for CP in Julia include: +- [ConstraintSolver.jl](https://github.com/Wikunia/ConstraintSolver.jl/), another pure-Julia CP solvers + +- [SeaPerl.jl](https://github.com/corail-research/SeaPearl.jl), a research CP solver implemented with reinforcement learning, in pure Julia + + +### Operational Research vs Constraint Programming {#Operational-Research-vs-Constraint-Programming} + +Operational research (OR) is a problem-solving approach that uses mathematical models, statistical analysis, and optimization techniques to help organizations make better decisions. OR is concerned with understanding and optimizing complex systems, such as supply chains, transportation networks, and manufacturing processes, to improve efficiency and reduce costs. + +On the other hand, constraint programming (CP) is a programming paradigm that focuses on solving problems with constraints. Constraints are conditions that must be satisfied for a solution to be valid. CP is often used to solve combinatorial problems, such as scheduling, routing, and allocation, where the search space of possible solutions is very large. + +So, while both OR and CP are concerned with solving complex problems, they approach the problem-solving process from different angles. OR typically uses mathematical models and optimization techniques to analyze and optimize existing systems, while CP focuses on finding valid solutions that satisfy a set of constraints. + +### Constraint-Based Local Search {#Constraint-Based-Local-Search} + +Constraint-based local search (CBLS) is a type of constraint programming solver that uses a heuristic search algorithm to find solutions to problems. It starts with an initial solution and tries to improve it by making small changes that satisfy the constraints. CBLS is especially useful for large and complex problems where finding an exact solution may take too much time or be impossible. + +In contrast, other constraint programming solvers use a variety of algorithms and techniques to find exact solutions to problems. These solvers try to find a solution that satisfies all of the constraints in the problem. They can be useful for smaller problems where finding an exact solution is feasible, or for problems that have a clear mathematical structure. + +In summary, CBLS is a type of constraint programming solver that uses a heuristic search algorithm to find good solutions, while other constraint programming solvers use various techniques to find exact solutions to problems. diff --git a/previews/PR50/.documenter/index.md b/previews/PR50/.documenter/index.md new file mode 100644 index 0000000..977d185 --- /dev/null +++ b/previews/PR50/.documenter/index.md @@ -0,0 +1,58 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: "Julia Constraints" + text: "Model Smoothly Decide Wisely" + tagline: A Toolkit for Constraint Programming + image: + src: /logo.png + alt: JuliaConstraints + actions: + - theme: brand + text: Constraint Programming ?! + link: /cp/intro + - theme: alt + text: View on Github + link: https://github.com/JuliaConstraints/JuliaConstraints.github.io + +features: + - icon: JuMP.jl + title: JuMP.jl + details: Model optimization problems via JuMP.jl! + link: "https://jump.dev/" + - icon: ToQUBO.jl + title: ToQUBO.jl + details: Convert and send optimization models to QUBO solvers! + link: "https://github.com/psrenergy/ToQUBO.jl" + - icon: Pluto.jl + title: Pluto.jl + details: Simple, reactive programming environment via Julia notebooks + link: "https://plutojl.org/" +--- + + +<p style="margin-bottom:2cm"></p> + +<div class="vp-doc" style="width:80%; margin:auto"> + +<h1>What is Julia Constraints? (chatGPTed atm)</h1> + +<p>The Julia Constraints organization is dedicated to advancing Constraint Programming within the Julia ecosystem, serving as a hub for resources that facilitate the creation, understanding, and solution of constraint programming problems. Our goal is to make Constraint Programming accessible and efficient for users at all levels of expertise, by providing a comprehensive suite of tools that integrate seamlessly with JuMP.jl, a popular Julia package for mathematical optimization.</p> + +<h2>Our offerings include:</h2> + +<h3>Core Packages:</h3> <p>A foundation of common packages (ConstraintCommons, ConstraintDomains, Constraints, ConstraintModels) that supply essential features for constraint programming, ensuring users have the basic tools necessary for their projects.</p> + +<h3>Learning and Translation Tools:</h3> <p>Advanced packages like CompositionalNetworks, QUBOConstraints, and ConstraintsTranslator bridge the gap between ease of modeling and computational efficiency. These tools learn from constraints and convert natural language problems into constraint programming solutions, requiring minimal input from the user beyond the model itself.</p> + +<h3>Solvers:</h3> <p>We provide a range of solvers, from native Julia solvers (LocalSearchSolvers) to interfaces with JuMP for external CP solvers, catering to various problem-solving needs.</p> + +<h3>MetaStrategist (Emerging Technology):</h3> <p>In its formative stages, MetaStrategist embodies our pioneering spirit. As a burgeoning meta-solving package, it aims to harness the strengths of CP and JuMP. Its vision is to formulate tailored strategies that consider the unique hardware and software resources at hand, offering a new horizon in problem-solving efficiency and adaptability.</p> + +<h3>Performance Checker (Community Resource):</h3> <p>PerfChecker.jl transcends its role within Julia Constraints, offering its capabilities to the broader Julia package ecosystem. This indispensable tool for cross-version performance checking not only safeguards the high efficiency and reliability of our packages but also serves the wider community. By facilitating clear and simple performance evaluations, PerfChecker.jl enhances both development and maintenance, contributing to the overall health and progress of Julia's growing library of resources.</p> + +<p>At Julia Constraints, our mission is to democratize Constraint Programming by providing robust, user-friendly tools that simplify the modeling process, enhance efficiency, and empower users to solve complex problems with ease.</p> + +</div> diff --git a/previews/PR50/.documenter/learning/aggregation.md b/previews/PR50/.documenter/learning/aggregation.md new file mode 100644 index 0000000..34359a2 --- /dev/null +++ b/previews/PR50/.documenter/learning/aggregation.md @@ -0,0 +1,64 @@ + +# Aggregation Layer {#Aggregation-Layer} + + + +Some text to describe the aggragation layer within usual ICNs. + +## List of aggregations {#List-of-aggregations} +
+# CompositionalNetworks.ag_sumFunction. + + + + +```julia +ag_sum(x) +``` + + +Aggregate through `+` a vector into a single scalar. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/aggregation.jl#L1-L4) + +
+
+
+# CompositionalNetworks.ag_count_positiveFunction. + + + + +```julia +ag_count_positive(x) +``` + + +Count the number of strictly positive elements of `x`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/aggregation.jl#L7-L10) + +
+
+ +## Layer generation {#Layer-generation} +
+# CompositionalNetworks.aggregation_layerFunction. + + + + +```julia +aggregation_layer() +``` + + +Generate the layer of aggregations of the ICN. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/aggregation.jl#L13-L16) + +
+
diff --git a/previews/PR50/.documenter/learning/arithmetic.md b/previews/PR50/.documenter/learning/arithmetic.md new file mode 100644 index 0000000..114919b --- /dev/null +++ b/previews/PR50/.documenter/learning/arithmetic.md @@ -0,0 +1,64 @@ + +# Arithmetic Layer {#Arithmetic-Layer} + + + +Some text to describe the arithmetic layer within usual ICNs. + +## List of arithmetic operations {#List-of-arithmetic-operations} +
+# CompositionalNetworks.ar_sumFunction. + + + + +```julia +ar_sum(x) +``` + + +Reduce `k = length(x)` vectors through sum to a single vector. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/arithmetic.jl#L1-L4) + +
+
+
+# CompositionalNetworks.ar_prodFunction. + + + + +```julia +ar_prod(x) +``` + + +Reduce `k = length(x)` vectors through product to a single vector. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/arithmetic.jl#L7-L10) + +
+
+ +## Layer generation {#Layer-generation} +
+# CompositionalNetworks.arithmetic_layerFunction. + + + + +```julia +arithmetic_layer() +``` + + +Generate the layer of arithmetic operations of the ICN. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/arithmetic.jl#L13-L16) + +
+
diff --git a/previews/PR50/.documenter/learning/comparison.md b/previews/PR50/.documenter/learning/comparison.md new file mode 100644 index 0000000..2c0152e --- /dev/null +++ b/previews/PR50/.documenter/learning/comparison.md @@ -0,0 +1,178 @@ + +# Comparison Layer {#Comparison-Layer} + + + +Some text to describe the comparison layer within usual ICNs. + +## List of comparisons {#List-of-comparisons} + +List the possible parameters and how it affects the comparison. + +### Non-parametric +
+# CompositionalNetworks.co_identityFunction. + + + + +```julia +co_identity(x) +``` + + +Identity function. Already defined in Julia as `identity`, specialized for scalars in the `comparison` layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L1-L4) + +
+
+ +::: warning Missing docstring. + +Missing docstring for `co_euclidian`. Check Documenter's build log for details. + +::: +
+# CompositionalNetworks.co_abs_diff_val_varsFunction. + + + + +```julia +co_abs_diff_val_vars(x; nvars) +``` + + +Return the absolute difference between `x` and the number of variables `nvars`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L41-L44) + +
+
+
+# CompositionalNetworks.co_val_minus_varsFunction. + + + + +```julia +co_val_minus_vars(x; nvars) +``` + + +Return the difference `x - nvars` if positive, `0.0` otherwise, where `nvars` denotes the numbers of variables. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L47-L50) + +
+
+
+# CompositionalNetworks.co_vars_minus_valFunction. + + + + +```julia +co_vars_minus_val(x; nvars) +``` + + +Return the difference `nvars - x` if positive, `0.0` otherwise, where `nvars` denotes the numbers of variables. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L54-L57) + +
+
+ +### Param: `:val` {#Param:-:val} +
+# CompositionalNetworks.co_abs_diff_val_paramFunction. + + + + +```julia +co_abs_diff_val_param(x; param) +``` + + +Return the absolute difference between `x` and `param`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L7-L10) + +
+
+
+# CompositionalNetworks.co_val_minus_paramFunction. + + + + +```julia +co_val_minus_param(x; param) +``` + + +Return the difference `x - param` if positive, `0.0` otherwise. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L13-L16) + +
+
+
+# CompositionalNetworks.co_param_minus_valFunction. + + + + +```julia +co_param_minus_val(x; param) +``` + + +Return the difference `param - x` if positive, `0.0` otherwise. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L19-L22) + +
+
+ +::: warning Missing docstring. + +Missing docstring for `co_euclidian_param`. Check Documenter's build log for details. + +::: + +### Layer generation {#Layer-generation} + +::: warning Missing docstring. + +Missing docstring for `make_comparisons`. Check Documenter's build log for details. + +::: +
+# CompositionalNetworks.comparison_layerFunction. + + + + +```julia +comparison_layer(param = false) +``` + + +Generate the layer of transformations functions of the ICN. Iff `param` value is set, also includes all the parametric comparison with that value. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L85-L88) + +
+
diff --git a/previews/PR50/.documenter/learning/compositional_networks.md b/previews/PR50/.documenter/learning/compositional_networks.md new file mode 100644 index 0000000..0bbb57c --- /dev/null +++ b/previews/PR50/.documenter/learning/compositional_networks.md @@ -0,0 +1,180 @@ + +# CompositionalNetworks.jl + + + +Documentation for `CompositionalNetworks.jl`. + +## Utilities +
+# CompositionalNetworks.map_tr!Function. + + + + +```julia +map_tr!(f, x, X, param) +``` + + +Return an anonymous function that applies `f` to all elements of `x` and store the result in `X`, with a parameter `param` (which is set to `nothing` for function with no parameter). + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L1-L4) + +
+
+
+# CompositionalNetworks.lazyFunction. + + + + +```julia +lazy(funcs::Function...) +``` + + +Generate methods extended to a vector instead of one of its components. A function `f` should have the following signature: `f(i::Int, x::V)`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L22-L25) + +
+
+
+# CompositionalNetworks.lazy_paramFunction. + + + + +```julia +lazy_param(funcs::Function...) +``` + + +Generate methods extended to a vector instead of one of its components. A function `f` should have the following signature: `f(i::Int, x::V; param)`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L36-L39) + +
+
+
+# CompositionalNetworks.as_bitvectorFunction. + + + + +```julia +as_bitvector(n::Int, max_n::Int = n) +``` + + +Convert an Int to a BitVector of minimal size (relatively to `max_n`). + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L48-L51) + +
+
+
+# CompositionalNetworks.as_intFunction. + + + + +```julia +as_int(v::AbstractVector) +``` + + +Convert a `BitVector` into an `Int`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L65-L68) + +
+
+
+# CompositionalNetworks.reduce_symbolsFunction. + + + + +```julia +reduce_symbols(symbols, sep) +``` + + +Produce a formatted string that separates the symbols by `sep`. Used internally for `show_composition`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L77-L80) + +
+
+ +::: warning Missing docstring. + +Missing docstring for `CompositionalNeworks.tr_in`. Check Documenter's build log for details. + +::: + +## Metrics +
+# CompositionalNetworks.hammingFunction. + + + + +```julia +hamming(x, X) +``` + + +Compute the hamming distance of `x` over a collection of solutions `X`, i.e. the minimal number of variables to switch in `x`to reach a solution. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L1-L4) + +
+
+
+# CompositionalNetworks.minkowskiFunction. + + + + +```julia +minkowski(x, X, p) +``` + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L7-L9) + +
+
+
+# CompositionalNetworks.manhattanFunction. + + + + +```julia +manhattan(x, X) +``` + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L12-L14) + +
+
+ +::: warning Missing docstring. + +Missing docstring for `weigths_bias`. Check Documenter's build log for details. + +::: diff --git a/previews/PR50/.documenter/learning/constraint_learning.md b/previews/PR50/.documenter/learning/constraint_learning.md new file mode 100644 index 0000000..94c64a6 --- /dev/null +++ b/previews/PR50/.documenter/learning/constraint_learning.md @@ -0,0 +1,508 @@ + +# ConstraintLearning.jl + +Documentation for `ConstraintLearning.jl`. +
+# ConstraintLearning.ICNConfigType. + + + + +```julia +struct ICNConfig{O <: ICNOptimizer} +``` + + +A structure to hold the metric and optimizer configurations used in learning the weights of an ICN. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/base.jl#L8-L12) + +
+
+
+# ConstraintLearning.ICNConfigMethod. + + + + +```julia +ICNConfig(; metric = :hamming, optimizer = ICNGeneticOptimizer()) +``` + + +Constructor for `ICNConfig`. Defaults to hamming metric using a genetic algorithm. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/genetic.jl#L150-L154) + +
+
+
+# ConstraintLearning.ICNGeneticOptimizerMethod. + + + + +```julia +ICNGeneticOptimizer(; kargs...) +``` + + +Default constructor to learn an ICN through a Genetic Algorithm. Default `kargs` TBW. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/genetic.jl#L111-L115) + +
+
+
+# ConstraintLearning.ICNLocalSearchOptimizerType. + + + + +```julia +ICNLocalSearchOptimizer(options = LocalSearchSolvers.Options()) +``` + + +Default constructor to learn an ICN through a CBLS solver. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/cbls.jl#L1-L5) + +
+
+
+# ConstraintLearning.ICNOptimizerType. + + + + +```julia +const ICNOptimizer = CompositionalNetworks.AbstractOptimizer +``` + + +An abstract type for optmizers defined to learn ICNs. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/base.jl#L1-L5) + +
+
+
+# ConstraintLearning.QUBOGradientOptimizerMethod. + + + + +```julia +QUBOGradientOptimizer(; kargs...) +``` + + +A QUBO optimizer based on gradient descent. Defaults TBW + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo/gradient.jl#L8-L12) + +
+
+
+# ConstraintLearning.QUBOOptimizerType. + + + + +```julia +const QUBOOptimizer = QUBOConstraints.AbstractOptimizer +``` + + +An abstract type for optimizers used to learn QUBO matrices from constraints. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo/base.jl#L1-L5) + +
+
+
+# CompositionalNetworks.optimize!Method. + + + + +```julia +CompositionalNetworks.optimize!(icn, solutions, non_sltns, dom_size, metric, optimizer::ICNGeneticOptimizer; parameters...) +``` + + +Extends the `optimize!` method to `ICNGeneticOptimizer`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/genetic.jl#L126-L130) + +
+
+
+# CompositionalNetworks.optimize!Method. + + + + +```julia +CompositionalNetworks.optimize!(icn, solutions, non_sltns, dom_size, metric, optimizer::ICNLocalSearchOptimizer; parameters...) +``` + + +Extends the `optimize!` method to `ICNLocalSearchOptimizer`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/cbls.jl#L37-L41) + +
+
+
+# ConstraintLearning._optimize!Method. + + + + +```julia +_optimize!(icn, X, X_sols; metric = hamming, pop_size = 200) +``` + + +Optimize and set the weights of an ICN with a given set of configuration `X` and solutions `X_sols`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/genetic.jl#L11-L14) + +
+
+
+# ConstraintLearning.domain_sizeMethod. + + + + +```julia +domain_size(ds::Number) +``` + + +Extends the domain_size function when `ds` is number (for dispatch purposes). + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/common.jl#L24-L28) + +
+
+
+# ConstraintLearning.generate_populationMethod. + + + + +```julia +generate_population(icn, pop_size +``` + + +Generate a pôpulation of weights (individuals) for the genetic algorithm weighting `icn`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/genetic.jl#L1-L4) + +
+
+
+# ConstraintLearning.icnMethod. + + + + +```julia +icn(X,X̅; kargs..., parameters...) +``` + + +TBW + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn.jl#L1-L5) + +
+
+
+# ConstraintLearning.lossMethod. + + + + +```julia +loss(x, y, Q) +``` + + +Loss of the prediction given by `Q`, a training set `y`, and a given configuration `x`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo/gradient.jl#L29-L33) + +
+
+
+# ConstraintLearning.make_dfMethod. + + + + +```julia +make_df(X, Q, penalty, binarization, domains) +``` + + +DataFrame arrangement to output some basic evaluation of a matrix `Q`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo/gradient.jl#L36-L40) + +
+
+
+# ConstraintLearning.make_set_penaltyMethod. + + + + +```julia +make_set_penalty(X, X̅, args...; kargs) +``` + + +Return a penalty function when the training set is already split into a pair of solutions `X` and non solutions `X̅`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/common.jl#L63-L67) + +
+
+
+# ConstraintLearning.make_training_setsMethod. + + + + +```julia +make_training_sets(X, penalty, args...) +``` + + +Return a pair of solutions and non solutions sets based on `X` and `penalty`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/common.jl#L31-L35) + +
+
+
+# ConstraintLearning.mutually_exclusiveMethod. + + + + +```julia +mutually_exclusive(layer, w) +``` + + +Constraint ensuring that `w` encode exclusive operations in `layer`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/cbls.jl#L12-L16) + +
+
+
+# ConstraintLearning.no_empty_layerMethod. + + + + +```julia +no_empty_layer(x; X = nothing) +``` + + +Constraint ensuring that at least one operation is selected. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/cbls.jl#L23-L27) + +
+
+
+# ConstraintLearning.optimize!Method. + + + + +```julia +optimize!(icn, X, X_sols, global_iter, local_iter; metric=hamming, popSize=100) +``` + + +Optimize and set the weights of an ICN with a given set of configuration `X` and solutions `X_sols`. The best weights among `global_iter` will be set. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/genetic.jl#L57-L60) + +
+
+
+# ConstraintLearning.parameter_specific_operationsMethod. + + + + +```julia +parameter_specific_operations(x; X = nothing) +``` + + +Constraint ensuring that at least one operation related to parameters is selected if the error function to be learned is parametric. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/icn/cbls.jl#L30-L34) + +
+
+
+# ConstraintLearning.predictMethod. + + + + +```julia +predict(x, Q) +``` + + +Return the predictions given by `Q` for a given configuration `x`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo/gradient.jl#L22-L26) + +
+
+
+# ConstraintLearning.preliminariesMethod. + + + + +```julia +preliminaries(args) +``` + + +Preliminaries to the training process in a `QUBOGradientOptimizer` run. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo/gradient.jl#L77-L81) + +
+
+
+# ConstraintLearning.quboFunction. + + + + +```julia +qubo(X,X̅; kargs..., parameters...) +``` + + +TBW + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo.jl#L1-L5) + +
+
+
+# ConstraintLearning.sub_eltypeMethod. + + + + +```julia +sub_eltype(X) +``` + + +Return the element type of of the first element of a collection. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/common.jl#L17-L21) + +
+
+
+# ConstraintLearning.train!Method. + + + + +```julia +train!(Q, X, penalty, η, precision, X_test, oversampling, binarization, domains) +``` + + +Training inner method. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo/gradient.jl#L98-L102) + +
+
+
+# ConstraintLearning.trainMethod. + + + + +```julia +train(X, penalty[, d]; optimizer = QUBOGradientOptimizer(), X_test = X) +``` + + +Learn a QUBO matrix on training set `X` for a constraint defined by `penalty` with optional domain information `d`. By default, it uses a `QUBOGradientOptimizer` and `X` as a testing set. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/qubo/gradient.jl#L127-L131) + +
+
+
+# ConstraintLearning.δMethod. + + + + +```julia +δ(X[, Y]; discrete = true) +``` + + +Compute the extrema over a collection `X``or a pair of collection`(X, Y)`. + + +[source](https://github.com/JuliaConstraints/ConstraintLearning.jl/blob/v0.1.7/src/common.jl#L1-L5) + +
+
diff --git a/previews/PR50/.documenter/learning/intro.md b/previews/PR50/.documenter/learning/intro.md new file mode 100644 index 0000000..b5e853e --- /dev/null +++ b/previews/PR50/.documenter/learning/intro.md @@ -0,0 +1,4 @@ + +# Learning about Constraints {#Learning-about-Constraints} + +About learning constraints related matters. diff --git a/previews/PR50/.documenter/learning/layers.md b/previews/PR50/.documenter/learning/layers.md new file mode 100644 index 0000000..e9875fa --- /dev/null +++ b/previews/PR50/.documenter/learning/layers.md @@ -0,0 +1,215 @@ + +# A layer structure for any ICN {#A-layer-structure-for-any-ICN} + + + +The `layer.jl` file defines a `Layer` structure and several associated functions for manipulating and interacting with this structure in the context of an Interpretable Compositional Network (ICN). + +The `Layer` structure is used to store a `LittleDict` of operations that can be selected during the learning phase of an ICN. Each layer can be exclusive, meaning only one operation can be selected at a time. This is particularly useful in the context of ICNs, which are used to learn alternative expressions for highly combinatorial functions, such as those found in Constraint-based Local Search solvers. +
+# CompositionalNetworks.LayerType. + + + + +```julia +Layer +``` + + +A structure to store a `LittleDict` of operations that can be selected during the learning phase of an ICN. If the layer is exclusive, only one operation can be selected at a time. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L1-L4) + +
+
+
+# CompositionalNetworks.functionsFunction. + + + + +```julia +functions(layer) +``` + + +Access the operations of a layer. The container is ordered. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L11-L14) + +
+
+
+# Base.lengthMethod. + + + + +```julia +length(layer) +``` + + +Return the number of operations in a layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L17-L20) + +
+
+
+# CompositionalNetworks.excluFunction. + + + + +```julia +exclu(layer) +``` + + +Return `true` if the layer has mutually exclusive operations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L23-L26) + +
+
+
+# CompositionalNetworks.symbolFunction. + + + + +```julia +symbol(layer, i) +``` + + +Return the i-th symbols of the operations in a given layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L29-L32) + +
+
+
+# CompositionalNetworks.nbits_excluFunction. + + + + +```julia +nbits_exclu(layer) +``` + + +Convert the length of an exclusive layer into a number of bits. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L35-L38) + +
+
+
+# CompositionalNetworks.show_layerFunction. + + + + +```julia +show_layer(layer) +``` + + +Return a string that contains the elements in a layer. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L41-L44) + +
+
+
+# CompositionalNetworks.selected_sizeFunction. + + + + +```julia +selected_size(layer, layer_weights) +``` + + +Return the number of operations selected by `layer_weights` in `layer`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L47-L50) + +
+
+
+# CompositionalNetworks.is_viableFunction. + + + + +```julia +is_viable(layer, w) +is_viable(icn) +is_viable(icn, w) +``` + + +Assert if a pair of layer/icn and weights compose a viable pattern. If no weights are given with an icn, it will check the current internal value. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L53-L58) + +
+
+
+# CompositionalNetworks.generate_inclusive_operationsFunction. + + + + +```julia +generate_inclusive_operations(predicate, bits) +generate_exclusive_operation(max_op_number) +``` + + +Generates the operations (weights) of a layer with inclusive/exclusive operations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L61-L65) + +
+
+
+# CompositionalNetworks.generate_exclusive_operationFunction. + + + + +```julia +generate_exclusive_operation(max_op_number) +``` + + +Generates the operations (weigths) of a layer with exclusive operations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layer.jl#L75-L78) + +
+
+ +::: warning Missing docstring. + +Missing docstring for `generate_weigths`. Check Documenter's build log for details. + +::: diff --git a/previews/PR50/.documenter/learning/qubo_constraints.md b/previews/PR50/.documenter/learning/qubo_constraints.md new file mode 100644 index 0000000..178fffe --- /dev/null +++ b/previews/PR50/.documenter/learning/qubo_constraints.md @@ -0,0 +1,44 @@ + +# Introduction to QUBOConstraints.jl {#Introduction-to-QUBOConstraints.jl} + +Introduction to `QUBOConstraints.jl`. + + + +## Basic features {#Basic-features} +
+# QUBOConstraints.QUBO_baseFunction. + + + + +```julia +QUBO_base(n, weight = 1) +``` + + +A basic QUBO matrix to ensure that binarized variables keep a valid encoding. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/base.jl#L1-L5) + +
+
+
+# QUBOConstraints.QUBO_linear_sumFunction. + + + + +```julia +QUBO_linear_sum(n, σ) +``` + + +One valid QUBO matrix given `n` variables and parameter `σ` for the linear sum constraint. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/handmade/linear_sum.jl#L1-L5) + +
+
diff --git a/previews/PR50/.documenter/learning/qubo_encoding.md b/previews/PR50/.documenter/learning/qubo_encoding.md new file mode 100644 index 0000000..49b3c19 --- /dev/null +++ b/previews/PR50/.documenter/learning/qubo_encoding.md @@ -0,0 +1,60 @@ + +# Encoding for QUBO programs {#Encoding-for-QUBO-programs} + + +
+# QUBOConstraints.is_validFunction. + + + + +```julia +is_valid(x, encoding::Symbol = :none) +``` + + +Check if `x` has a valid format for `encoding`. + +For instance, if `encoding == :one_hot`, at most one bit of `x` can be set to 1. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L1-L7) + +
+
+
+# QUBOConstraints.binarizeFunction. + + + + +```julia +binarize(x[, domain]; binarization = :one_hot) +``` + + +Binarize `x` following the `binarization` encoding. If `x` is a vector (instead of a number per say), `domain` is optional. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L12-L16) + +
+
+
+# QUBOConstraints.debinarizeFunction. + + + + +```julia +debinarize(x[, domain]; binarization = :one_hot) +``` + + +Transform a binary vector into a number or a set of number. If `domain` is not given, it will compute a default value based on `binarization` and `x`. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L35-L39) + +
+
diff --git a/previews/PR50/.documenter/learning/qubo_learning.md b/previews/PR50/.documenter/learning/qubo_learning.md new file mode 100644 index 0000000..b6bd1f9 --- /dev/null +++ b/previews/PR50/.documenter/learning/qubo_learning.md @@ -0,0 +1,171 @@ + +# Learning QUBO matrices {#Learning-QUBO-matrices} + + + +## Interface +
+# QUBOConstraints.AbstractOptimizerType. + + + + +```julia +AbstractOptimizer +``` + + +An abstract type (interface) used to learn QUBO matrices from constraints. Only a `train` method is required. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/learn.jl#L1-L5) + +
+
+
+# QUBOConstraints.trainFunction. + + + + +```julia +train(args...) +``` + + +Default `train` method for any AbstractOptimizer. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/learn.jl#L8-L12) + +
+
+ +## Examples with various optimizers {#Examples-with-various-optimizers} + +### Gradient Descent {#Gradient-Descent} + +```julia +struct GradientDescentOptimizer <: QUBOConstraints.AbstractOptimizer + binarization::Symbol + η::Float64 + precision::Int + oversampling::Bool +end + +function GradientDescentOptimizer(; + binarization = :one_hot, + η = .001, + precision = 5, + oversampling = false, +) + return GradientDescentOptimizer(binarization, η, precision, oversampling) +end + + +predict(x, Q) = transpose(x) * Q * x + +loss(x, y, Q) = (predict(x, Q) .-y).^2 + +function make_df(X, Q, penalty, binarization, domains) + df = DataFrame() + for (i,x) in enumerate(X) + if i == 1 + df = DataFrame(transpose(x), :auto) + else + push!(df, transpose(x)) + end + end + + dim = length(df[1,:]) + + if binarization == :none + df[!,:penalty] = map(r -> penalty(Vector(r)), eachrow(df)) + df[!,:predict] = map(r -> predict(Vector(r), Q), eachrow(df[:, 1:dim])) + else + df[!,:penalty] = map( + r -> penalty(binarize(Vector(r), domains; binarization)), + eachrow(df) + ) + df[!,:predict] = map( + r -> predict(binarize(Vector(r), domains; binarization), Q), + eachrow(df[:, 1:dim]) + ) + end + + min_false = minimum( + filter(:penalty => >(minimum(df[:,:penalty])), df)[:,:predict]; + init = typemax(Int) + ) + df[!,:shifted] = df[:,:predict] .- min_false + df[!,:accurate] = df[:, :penalty] .* df[:,:shifted] .≥ 0. + + return df +end + +function preliminaries(X, domains, binarization) + if binarization==:none + n = length(first(X)) + return X, zeros(n,n) + else + Y = map(x -> collect(binarize(x, domains; binarization)), X) + n = length(first(Y)) + return Y, zeros(n,n) + end +end + +function preliminaries(X, _) + n = length(first(X)) + return X, zeros(n,n) +end + +function train!(Q, X, penalty, η, precision, X_test, oversampling, binarization, domains) + θ = params(Q) + try + penalty(first(X)) + catch e + if isa(e, UndefKeywordError) + penalty = (x; dom_size = δ_extrema(Iterators.flatten(X)))-> penalty(x; dom_size) + else + throw(e) + end + end + for x in (oversampling ? oversample(X, penalty) : X) + grads = gradient(() -> loss(x, penalty(x), Q), θ) + Q .-= η * grads[Q] + end + + Q[:,:] = round.(precision*Q) + + df = make_df(X_test, Q, penalty, binarization, domains) + return pretty_table(describe(df[!, [:penalty, :predict, :shifted, :accurate]])) +end + +function train( + X, + penalty, + domains::Vector{D}; + optimizer = GradientDescentOptimizer(), + X_test = X, +) where {D <: DiscreteDomain} + Y, Q = preliminaries(X, domains, optimizer.binarization) + train!( + Q, Y, penalty, optimizer.η, optimizer.precision, X_test, + optimizer.oversampling, optimizer.binarization, domains + ) + return Q +end + +function train( + X, + penalty, + dom_stuff = nothing; + optimizer = GradientDescentOptimizer(), + X_test = X, +) + return train(X, penalty, to_domains(X, dom_stuff); optimizer, X_test) +end +``` + + +### Constraint-based Local Search {#Constraint-based-Local-Search} diff --git a/previews/PR50/.documenter/learning/transformation.md b/previews/PR50/.documenter/learning/transformation.md new file mode 100644 index 0000000..8276b65 --- /dev/null +++ b/previews/PR50/.documenter/learning/transformation.md @@ -0,0 +1,443 @@ + +# Transformations Layer {#Transformations-Layer} + + + +Some text to describe the transformation layer within usual ICNs. + +The implementation of the transformation relies heavily on the use of the lazy function (make a ref, open an issue to make `@lazy` macro in front of each transformation). + +## List of transformations {#List-of-transformations} + +List the possible parameters and how it affects the transformations. + +### Non-parametric +
+# CompositionalNetworks.tr_identityFunction. + + + + +```julia +tr_identity(i, x) +tr_identity(x) +tr_identity(x, X::AbstractVector) +``` + + +Identity function. Already defined in Julia as `identity`, specialized for vectors. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L3-L10) + +
+
+
+# CompositionalNetworks.tr_count_eqFunction. + + + + +```julia +tr_count_eq(i, x) +tr_count_eq(x) +tr_count_eq(x, X::AbstractVector) +``` + + +Count the number of elements equal to `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L16-L23) + +
+
+
+# CompositionalNetworks.tr_count_eq_rightFunction. + + + + +```julia +tr_count_eq_right(i, x) +tr_count_eq_right(x) +tr_count_eq_right(x, X::AbstractVector) +``` + + +Count the number of elements to the right of and equal to `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L26-L33) + +
+
+
+# CompositionalNetworks.tr_count_eq_leftFunction. + + + + +```julia +tr_count_eq_left(i, x) +tr_count_eq_left(x) +tr_count_eq_left(x, X::AbstractVector) +``` + + +Count the number of elements to the left of and equal to `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L36-L43) + +
+
+
+# CompositionalNetworks.tr_count_greaterFunction. + + + + +```julia +tr_count_greater(i, x) +tr_count_greater(x) +tr_count_greater(x, X::AbstractVector) +``` + + +Count the number of elements greater than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L51-L58) + +
+
+
+# CompositionalNetworks.tr_count_lesserFunction. + + + + +```julia +tr_count_lesser(i, x) +tr_count_lesser(x) +tr_count_lesser(x, X::AbstractVector) +``` + + +Count the number of elements lesser than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L61-L68) + +
+
+
+# CompositionalNetworks.tr_count_g_leftFunction. + + + + +```julia +tr_count_g_left(i, x) +tr_count_g_left(x) +tr_count_g_left(x, X::AbstractVector) +``` + + +Count the number of elements to the left of and greater than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L71-L78) + +
+
+
+# CompositionalNetworks.tr_count_g_rightFunction. + + + + +```julia +tr_count_g_right(i, x) +tr_count_g_right(x) +tr_count_g_right(x, X::AbstractVector) +``` + + +Count the number of elements to the right of and greater than `x[i]`. Extended method to vector with sig `(x)` are generated. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L91-L97) + +
+
+
+# CompositionalNetworks.tr_count_l_rightFunction. + + + + +```julia +tr_count_l_right(i, x) +tr_count_l_right(x) +tr_count_l_right(x, X::AbstractVector) +``` + + +Count the number of elements to the right of and lesser than `x[i]`. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L100-L107) + +
+
+
+# CompositionalNetworks.tr_contiguous_vals_minusFunction. + + + + +```julia +tr_contiguous_vals_minus(i, x) +tr_contiguous_vals_minus(x) +tr_contiguous_vals_minus(x, X::AbstractVector) +``` + + +Return the difference `x[i] - x[i + 1]` if positive, `0.0` otherwise. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L190-L197) + +
+
+
+# CompositionalNetworks.tr_contiguous_vals_minus_revFunction. + + + + +```julia +tr_contiguous_vals_minus_rev(i, x) +tr_contiguous_vals_minus_rev(x) +tr_contiguous_vals_minus_rev(x, X::AbstractVector) +``` + + +Return the difference `x[i + 1] - x[i]` if positive, `0.0` otherwise. Extended method to vector with sig `(x)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L201-L208) + +
+
+ +### Param: `:val` {#Param:-:val} +
+# CompositionalNetworks.tr_count_eq_paramFunction. + + + + +```julia +tr_count_eq_param(i, x; param) +tr_count_eq_param(x; param) +tr_count_eq_param(x, X::AbstractVector; param) +``` + + +Count the number of elements equal to `x[i] + param`. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L116-L123) + +
+
+
+# CompositionalNetworks.tr_count_l_paramFunction. + + + + +```julia +tr_count_l_param(i, x; param) +tr_count_l_param(x; param) +tr_count_l_param(x, X::AbstractVector; param) +``` + + +Count the number of elements lesser than `x[i] + param`. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L126-L133) + +
+
+
+# CompositionalNetworks.tr_count_g_paramFunction. + + + + +```julia +tr_count_g_param(i, x; param) +tr_count_g_param(x; param) +tr_count_g_param(x, X::AbstractVector; param) +``` + + +Count the number of elements greater than `x[i] + param`. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L136-L143) + +
+
+
+# CompositionalNetworks.tr_count_bounding_paramFunction. + + + + +```julia +tr_count_bounding_param(i, x; param) +tr_count_bounding_param(x; param) +tr_count_bounding_param(x, X::AbstractVector; param) +``` + + +Count the number of elements bounded (not strictly) by `x[i]` and `x[i] + param`. An extended method to vector with sig `(x, param)` is generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L151-L158) + +
+
+
+# CompositionalNetworks.tr_val_minus_paramFunction. + + + + +```julia +tr_val_minus_param(i, x; param) +tr_val_minus_param(x; param) +tr_val_minus_param(x, X::AbstractVector; param) +``` + + +Return the difference `x[i] - param` if positive, `0.0` otherwise. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L166-L173) + +
+
+
+# CompositionalNetworks.tr_param_minus_valFunction. + + + + +```julia +tr_param_minus_val(i, x; param) +tr_param_minus_val(x; param) +tr_param_minus_val(x, X::AbstractVector; param) +``` + + +Return the difference `param - x[i]` if positive, `0.0` otherwise. Extended method to vector with sig `(x, param)` are generated. When `X` is provided, the result is computed without allocations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L176-L183) + +
+
+ +### Layer generation {#Layer-generation} +
+# CompositionalNetworks.make_transformationsFunction. + + + + +```julia +make_transformations(param::Symbol) +``` + + +Generates a dictionary of transformation functions based on the specified parameterization. This function facilitates the creation of parametric layers for constraint transformations, allowing for flexible and dynamic constraint manipulation according to the needs of different constraint programming models. + +**Parameters** +- `param::Symbol`: Specifies the type of transformations to generate. It can be `:none` for basic transformations that do not depend on external parameters, or `:val` for transformations that operate with respect to a specific value parameter. + + +**Returns** +- `LittleDict{Symbol, Function}`: A dictionary mapping transformation names (`Symbol`) to their corresponding functions (`Function`). The functions encapsulate various types of transformations, such as counting, comparison, and contiguous value processing. + + +**Transformation Types** +- When `param` is `:none`, the following transformations are available: + - `:identity`: No transformation is applied. + + - `:count_eq`, `:count_eq_left`, `:count_eq_right`: Count equalities under different conditions. + + - `:count_greater`, `:count_lesser`: Count values greater or lesser than a threshold. + + - `:count_g_left`, `:count_l_left`, `:count_g_right`, `:count_l_right`: Count values with greater or lesser comparisons from different directions. + + - `:contiguous_vals_minus`, `:contiguous_vals_minus_rev`: Process contiguous values with subtraction in normal and reverse order. + + +- When `param` is `:val`, the transformations relate to operations involving a parameter value: + - `:count_eq_param`, `:count_l_param`, `:count_g_param`: Count equalities or comparisons against a parameter value. + + - `:count_bounding_param`: Count values bounding a parameter value. + + - `:val_minus_param`, `:param_minus_val`: Subtract a parameter value from values or vice versa. + + + +The function delegates to a version that uses `Val(param)` for dispatch, ensuring compile-time selection of the appropriate transformation set. + +**Examples** + +```julia +# Get basic transformations +basic_transforms = make_transformations(:none) + +# Apply an identity transformation +identity_result = basic_transforms[:identity](data) + +# Get value-based transformations +val_transforms = make_transformations(:val) + +# Apply a count equal to parameter transformation +count_eq_param_result = val_transforms[:count_eq_param](data, param) +``` + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L216-L262) + +
+
+
+# CompositionalNetworks.transformation_layerFunction. + + + + +```julia +transformation_layer(param = false) +``` + + +Generate the layer of transformations functions of the ICN. Iff `param` value is true, also includes all the parametric transformations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L298-L301) + +
+
diff --git a/previews/PR50/.documenter/meta/meta_strategist.md b/previews/PR50/.documenter/meta/meta_strategist.md new file mode 100644 index 0000000..bf12eab --- /dev/null +++ b/previews/PR50/.documenter/meta/meta_strategist.md @@ -0,0 +1,4 @@ + +# MetaStrategist.jl + +Documentation for `MetaStrategist.jl`. diff --git a/previews/PR50/.documenter/perf/api.md b/previews/PR50/.documenter/perf/api.md new file mode 100644 index 0000000..585274d --- /dev/null +++ b/previews/PR50/.documenter/perf/api.md @@ -0,0 +1,178 @@ + +# API + +Here's the API for PerfChecker.jl +
+# PerfChecker.arrange_breakingMethod. + + + + +Outputs the last breaking or next breaking version. + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/versions.jl#L56-L58) + +
+
+
+# PerfChecker.arrange_majorMethod. + + + + +Outputs the earlier or next major version. + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/versions.jl#L67-L69) + +
+
+
+# PerfChecker.arrange_patchesMethod. + + + + +Outputs the last patch or first patch of a version. + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/versions.jl#L35-L37) + +
+
+
+# PerfChecker.checkres_to_boxplotsFunction. + + + + +General Usage: Takes the output of a check macro, and creates a boxplot. + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/check.jl#L192-L195) + +
+
+
+# PerfChecker.checkres_to_pieFunction. + + + + +General Usage: Takes the output of a check macro as input, and creates a pie plot. Uses `table_to_pie` internally. + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/check.jl#L184-L187) + +
+
+
+# PerfChecker.checkres_to_scatterlinesFunction. + + + + +General Usage: Takes the output of a check macro as input, and creates a scatterlines plot. + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/check.jl#L178-L181) + +
+
+
+# PerfChecker.find_by_tagsMethod. + + + + +Usage: (Assuming you ran the 'Basic Example') + +``` +julia> find_by_tags([:example, :nice, :great], res) +``` + + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/checker_results.jl#L28-L34) + +
+
+
+# PerfChecker.get_pkg_versionsFunction. + + + + +Finds all versions of a package in all the installed registries and returns it as a vector. + +Example: + +```julia +julia> get_pkg_versions("ConstraintLearning") +7-element Vector{VersionNumber}: + v"0.1.4" + v"0.1.5" + v"0.1.0" + v"0.1.6" + v"0.1.1" + v"0.1.3" + v"0.1.2" +``` + + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/versions.jl#L1-L17) + +
+
+
+# PerfChecker.table_to_pieFunction. + + + + +General Usage: Takes a table generated via the check macro as input, and creates a pie plot. + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/check.jl#L172-L175) + +
+
+
+# PerfChecker.to_tableFunction. + + + + +General Usage: Returns a table from the output of the results of respective backends + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/check.jl#L198-L201) + +
+
+
+# PerfChecker.@checkMacro. + + + + +General usage: + +```julia +@check :name_of_backend config_dictionary begin + # the prelimnary code +end begin + # the actual code you want to do perf testing for +end +``` + + +Outputs a `CheckerResult` which can be used with other functions. + + +[source](https://github.com/JuliaConstraints/PerfChecker.jl/blob/v0.2.1/src/check.jl#L148-L158) + +
+
diff --git a/previews/PR50/.documenter/perf/benchmark_ext.md b/previews/PR50/.documenter/perf/benchmark_ext.md new file mode 100644 index 0000000..29fd4f2 --- /dev/null +++ b/previews/PR50/.documenter/perf/benchmark_ext.md @@ -0,0 +1,39 @@ + +# BenchmarkTools Extension {#BenchmarkTools-Extension} + +A benchmarking extension, based on `BenchmarkTools.jl`, has been interfaced with `PerfChecker.jl`. This section will provide some usage examples, documentation, and links to related notebooks. + +## Usage + +Like all other extensions, `BenchmarkTools` extension can be used in the following way: + +```julia +julia> using BenchmarkTools, PerfChecker + +julia> @check :benchmark Dict(:option1 => "value1", :option2 => "value2", :PATH => @__DIR__) begin + # the prelimnary code goes here + using Example +end begin + # the code you want to be benchmarked + Example.domath(10) # returns x + 5, 15 in this case. +end +``` + + +## Options + +Options specific to this backend with their default values are defined as: + +```julia +:threads => 1 +:track => "none" +:samples => BenchmarkTools.DEFAULT_PARAMETERS.samples +:seconds => BenchmarkTools.DEFAULT_PARAMETERS.seconds +:evals => BenchmarkTools.DEFAULT_PARAMETERS.evals +:overhead => BenchmarkTools.DEFAULT_PARAMETERS.overhead +:gctrial => BenchmarkTools.DEFAULT_PARAMETERS.gctrial +:gcsample => BenchmarkTools.DEFAULT_PARAMETERS.gcsample +:time_tolerance => BenchmarkTools.DEFAULT_PARAMETERS.time_tolerance +:memory_tolerance => BenchmarkTools.DEFAULT_PARAMETERS.memory_tolerance +``` + diff --git a/previews/PR50/.documenter/perf/chairmarks_ext.md b/previews/PR50/.documenter/perf/chairmarks_ext.md new file mode 100644 index 0000000..2f39f82 --- /dev/null +++ b/previews/PR50/.documenter/perf/chairmarks_ext.md @@ -0,0 +1,35 @@ + +# Chairmarks Extension {#Chairmarks-Extension} + +A benchmarking extension, based on `Chairmarks.jl`, has been interfaced with `PerfChecker.jl`. This section will provide some usage examples, documentation, and links to related notebooks. + +## Usage + +Like all other extensions, `BenchmarkTools` extension can be used in the following way: + +```julia +julia> using Chairmarks, PerfChecker + +julia> @check :chairmark Dict(:option1 => "value1", :option2 => "value2", :PATH => @__DIR__) begin + # the prelimnary code goes here + using Example +end begin + # the code you want to be benchmarked + Example.domath(10) # returns x + 5, 15 in this case. +end +``` + + +## Options + +Options specific to this backend with their default values are defined as: + +```julia +:threads => 1 +:track => "none" +:evals => nothing +:seconds => 1, +:samples => nothing +:gc => true +``` + diff --git a/previews/PR50/.documenter/perf/perf_checker.md b/previews/PR50/.documenter/perf/perf_checker.md new file mode 100644 index 0000000..e7fe938 --- /dev/null +++ b/previews/PR50/.documenter/perf/perf_checker.md @@ -0,0 +1,65 @@ + +# PerfChecker.jl + +PerfChecker.jl is a package designed for package authors to easily performance test their packages. To achieve that, it provides the follwing features: +- The main macro `@check`, which provides an easy-to-use interface over various interfaces, configurable for various backends via a dictionary. + +- (WIP) A CI for reproducible performance testing. + +- Visualization of different metrics from `@check` using Makie.jl + + +## Usage + +The primary usage of PerfChecker.jl looks like this: + +```julia + using PerfChecker + # optional using custom backend like BenchmarkTools, Chairmark etc + config = Dict(:option1 => "value1", :option2 => :value2) + + results = @check :name_of_backend config begin + # preparatory code goes here + end begin + # the code block to be performance tested goes here + end + + # Visualization of the results + using Makie + checkres_to_scatterlines(results) +``` + + +The config dictionary can take many options, depending on the backend. + +Some of the commonly used options are: +- `:PATH` => The path where to the default environment of julia when creating a new process. + +- `:pkgs` => A list of versions to test performance for. Its defined as the `Tuple`, `(name::String, option::Symbol, versions::Vector{VersionNumber}, last_or_first::Bool)` Can be given as follows: + - `name` is the name of the package. + + - `option` is one of the 5 symbols: + - `:patches`: last patch or first patch of a version + + - `:breaking`: last breaking or next breaking version + + - `:major`: previous or next major version + + - `:minor`: previous or next minor version + + - `:custom`: custom version numbers (provide any boolean value for `last_or_first` in this case as it doesn't matter) + + + - `versions`: The input for the provided `option` + + - `last_or_first`: Input for the provided `option` + + +- `:tags` => A list of tags (a vector of symbols) to easily tag performance tests. + +- `:devops` => Giving a custom input to `Pkg.develop`. Intended to be used to test performance of a local development branch of a pacakge with previous versions. Often can be used as simply as `:devops => "MyPackageName"` + +- `:threads` => An integer to select the number of threads to start Julia with. + + +Checkout the documentation of the other backends for more default options and the default values. diff --git a/previews/PR50/.documenter/perf/perf_interface.md b/previews/PR50/.documenter/perf/perf_interface.md new file mode 100644 index 0000000..9af3dc2 --- /dev/null +++ b/previews/PR50/.documenter/perf/perf_interface.md @@ -0,0 +1,118 @@ + +# Extending PerfChecker {#Extending-PerfChecker} + +PerfChecker was build as an easy to extend interface. A good reference example for this is the Chairmarks extension. + +Extending PerfChecker works via PkgExtensions feature in Julia. There are 6 essential functions that need to be extended inside the Pkg extension. Each extension has a keyword symbol for it, which users can input to use the extension. + +## The Default Options {#The-Default-Options} + +Method to be overloaded: `PerfChecker.default_options(::Val{:myperfextension})::Dict` + +PerfChecker works via a config dictionary. Users can populate this dictionary with options and provide it to the main `check` macro to customize the performance testing to their liking. + +For Chairmarks.jl, it looks like this: + +```julia +function PerfChecker.default_options(::Val{:chairmark}) + return Dict( + :threads => 1, + :track => "none", + :evals => nothing, + :seconds => 1, + :samples => nothing, + :gc => true + ) +end +``` + + +## Package initialization {#Package-initialization} + +Method to be overloaded: `PerfChecker.initpkgs(::Val{:myperfextension})::Expr` + +This method is plainly to load the main package(s) associated with the custom backend. In case of Chairmarks.jl, it looks like this: + +```julia +PerfChecker.initpkgs(::Val{:chairmark}) = quote + using Chairmarks +end +``` + + +## Preparatory Code: {#Preparatory-Code:} + +Method to be overloaded: `PerfChecker.prep(config_dict::Dict, block::Expr, ::Val{:myperfextension})::Expr` + +This method exists to run arbitrary "preparatory" code (represented by `block` parameter here) before running the code to be performance tested for. + +The output from here are stored inside the `:prep_result` key of the configuration dictionary. + +Example for Chairmarks.jl: + +```julia +PerfChecker.prep(::Dict, block::Expr, ::Val{:chairmark}) = quote + $block + nothing +end +``` + + +This just runs the code in `block` provided by the user. + +## Main Code to be Performance Tested {#Main-Code-to-be-Performance-Tested} + +Method to be overloaded: `PerfChecker.check(config_dict::Dict, block::Expr, ::Val{:myperfextension})::Expr`. + +Runs the appropriate code to run the performance testing on user's code. For Chairmarks.jl, it looks like this: + +```julia +function PerfChecker.check(d::Dict, block::Expr, ::Val{:chairmark}) + quote + d = $d + return @be $block evals=d[:evals] seconds=d[:seconds] samples=d[:samples] gc=d[:gc] + end +end +``` + + +The output from here are stored inside the `:check_result` key of the configuration dictionary. + +## Post Performance Testing Code {#Post-Performance-Testing-Code} + +Method to be overloaded: `PerfChecker.post(config_dict::Dict, ::Val{:myperfextension})` + +The code to be run after the performance testing is done. The output from here is converted into a table via the `to_table` method overloading. + +In the case of Chairmarks.jl: + +```julia +PerfChecker.post(d::Dict, ::Val{:chairmark}) = d[:check_result] +``` + + +## Converting the result into a Table {#Converting-the-result-into-a-Table} + +Method to be overloaded: `PerfChecker.to_table` + +Convert the output from `post` function into an appropriate table. + +In the case of Chairmarks.jl + +```julia +function PerfChecker.to_table(chair::Chairmarks.Benchmark) + l = length(chair.samples) + times = [chair.samples[i].time for i in 1:l] + gctimes = [chair.samples[i].gc_fraction for i in 1:l] + bytes = [chair.samples[i].bytes for i in 1:l] + allocs = [chair.samples[i].allocs for i in 1:l] + return Table(times = times, gctimes = gctimes, bytes = bytes, allocs = allocs) +end +``` + + + +--- + + +There are also other functions that can be overloaded, mostly related to plotting but these are the basic functions to extend PerfChecker for a custom backend. diff --git a/previews/PR50/.documenter/perf/tutorial.md b/previews/PR50/.documenter/perf/tutorial.md new file mode 100644 index 0000000..73c4a2a --- /dev/null +++ b/previews/PR50/.documenter/perf/tutorial.md @@ -0,0 +1,71 @@ + +# Tutorial + +Taken from PerfChecker.jl examples, this is a guide for performance testing of PatterFolds.jl package using Chairmarks.jl + +Using PerfChecker.jl requires an environment with the dependencies present in it. + +The actual script looks like this: + +```julia +using PerfChecker, Chairmarks, CairoMakie + +d = Dict(:path => @__DIR__, :evals => 10, :samples => 1000, + :seconds => 100, :tags => [:patterns, :intervals], + :pkgs => ( + "PatternFolds", :custom, [v"0.2.0", v"0.2.1", v"0.2.2", v"0.2.3", v"0.2.4"], true), + :devops => "PatternFolds") + +x = @check :chairmark d begin + using PatternFolds +end begin + # Intervals + itv = Interval{Open, Closed}(0.0, 1.0) + i = IntervalsFold(itv, 2.0, 1000) + + unfold(i) + collect(i) + reverse(collect(i)) + + # Vectors + vf = make_vector_fold([0, 1], 2, 1000) + + unfold(vf) + collect(vf) + reverse(collect(vf)) + + rand(vf, 1000) + + return nothing +end + +mkpath(joinpath(@__DIR__, "visuals")) + +c = checkres_to_scatterlines(x, Val(:chairmark)) +save(joinpath(@__DIR__, "visuals", "chair_evolution.png"), c) + +for kwarg in [:times, :gctimes, :bytes, :allocs] + c2 = checkres_to_boxplots(x, Val(:chairmark); kwarg) + save(joinpath(@__DIR__, "visuals", "chair_boxplots_$kwarg.png"), c2) +end +``` + + +`d` here is the configuration dictionary. `x` stores the results from performance testing + +The code below the macro call is for plotting and storing the plots. It creates the visuals folder and stores the following plots in the folder: + +Boxplots from Chairmarks for allocations: + +chair_boxplots + + +Boxplots from Chairmarks for times: + +chair_times + + +Evolution of different metrics across versions according to Chairmarks: + +chair_evolution + diff --git a/previews/PR50/.documenter/public/JuMP-logo-dark.png b/previews/PR50/.documenter/public/JuMP-logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..23a0862739ac7d2b789882396eb811530bd7b065 GIT binary patch literal 3318 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 literal 0 HcmV?d00001 diff --git a/previews/PR50/.documenter/public/logo.png b/previews/PR50/.documenter/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4a1302eacc6c702423c1d41d64283fb33c8e5646 GIT binary patch literal 60313 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 Ss?rev0000)L|G5#-?`f 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 taH7`j$<@}-cf@c31E# literal 0 HcmV?d00001 diff --git a/previews/PR50/.documenter/public_api.md b/previews/PR50/.documenter/public_api.md new file mode 100644 index 0000000..884078a --- /dev/null +++ b/previews/PR50/.documenter/public_api.md @@ -0,0 +1,1480 @@ + +# Public API {#Public-API} + +
+
+# ConstraintCommons.MDDType. + + + + +```julia +MDD{S,T} <: AbstractMultivaluedDecisionDiagram +``` + + +A minimal implementation of a multivalued decision diagram structure. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/diagrams.jl#L9-L13) + +
+
+
+# ConstraintCommons.acceptMethod. + + + + +```julia +accept(a::Union{Automaton, MDD}, w) +``` + + +Return `true` if `a` accepts the word `w` and `false` otherwise. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L29-L33) + +
+
+
+# ConstraintCommons.consinMethod. + + + + +```julia +Base.in(::Any, ::Nothing) +``` + + +Extends `Base.in` (or `∈`) when the set is `nothing`. Returns `false`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/nothing.jl#L1-L5) + +
+
+
+# ConstraintCommons.extract_parametersMethod. + + + + +```julia +extract_parameters(m::Union{Method, Function}; parameters) +``` + + +Extracts the intersection between the `kargs` of `m` and `parameters` (defaults to `USUAL_CONSTRAINT_PARAMETERS`). + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/parameters.jl#L21-L25) + +
+
+
+# ConstraintCommons.incsert!Function. + + + + +```julia +incsert!(d::Union{AbstractDict, AbstractDictionary}, ind, val = 1) +``` + + +Increase or insert a counter in a dictionary-based collection. The counter insertion defaults to `val = 1`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/dictionaries.jl#L2-L6) + +
+
+
+# ConstraintCommons.oversampleMethod. + + + + +```julia +oversample(X, f) +``` + + +Oversample elements of `X` until the boolean function `f` has as many `true` and `false` configurations. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/sampling.jl#L1-L5) + +
+
+
+# ConstraintCommons.symconFunction. + + + + +```julia +Base.:*(s1::Symbol, s2::Symbol, connector::AbstractString="_") +``` + + +Extends `*` to `Symbol`s multiplication by connecting the symbols by an `_`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/symbols.jl#L1-L5) + +
+
+
+# ConstraintCommons.δ_extremaMethod. + + + + +```julia +δ_extrema(X...) +``` + + +Compute both the difference between the maximum and the minimum of over all the collections of `X`. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/extrema.jl#L1-L4) + +
+
+
+# ConstraintDomains.AbstractDomainType. + + + + +```julia +AbstractDomain +``` + + +An abstract super type for any domain type. A domain type `D <: AbstractDomain` must implement the following methods to properly interface `AbstractDomain`. +- `Base.∈(val, ::D)` + +- `Base.rand(::D)` + +- `Base.length(::D)` that is the number of elements in a discrete domain, and the distance between bounds or similar for a continuous domain + + +Additionally, if the domain is used in a dynamic context, it can extend +- `add!(::D, args)` + +- `delete!(::D, args)` + + +where `args` depends on `D`'s structure + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L1-L11) + +
+
+
+# ConstraintDomains.ContinuousDomainType. + + + + +```julia +ContinuousDomain{T <: Real} <: AbstractDomain +``` + + +An abstract supertype for all continuous domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L1-L4) + +
+
+
+# ConstraintDomains.DiscreteDomainType. + + + + +```julia +DiscreteDomain{T <: Number} <: AbstractDomain +``` + + +An abstract supertype for discrete domains (set, range). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L1-L4) + +
+
+
+# ConstraintDomains.ExploreSettingsMethod. + + + + +```julia +ExploreSettings( + domains; + complete_search_limit = 10^6, + max_samplings = sum(domain_size, domains), + search = :flexible, + solutions_limit = floor(Int, sqrt(max_samplings)), +) +``` + + +Settings for the exploration of a search space composed by a collection of domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/explore.jl#L8-L18) + +
+
+
+# ConstraintDomains.RangeDomainType. + + + + +```julia +RangeDomain +``` + + +A discrete domain defined by a `range <: AbstractRange{Real}`. As ranges are immutable in Julia, changes in `RangeDomain` must use `set_domain!`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L16-L19) + +
+
+
+# Base.delete!Method. + + + + +```julia +Base.delete!(d::SetDomain, value)(d::SetDomain, value) +``` + + +Delete `value` from the list of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L76-L79) + +
+
+
+# ConstraintDomains.add!Method. + + + + +```julia +add!(d::SetDomain, value) +``` + + +Add `value` to the list of points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L70-L73) + +
+
+
+# ConstraintDomains.domainMethod. + + + + +```julia +domain(values) +domain(range::R) where {T <: Real, R <: AbstractRange{T}} +``` + + +Construct either a `SetDomain` or a `RangeDomain``. + +```julia +d1 = domain(1:5) +d2 = domain([53.69, 89.2, 0.12]) +d3 = domain([2//3, 89//123]) +d4 = domain(4.3) +d5 = domain(1,42,86.9) +``` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L31-L42) + +
+
+
+# ConstraintDomains.domainMethod. + + + + +```julia +domain() +``` + + +Construct an `EmptyDomain`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L20-L23) + +
+
+
+# ConstraintDomains.domainMethod. + + + + +```julia +domain(a::Tuple{T, Bool}, b::Tuple{T, Bool}) where {T <: Real} +domain(intervals::Vector{Tuple{Tuple{T, Bool},Tuple{T, Bool}}}) where {T <: Real} +``` + + +Construct a domain of continuous interval(s). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L15-L19) + +
+
+
+# ConstraintDomains.domain_sizeMethod. + + + + +```julia +domain_size(itv::Intervals) +``` + + +Return the difference between the highest and lowest values in `itv`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L61-L64) + +
+
+
+# ConstraintDomains.domain_sizeMethod. + + + + +```julia +domain_size(d <: AbstractDomain) +``` + + +Fallback method for `domain_size(d)` that return `length(d)`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L46-L49) + +
+
+
+# ConstraintDomains.domain_sizeMethod. + + + + +```julia +domain_size(d::D) where D <: DiscreteDomain +``` + + +Return the maximum distance between two points in `d`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L64-L67) + +
+
+
+# ConstraintDomains.exploreMethod. + + + + +```julia +explore(domains, concept, param = nothing; search_limit = 1000, solutions_limit = 100) +``` + + +Search (a part of) a search space and returns a pair of vector of configurations: `(solutions, non_solutions)`. If the search space size is over `search_limit`, then both `solutions` and `non_solutions` are limited to `solutions_limit`. + +Beware that if the density of the solutions in the search space is low, `solutions_limit` needs to be reduced. This process will be automatic in the future (simple reinforcement learning). + +**Arguments:** +- `domains`: a collection of domains + +- `concept`: the concept of the targeted constraint + +- `param`: an optional parameter of the constraint + +- `sol_number`: the required number of solutions (half of the number of configurations), default to `100` + + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/explore.jl#L66-L78) + +
+
+
+# ConstraintDomains.generate_parametersMethod. + + + + +```julia +generate_parameters(d<:AbstractDomain, param) +``` + + +Generates random parameters based on the domain `d` and the kind of parameters `param`. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/parameters.jl#L128-L132) + +
+
+
+# ConstraintDomains.get_domainMethod. + + + + +```julia +get_domain(::AbstractDomain) +``` + + +Access the internal structure of any domain type. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L52-L55) + +
+
+
+# ConstraintDomains.intersect_domainsMethod. + + + + +```julia +intersect_domains(d₁, d₂) +``` + + +Compute the intersections of two domains. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/continuous.jl#L72-L76) + +
+
+
+# ConstraintDomains.merge_domainsMethod. + + + + +```julia +merge_domains(d₁::AbstractDomain, d₂::AbstractDomain) +``` + + +Merge two domains of same nature (discrete/contiuous). + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/discrete.jl#L83-L87) + +
+
+
+# ConstraintDomains.to_domainsMethod. + + + + +```julia +to_domains(args...) +``` + + +Convert various arguments into valid domains format. + + +[source](https://github.com/JuliaConstraints/ConstraintDomains.jl/blob/v0.3.10/src/common.jl#L58-L62) + +
+
+
+# Constraints.USUAL_CONSTRAINTSConstant. + + + + +```julia +USUAL_CONSTRAINTS::Dict +``` + + +Dictionary that contains all the usual constraints defined in Constraint.jl. It is based on XCSP3-core specifications available at https://arxiv.org/abs/2009.00514 + +Adding a new constraint is as simple as defining a new function with the same name as the constraint and using the `@usual` macro to define it. The macro will take care of adding the new constraint to the `USUAL_CONSTRAINTS` dictionary. + +**Example** + +```julia +@usual concept_all_different(x; vals=nothing) = xcsp_all_different(list=x, except=vals) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L1-L11) + +
+
+
+# Constraints.USUAL_SYMMETRIESConstant. + + + + +```julia +USUAL_SYMMETRIES +``` + + +A Dictionary that contains the function to apply for each symmetry to avoid searching a whole space. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L1-L4) + +
+
+
+# Constraints.ConstraintType. + + + + +```julia +Constraint +``` + + +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 assignments. Return `0.0` if the constraint is satisfied, and a strictly positive real otherwise. + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L7-L12) + +
+
+
+# ConstraintCommons.extract_parametersFunction. + + + + +```julia +extract_parameters(s::Symbol, constraints_dict=USUAL_CONSTRAINTS; parameters=ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS) +``` + + +Return the parameters of the constraint `s` in `constraints_dict`. + +**Arguments** +- `s::Symbol`: the constraint name. + +- `constraints_dict::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + +- `parameters::Vector{Symbol}`: vector of parameters. Default is `ConstraintCommons.USUAL_CONSTRAINT_PARAMETERS`. + + +**Example** + +```julia +extract_parameters(:all_different) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L44-L58) + +
+
+
+# Constraints.argsMethod. + + + + +```julia +args(c::Constraint) +``` + + +Return the expected length restriction of the arguments in a constraint `c`. The value `nothing` indicates that any strictly positive number of value is accepted. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L62-L65) + +
+
+
+# Constraints.conceptMethod. + + + + +```julia +concept(c::Constraint) +``` + + +Return the concept (function) of constraint `c`. concept(c::Constraint, x...; param = nothing) Apply the concept of `c` to values `x` and optionally `param`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L40-L45) + +
+
+
+# Constraints.conceptMethod. + + + + +```julia +concept(s::Symbol, args...; kargs...) +``` + + +Return the concept of the constraint `s` applied to `args` and `kargs`. This is a shortcut for `concept(USUAL_CONSTRAINTS[s])(args...; kargs...)`. + +**Arguments** +- `s::Symbol`: the constraint name. + +- `args...`: the arguments to apply the concept to. + +- `kargs...`: the keyword arguments to apply the concept to. + + +**Example** + +```julia +concept(:all_different, [1, 2, 3]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L221-L235) + +
+
+
+# Constraints.constraints_descriptionsFunction. + + + + +```julia +constraints_descriptions(C=USUAL_CONSTRAINTS) +``` + + +Return a pretty table with the descriptions of the constraints in `C`. + +**Arguments** +- `C::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + + +**Example** + +```julia +constraints_descriptions() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L180-L192) + +
+
+
+# Constraints.constraints_parametersFunction. + + + + +```julia +constraints_parameters(C=USUAL_CONSTRAINTS) +``` + + +Return a pretty table with the parameters of the constraints in `C`. + +**Arguments** +- `C::Dict{Symbol,Constraint}`: dictionary of constraints. Default is `USUAL_CONSTRAINTS`. + + +**Example** + +```julia +constraints_parameters() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L127-L139) + +
+
+
+# Constraints.describeFunction. + + + + +```julia +describe(constraints::Dict{Symbol,Constraint}=USUAL_CONSTRAINTS; width=150) +``` + + +Return a pretty table with the description of the constraints in `constraints`. + +**Arguments** +- `constraints::Dict{Symbol,Constraint}`: dictionary of constraints to describe. Default is `USUAL_CONSTRAINTS`. + +- `width::Int`: width of the table. + + +**Example** + +```julia +describe() +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/usual_constraints.jl#L14-L27) + +
+
+
+# Constraints.error_fMethod. + + + + +```julia +error_f(c::Constraint) +``` + + +Return the error function of constraint `c`. error_f(c::Constraint, x; param = nothing) Apply the error function of `c` to values `x` and optionally `param`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L51-L56) + +
+
+
+# Constraints.params_lengthMethod. + + + + +```julia +params_length(c::Constraint) +``` + + +Return the expected length restriction of the arguments in a constraint `c`. The value `nothing` indicates that any strictly positive number of parameters is accepted. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L68-L71) + +
+
+
+# Constraints.symmetriesMethod. + + + + +```julia +symmetries(c::Constraint) +``` + + +Return the list of symmetries of `c`. + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraint.jl#L74-L77) + +
+
+
+# CompositionalNetworks.CompositionMethod. + + + + +```julia +Composition(f::F, symbols) where {F<:Function} +``` + + +Construct a `Composition`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L12-L16) + +
+
+
+# CompositionalNetworks.CompositionType. + + + + +```julia +struct Composition{F<:Function} +``` + + +Store the all the information of a composition learned by an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L1-L5) + +
+
+
+# CompositionalNetworks.ICNType. + + + + +```julia +ICN(; nvars, dom_size, param, transformation, arithmetic, aggregation, comparison) +``` + + +Construct an Interpretable Compositional Network, with the following arguments: +- `nvars`: number of variable in the constraint + +- `dom_size: maximum domain size of any variable in the constraint` + +- `param`: optional parameter (default to `nothing`) + +- `transformation`: a transformation layer (optional) + +- `arithmetic`: a arithmetic layer (optional) + +- `aggregation`: a aggregation layer (optional) + +- `comparison`: a comparison layer (optional) + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L1-L11) + +
+
+
+# CompositionalNetworks.aggregation_layerMethod. + + + + +```julia +aggregation_layer() +``` + + +Generate the layer of aggregations of the ICN. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/aggregation.jl#L13-L16) + +
+
+
+# CompositionalNetworks.arithmetic_layerMethod. + + + + +```julia +arithmetic_layer() +``` + + +Generate the layer of arithmetic operations of the ICN. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/arithmetic.jl#L13-L16) + +
+
+
+# CompositionalNetworks.codeFunction. + + + + +```julia +code(c::Composition, lang=:maths; name="composition") +``` + + +Access the code of a composition `c` in a given language `lang`. The name of the generated method is optional. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L22-L26) + +
+
+
+# CompositionalNetworks.comparison_layerFunction. + + + + +```julia +comparison_layer(param = false) +``` + + +Generate the layer of transformations functions of the ICN. Iff `param` value is set, also includes all the parametric comparison with that value. The operations are mutually exclusive, that is only one will be selected. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/comparison.jl#L85-L88) + +
+
+
+# CompositionalNetworks.composeFunction. + + + + +```julia +compose(icn, weights=nothing) +``` + + +Return a function composed by some of the operations of a given ICN. Can be applied to any vector of variables. If `weights` are given, will assign to `icn`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L45-L48) + +
+
+
+# CompositionalNetworks.compose_to_file!Method. + + + + +```julia +compose_to_file!(concept, name, path; domains, param = nothing, language = :Julia, search = :complete, global_iter = 10, local_iter = 100, metric = hamming, popSize = 200) +``` + + +Explore, learn and compose a function and write it to a file. + +**Arguments:** +- `concept`: the concept to learn + +- `name`: the name to give to the constraint + +- `path`: path of the output file + + +**Keywords arguments:** +- `domains`: domains that defines the search space + +- `param`: an optional parameter of the constraint + +- `language`: the language to export to, default to `:julia` + +- `search`: either `:partial` or `:complete` search + +- `global_iter`: number of learning iteration + +- `local_iter`: number of generation in the genetic algorithm + +- `metric`: the metric to measure the distance between a configuration and known solutions + +- `popSize`: size of the population in the genetic algorithm + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/learn.jl#L77-L95) + +
+
+
+# CompositionalNetworks.compositionMethod. + + + + +```julia +composition(c::Composition) +``` + + +Access the actual method of an ICN composition `c`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L31-L35) + +
+
+
+# CompositionalNetworks.composition_to_file!Function. + + + + +```julia +composition_to_file!(c::Composition, path, name, language=:Julia) +``` + + +Write the composition code in a given `language` into a file at `path`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L97-L101) + +
+
+
+# CompositionalNetworks.explore_learn_composeMethod. + + + + +```julia +explore_learn_compose(concept; domains, param = nothing, search = :complete, global_iter = 10, local_iter = 100, metric = hamming, popSize = 200, action = :composition) +``` + + +Explore a search space, learn a composition from an ICN, and compose an error function. + +**Arguments:** +- `concept`: the concept of the targeted constraint + +- `domains`: domains of the variables that define the training space + +- `param`: an optional parameter of the constraint + +- `search`: either `flexible`,`:partial` or `:complete` search. Flexible search will use `search_limit` and `solutions_limit` to determine if the search space needs to be partially or completely explored + +- `global_iter`: number of learning iteration + +- `local_iter`: number of generation in the genetic algorithm + +- `metric`: the metric to measure the distance between a configuration and known solutions + +- `popSize`: size of the population in the genetic algorithm + +- `action`: either `:symbols` to have a description of the composition or `:composition` to have the composed function itself + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/learn.jl#L35-L50) + +
+
+
+# CompositionalNetworks.hammingMethod. + + + + +```julia +hamming(x, X) +``` + + +Compute the hamming distance of `x` over a collection of solutions `X`, i.e. the minimal number of variables to switch in `x`to reach a solution. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L1-L4) + +
+
+
+# CompositionalNetworks.lazyMethod. + + + + +```julia +lazy(funcs::Function...) +``` + + +Generate methods extended to a vector instead of one of its components. A function `f` should have the following signature: `f(i::Int, x::V)`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L22-L25) + +
+
+
+# CompositionalNetworks.lazy_paramMethod. + + + + +```julia +lazy_param(funcs::Function...) +``` + + +Generate methods extended to a vector instead of one of its components. A function `f` should have the following signature: `f(i::Int, x::V; param)`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/utils.jl#L36-L39) + +
+
+
+# CompositionalNetworks.learn_composeMethod. + + + + +```julia +learn_compose(; + nvars, dom_size, param=nothing, icn=ICN(nvars, dom_size, param), + X, X_sols, global_iter=100, local_iter=100, metric=hamming, popSize=200 +) +``` + + +Create an ICN, optimize it, and return its composition. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/learn.jl#L7-L13) + +
+
+
+# CompositionalNetworks.manhattanMethod. + + + + +```julia +manhattan(x, X) +``` + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L12-L14) + +
+
+
+# CompositionalNetworks.minkowskiMethod. + + + + +```julia +minkowski(x, X, p) +``` + + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L7-L9) + +
+
+
+# CompositionalNetworks.nbitsMethod. + + + + +```julia +nbits(icn) +``` + + +Return the expected number of bits of a viable weight of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L43-L46) + +
+
+
+# CompositionalNetworks.regularizationMethod. + + + + +```julia +regularization(icn) +``` + + +Return the regularization value of an ICN weights, which is proportional to the normalized number of operations selected in the icn layers. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L89-L92) + +
+
+
+# CompositionalNetworks.show_layersMethod. + + + + +```julia +show_layers(icn) +``` + + +Return a formatted string with each layers in the icn. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L81-L84) + +
+
+
+# CompositionalNetworks.symbolsMethod. + + + + +```julia +symbols(c::Composition) +``` + + +Output the composition as a layered collection of `Symbol`s. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/composition.jl#L38-L42) + +
+
+
+# CompositionalNetworks.transformation_layerFunction. + + + + +```julia +transformation_layer(param = false) +``` + + +Generate the layer of transformations functions of the ICN. Iff `param` value is true, also includes all the parametric transformations. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/layers/transformation.jl#L298-L301) + +
+
+
+# CompositionalNetworks.weights!Method. + + + + +```julia +weights!(icn, weights) +``` + + +Set the weights of an ICN with a `BitVector`. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L71-L74) + +
+
+
+# CompositionalNetworks.weightsMethod. + + + + +```julia +weights(icn) +``` + + +Access the current set of weights of an ICN. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/icn.jl#L49-L52) + +
+
+
+# CompositionalNetworks.weights_biasMethod. + + + + +```julia +weights_bias(x) +``` + + +A metric that bias `x` towards operations with a lower bit. Do not affect the main metric. + + +[source](https://github.com/JuliaConstraints/CompositionalNetworks.jl/blob/v0.5.6/src/metrics.jl#L17-L20) + +
+
+
+# QUBOConstraints.QUBO_linear_sumMethod. + + + + +```julia +QUBO_linear_sum(n, σ) +``` + + +One valid QUBO matrix given `n` variables and parameter `σ` for the linear sum constraint. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/handmade/linear_sum.jl#L1-L5) + +
+
+
+# QUBOConstraints.binarizeMethod. + + + + +```julia +binarize(x[, domain]; binarization = :one_hot) +``` + + +Binarize `x` following the `binarization` encoding. If `x` is a vector (instead of a number per say), `domain` is optional. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L12-L16) + +
+
+
+# QUBOConstraints.debinarizeMethod. + + + + +```julia +debinarize(x[, domain]; binarization = :one_hot) +``` + + +Transform a binary vector into a number or a set of number. If `domain` is not given, it will compute a default value based on `binarization` and `x`. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L35-L39) + +
+
+
+# QUBOConstraints.is_validFunction. + + + + +```julia +is_valid(x, encoding::Symbol = :none) +``` + + +Check if `x` has a valid format for `encoding`. + +For instance, if `encoding == :one_hot`, at most one bit of `x` can be set to 1. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/encoding/conversion.jl#L1-L7) + +
+
+
+# QUBOConstraints.trainMethod. + + + + +```julia +train(args...) +``` + + +Default `train` method for any AbstractOptimizer. + + +[source](https://github.com/JuliaConstraints/QUBOConstraints.jl/blob/v0.2.1/src/learn.jl#L8-L12) + +
+
diff --git a/previews/PR50/.documenter/solvers/cbls.md b/previews/PR50/.documenter/solvers/cbls.md new file mode 100644 index 0000000..1e0835d --- /dev/null +++ b/previews/PR50/.documenter/solvers/cbls.md @@ -0,0 +1,929 @@ + +# CBLS.jl + +Documentation for `CBLS.jl`. +
+# CBLS.AllDifferentType. + + + + +Global constraint ensuring that all the values of a given configuration are unique. + +```julia +@constraint(model, X in AllDifferent()) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L139-L145) + +
+
+
+# CBLS.AllEqualType. + + + + +Global constraint ensuring that all the values of `X` are all equal. + +```julia +@constraint(model, X in AllEqual()) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L170-L176) + +
+
+
+# CBLS.AllEqualParamType. + + + + +Global constraint ensuring that all the values of `X` are all equal to a given parameter `param`. + +```julia +@constraint(model, X in AllEqualParam(param)) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L338-L344) + +
+
+
+# CBLS.AlwaysTrueType. + + + + +Always return `true`. Mainly used for testing purpose. + +```julia +@constraint(model, X in AlwaysTrue()) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L231-L237) + +
+
+
+# CBLS.DiscreteSetType. + + + + +```julia +DiscreteSet(values) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L98-L100) + +
+
+
+# CBLS.DistDifferentType. + + + + +Local constraint ensuring that, given a vector `X` of size 4, `|X[1] - X[2]| ≠ |X[3] - X[4]|)`. + +```julia +@constraint(model, X in DistDifferent()) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L293-L299) + +
+
+
+# CBLS.EqType. + + + + +Equality between two variables. + +```julia +@constraint(model, X in Eq()) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L201-L207) + +
+
+
+# CBLS.ErrorType. + + + + +```julia +Error{F <: Function} <: JuMP.AbstractVectorSet +``` + + +The solver will compute a straightforward error function based on the `concept`. To run the solver efficiently, it is possible to provide an _error function_ `err` instead of `concept`. `err` must return a nonnegative real number. + +```julia +@constraint(model, X in Error(err)) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L58-L66) + +
+
+
+# CBLS.LessThanParamType. + + + + +Constraint ensuring that the value of `x` is less than a given parameter `param`. + +```julia +@constraint(model, x in LessThanParam(param)) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L432-L438) + +
+
+
+# CBLS.MOIAllDifferentType. + + + + +```julia +MOIAllDifferent <: MOI.AbstractVectorSet +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L119-L123) + +
+
+
+# CBLS.MOIAllEqualType. + + + + +```julia +MOIAllEqual <: MOI.AbstractVectorSet +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L149-L153) + +
+
+
+# CBLS.MOIAllEqualParamType. + + + + +```julia +MOIAllEqualParam{T <: Number} <: MOI.AbstractVectorSet +``` + + +DOCSTRING + +**Arguments:** +- `param::T`: DESCRIPTION + +- `dimension::Int`: DESCRIPTION + +- `MOIAllEqualParam(param, dim = 0) = begin #= none:5 =# new{typeof(param)}(param, dim) end`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L303-L315) + +
+
+
+# CBLS.MOIAlwaysTrueType. + + + + +```julia +MOIAlwaysTrue <: MOI.AbstractVectorSet +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L211-L215) + +
+
+
+# CBLS.MOIDistDifferentType. + + + + +```julia +MOIDistDifferent <: MOI.AbstractVectorSet +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L273-L277) + +
+
+
+# CBLS.MOIEqType. + + + + +```julia +MOIEq <: MOI.AbstractVectorSet +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L180-L184) + +
+
+
+# CBLS.MOIErrorType. + + + + +```julia +MOIError{F <: Function} <: MOI.AbstractVectorSet +``` + + +DOCSTRING + +**Arguments:** +- `f::F`: DESCRIPTION + +- `dimension::Int`: DESCRIPTION + +- `MOIError(f, dim = 0) = begin #= none:5 =# new{typeof(f)}(f, dim) end`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L1-L13) + +
+
+
+# CBLS.MOILessThanParamType. + + + + +```julia +MOILessThanParam{T <: Number} <: MOI.AbstractVectorSet +``` + + +DOCSTRING + +**Arguments:** +- `param::T`: DESCRIPTION + +- `dimension::Int`: DESCRIPTION + +- `MOILessThanParam(param, dim = 0) = begin #= none:5 =# new{typeof(param)}(param, dim) end`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L397-L409) + +
+
+
+# CBLS.MOIMinusEqualParamType. + + + + +```julia +MOIMinusEqualParam{T <: Number} <: MOI.AbstractVectorSet +``` + + +DOCSTRING + +**Arguments:** +- `param::T`: DESCRIPTION + +- `dimension::Int`: DESCRIPTION + +- `MOIMinusEqualParam(param, dim = 0) = begin #= none:5 =# new{typeof(param)}(param, dim) end`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L444-L456) + +
+
+
+# CBLS.MOIOrderedType. + + + + +```julia +MOIOrdered <: MOI.AbstractVectorSet +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L241-L245) + +
+
+
+# CBLS.MOIPredicateType. + + + + +```julia +MOIPredicate{F <: Function} <: MOI.AbstractVectorSet +``` + + +DOCSTRING + +**Arguments:** +- `f::F`: DESCRIPTION + +- `dimension::Int`: DESCRIPTION + +- `MOIPredicate(f, dim = 0) = begin #= none:5 =# new{typeof(f)}(f, dim) end`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L74-L86) + +
+
+
+# CBLS.MOISequentialTasksType. + + + + +```julia +MOISequentialTasks <: MOI.AbstractVectorSet +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L492-L496) + +
+
+
+# CBLS.MOISumEqualParamType. + + + + +```julia +MOISumEqualParam{T <: Number} <: MOI.AbstractVectorSet +``` + + +DOCSTRING + +**Arguments:** +- `param::T`: DESCRIPTION + +- `dimension::Int`: DESCRIPTION + +- `MOISumEqualParam(param, dim = 0) = begin #= none:5 =# new{typeof(param)}(param, dim) end`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L350-L362) + +
+
+
+# CBLS.MinusEqualParamType. + + + + +Constraint ensuring that the value of `x` is less than a given parameter `param`. + +```julia +@constraint(model, x in MinusEqualParam(param)) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L479-L485) + +
+
+
+# CBLS.OptimizerType. + + + + +```julia +Optimizer(model = Model(); options = Options()) +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L35-L39) + +
+
+
+# CBLS.OptimizerType. + + + + +```julia +Optimizer <: MOI.AbstractOptimizer +``` + + +DOCSTRING + +**Arguments:** +- `solver::Solver`: DESCRIPTION + +- `status::MOI.TerminationStatusCode`: DESCRIPTION + +- `options::Options`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L19-L28) + +
+
+
+# CBLS.OrderedType. + + + + +Global constraint ensuring that all the values of `x` are ordered. + +```julia +@constraint(model, X in Ordered()) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L262-L268) + +
+
+
+# CBLS.PredicateType. + + + + +```julia +Predicate{F <: Function} <: JuMP.AbstractVectorSet +``` + + +Assuming `X` is a (collection of) variables, `concept` a boolean function over `X`, and that a `model` is defined. In `JuMP` syntax we can create a constraint based on `concept` as follows. + +```julia +@constraint(model, X in Predicate(concept)) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L105-L113) + +
+
+
+# CBLS.ScalarFunctionType. + + + + +```julia +ScalarFunction{F <: Function, V <: Union{Nothing, VOV}} <: MOI.AbstractScalarFunction +``` + + +A container to express any function with real value in JuMP syntax. Used with the `@objective` macro. + +**Arguments:** +- `f::F`: function to be applied to `X` + +- `X::V`: a subset of the variables of the model. + + +Given a `model`, and some (collection of) variables `X` to optimize. an objective function `f` can be added as follows. Note that only `Min` for minimization us currently defined. `Max` will come soon. + +```julia +# Applies to all variables in order of insertion. +# Recommended only when the function argument order does not matter. +@objective(model, ScalarFunction(f)) + +# Generic use +@objective(model, ScalarFunction(f, X)) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/objectives.jl#L9-L28) + +
+
+
+# CBLS.SequentialTasksType. + + + + +Local constraint ensuring that, given a vector `X` of size 4, `|X[1] - X[2]| ≠ |X[3] - X[4]|)`. + +```julia +@constraint(model, X in SequentialTasks()) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L512-L518) + +
+
+
+# CBLS.SumEqualParamType. + + + + +Global constraint ensuring that the sum of the values of `X` is equal to a given parameter `param`. + +```julia +@constraint(model, X in SumEqualParam(param)) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L385-L391) + +
+
+
+# Base.copyMethod. + + + + +```julia +Base.copy(set::MOIError) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L51-L55) + +
+
+
+# Base.copyMethod. + + + + +```julia +Base.copy(set::DiscreteSet) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L107-L111) + +
+
+
+# JuMP.build_variableMethod. + + + + +```julia +JuMP.build_variable(::Function, info::JuMP.VariableInfo, set::T) where T <: MOI.AbstractScalarSet +``` + + +DOCSTRING + +**Arguments:** +- ``: DESCRIPTION + +- `info`: DESCRIPTION + +- `set`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L1-L10) + +
+
+
+# MathOptInterface.add_constraintMethod. + + + + +```julia +MOI.add_constraint(optimizer::Optimizer, vars::MOI.VectorOfVariables, set::MOIError) +``` + + +DOCSTRING + +**Arguments:** +- `optimizer`: DESCRIPTION + +- `vars`: DESCRIPTION + +- `set`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L36-L45) + +
+
+
+# MathOptInterface.add_constraintMethod. + + + + +```julia +MOI.add_constraint(optimizer::Optimizer, v::VI, set::DiscreteSet{T}) where T <: Number +``` + + +DOCSTRING + +**Arguments:** +- `optimizer`: DESCRIPTION + +- `v`: DESCRIPTION + +- `set`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/variables.jl#L34-L43) + +
+
+
+# MathOptInterface.add_variableMethod. + + + + +```julia +MOI.add_variable(model::Optimizer) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/variables.jl#L2-L6) + +
+
+
+# MathOptInterface.empty!Method. + + + + +```julia +MOI.empty!(opt) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L114-L118) + +
+
+
+# MathOptInterface.getMethod. + + + + +```julia +MOI.get(::Optimizer, ::MOI.SolverName) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L59-L63) + +
+
+
+# MathOptInterface.is_emptyMethod. + + + + +```julia +MOI.is_empty(model::Optimizer) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L78-L82) + +
+
+
+# MathOptInterface.optimize!Method. + + + + +```julia +MOI.optimize!(model::Optimizer) +``` + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L93-L95) + +
+
+
+# MathOptInterface.setFunction. + + + + +```julia +MOI.set(::Optimizer, ::MOI.Silent, bool = true) = begin +``` + + +DOCSTRING + +**Arguments:** +- ``: DESCRIPTION + +- ``: DESCRIPTION + +- `bool`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L66-L75) + +
+
+
+# MathOptInterface.setMethod. + + + + +```julia +MOI.set(model::Optimizer, p::MOI.RawOptimizerAttribute, value) +``` + + +Set a RawOptimizerAttribute to `value` + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/attributes.jl#L19-L22) + +
+
+
+# MathOptInterface.setMethod. + + + + +```julia +MOI.set(model::Optimizer, ::MOI.TimeLimitSec, value::Union{Nothing,Float64}) +``` + + +Set the time limit + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/attributes.jl#L7-L10) + +
+
+
+# MathOptInterface.supports_constraintMethod. + + + + +```julia +MOI.supports_constraint(::Optimizer, ::Type{VOV}, ::Type{MOIError}) = begin +``` + + +DOCSTRING + +**Arguments:** +- ``: DESCRIPTION + +- ``: DESCRIPTION + +- ``: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/constraints.jl#L21-L30) + +
+
+
+# MathOptInterface.supports_incremental_interfaceMethod. + + + + +Copy constructor for the optimizer + + +[source](https://github.com/JuliaConstraints/CBLS.jl/blob/v0.1.13/src/MOI_wrapper.jl#L85-L87) + +
+
diff --git a/previews/PR50/.documenter/solvers/intro.md b/previews/PR50/.documenter/solvers/intro.md new file mode 100644 index 0000000..ba43c19 --- /dev/null +++ b/previews/PR50/.documenter/solvers/intro.md @@ -0,0 +1,4 @@ + +# Solvers + +About solvers. diff --git a/previews/PR50/.documenter/solvers/local_search_solvers.md b/previews/PR50/.documenter/solvers/local_search_solvers.md new file mode 100644 index 0000000..7c1d120 --- /dev/null +++ b/previews/PR50/.documenter/solvers/local_search_solvers.md @@ -0,0 +1,2704 @@ + +# LocalSearchSolvers.jl + +Documentation for `LocalSearchSolvers.jl`. +
+# LocalSearchSolvers.AbstractSolverType. + + + + +```julia +AbstractSolver +``` + + +Abstract type to encapsulate the different solver types such as `Solver` or `_SubSolver`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L1-L4) + +
+
+
+# LocalSearchSolvers.ConstraintType. + + + + +```julia +Constraint{F <: Function} +``` + + +Structure to store an error function and the variables it constrains. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L1-L5) + +
+
+
+# LocalSearchSolvers.LeadSolverType. + + + + +```julia +LeadSolver <: MetaSolver +``` + + +Solver managed remotely by a MainSolver. Can manage its own set of local sub solvers. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solvers/lead.jl#L1-L4) + +
+
+
+# LocalSearchSolvers.MainSolverType. + + + + +```julia +MainSolver <: AbstractSolver +``` + + +Main solver. Handle the solving of a model, and optional multithreaded and/or distributed subsolvers. + +**Arguments:** +- `model::Model`: A formal description of the targeted problem + +- `state::_State`: An internal state to store the info necessary to a solving run + +- `options::Options`: User options for this solver + +- `subs::Vector{_SubSolver}`: Optional subsolvers + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solvers/main.jl#L1-L11) + +
+
+
+# LocalSearchSolvers.MetaSolverType. + + + + +Abstract type to encapsulate all solver types that manages other solvers. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solvers/meta.jl#L1-L3) + +
+
+
+# LocalSearchSolvers.ObjectiveType. + + + + +```julia +Objective{F <: Function} +``` + + +A structure to handle objectives in a solver. `struct Objective{F <: Function} name::String f::F end`` + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/objective.jl#L1-L10) + +
+
+
+# LocalSearchSolvers.ObjectiveMethod. + + + + +```julia +Objective(F, o::Objective{F2}) where {F2 <: Function} +``` + + +Constructor used in specializing a solver. Should never be called externally. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/objective.jl#L16-L19) + +
+
+
+# LocalSearchSolvers.OptionsType. + + + + +```julia +Options() +``` + + +**Arguments:** +- `dynamic::Bool`: is the model dynamic? + +- `iteration::Union{Int, Float64}`: limit on the number of iterations + +- `print_level::Symbol`: verbosity to choose among `:silent`, `:minimal`, `:partial`, `:verbose` + +- `solutions::Int`: number of solutions to return + +- `specialize::Bool`: should the types of the model be specialized or not. Usually yes for static problems. For dynamic in depends if the user intend to introduce new types. The specialized model is about 10% faster. + +- `tabu_time::Int`: DESCRIPTION + +- `tabu_local::Int`: DESCRIPTION + +- `tabu_delta::Float64`: DESCRIPTION + +- `threads::Int`: Number of threads to use + +- `time_limit::Float64`: time limit in seconds + +- `function Options(; dynamic = false, iteration = 10000, print_level = :minimal, solutions = 1, specialize = !dynamic, tabu_time = 0, tabu_local = 0, tabu_delta = 0.0, threads = typemax(0), time_limit = Inf) + + +```julia +# Setting options in JuMP syntax: print_level, time_limit, iteration +model = Model(CBLS.Optimizer) +set_optimizer_attribute(model, "iteration", 100) +set_optimizer_attribute(model, "print_level", :verbose) +set_time_limit_sec(model, 5.0) +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L13-L35) + +
+
+
+# LocalSearchSolvers.VariableType. + + + + +```julia +Variable{D <: AbstractDomain} +``` + + +A structure containing the necessary information for a solver's variables: `name`, `domain`, and `constraints` it belongs. + +``` +struct Variable{D <: AbstractDomain} + domain::D + constraints::Indices{Int} +end +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L1-L10) + +
+
+
+# LocalSearchSolvers._ModelType. + + + + +```julia +_Model{V <: Variable{<:AbstractDomain},C <: Constraint{<:Function},O <: Objective{<:Function}} +``` + + +A struct to model a problem as a set of variables, domains, constraints, and objectives. + +``` +struct _Model{V <: Variable{<:AbstractDomain},C <: Constraint{<:Function},O <: Objective{<:Function}} + variables::Dictionary{Int,V} + constraints::Dictionary{Int,C} + objectives::Dictionary{Int,O} + + # counter to add new variables: vars, cons, objs + max_vars::Ref{Int} + max_cons::Ref{Int} + max_objs::Ref{Int} + + # Bool to indicate if the _Model instance has been specialized (relatively to types) + specialized::Ref{Bool} + + # Symbol to indicate the kind of model for specialized methods such as pretty printing + kind::Symbol +end +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L1-L22) + +
+
+
+# LocalSearchSolvers._StateType. + + + + +```julia +GeneralState{T <: Number} +``` + + +A mutable structure to store the general state of a solver. All methods applied to `GeneralState` are forwarded to `S <: AbstractSolver`. + +``` +mutable struct GeneralState{T <: Number} <: AbstractState + configuration::Configuration{T} + cons_costs::Dictionary{Int, Float64} + last_improvement::Int + tabu::Dictionary{Int, Int} + vars_costs::Dictionary{Int, Float64} +end +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L5-L17) + +
+
+
+# LocalSearchSolvers._SubSolverType. + + + + +```julia +_SubSolver <: AbstractSolver +``` + + +An internal solver type called by MetaSolver when multithreading is enabled. + +**Arguments:** +- `id::Int`: subsolver id for debugging + +- `model::Model`: a ref to the model of the main solver + +- `state::_State`: a `deepcopy` of the main solver that evolves independently + +- `options::Options`: a ref to the options of the main solver + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solvers/sub.jl#L1-L11) + +
+
+
+# Base.empty!Method. + + + + +```julia +empty!(s::Solver) +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solvers/main.jl#L49-L52) + +
+
+
+# Base.empty!Method. + + + + +```julia +empty!(m::Model) +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L437-L441) + +
+
+
+# Base.inMethod. + + + + +```julia +var::Int ∈ c::Constraint +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L43-L45) + +
+
+
+# Base.inMethod. + + + + +```julia +x::Variable ∈ constraint +value ∈ x::Variable +``` + + +Check if a variable `x` is restricted by a `constraint::Int`, or if a `value` belongs to the domain of `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L52-L56) + +
+
+
+# LocalSearchSolvers._add!Method. + + + + +```julia +_add!(c::Constraint, x) +``` + + +Add the variable of indice `x` to `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L22-L26) + +
+
+
+# LocalSearchSolvers._add_to_constraint!Method. + + + + +```julia +_add_to_constraint!(x::Variable, id) +``` + + +Add a constraint `id` to the list of constraints of `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L34-L37) + +
+
+
+# LocalSearchSolvers._check_restartMethod. + + + + +```julia +_check_restart(s) +``` + + +Check if a restart of `s` is necessary. If `s` has subsolvers, this check is independent for all of them. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L265-L269) + +
+
+
+# LocalSearchSolvers._check_subsMethod. + + + + +```julia +_check_subs(s) +``` + + +Check if any subsolver of a main solver `s`, for +- _Satisfaction_, has a solution, then return it, resume the run otherwise + +- _Optimization_, has a better solution, then assign it to its internal state + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L390-L396) + +
+
+
+# LocalSearchSolvers._compute!Method. + + + + +```julia +_compute!(s; o::Int = 1, cons_lst = Indices{Int}()) +``` + + +Compute the objective `o`'s value if `s` is satisfied and return the current `error`. + +**Arguments:** +- `s`: a solver + +- `o`: targeted objective + +- `cons_lst`: list of targeted constraints, if empty compute for the whole set + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L165-L174) + +
+
+
+# LocalSearchSolvers._compute_cost!Method. + + + + +```julia +_compute_cost!(s, ind, c) +``` + + +Compute the cost of constraint `c` with index `ind`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L121-L125) + +
+
+
+# LocalSearchSolvers._compute_costs!Method. + + + + +```julia +_compute_costs!(s; cons_lst::Indices{Int} = Indices{Int}()) +``` + + +Compute the cost of constraints `c` in `cons_lst`. If `cons_lst` is empty, compute the cost for all the constraints in `s`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L133-L137) + +
+
+
+# LocalSearchSolvers._compute_objective!Method. + + + + +```julia +_compute_objective!(s, o::Objective) +_compute_objective!(s, o = 1) +``` + + +Compute the objective `o`'s value. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L150-L155) + +
+
+
+# LocalSearchSolvers._cons_cost!Method. + + + + +```julia +_cons_cost!(s::S, c, cost) where S <: Union{_State, AbstractSolver} +``` + + +Set the `cost` of constraint `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L117-L120) + +
+
+
+# LocalSearchSolvers._cons_costMethod. + + + + +```julia +_cons_cost(s::S, c) where S <: Union{_State, AbstractSolver} +``` + + +Return the cost of constraint `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L99-L102) + +
+
+
+# LocalSearchSolvers._cons_costs!Method. + + + + +```julia +_cons_costs!(s::S, costs) where S <: Union{_State, AbstractSolver} +``` + + +Set the constraints costs. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L69-L72) + +
+
+
+# LocalSearchSolvers._cons_costsMethod. + + + + +```julia +_cons_costs(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Access the constraints costs. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L45-L48) + +
+
+
+# LocalSearchSolvers._constrictionMethod. + + + + +```julia +_constriction(x::Variable) +``` + + +Return the `cosntriction` of `x`, i.e. the number of constraints restricting `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L46-L49) + +
+
+
+# LocalSearchSolvers._delete!Method. + + + + +```julia +_delete!(c::Constraint, x::Int) +``` + + +Delete `x` from `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L29-L33) + +
+
+
+# LocalSearchSolvers._delete_from_constraint!Method. + + + + +```julia +_delete_from_constraint!(x::Variable, id) +``` + + +Delete a constraint `id` from the list of constraints of `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L40-L43) + +
+
+
+# LocalSearchSolvers._draw!Method. + + + + +```julia +_draw!(s) +``` + + +Draw a random (re-)starting configuration. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L113-L116) + +
+
+
+# LocalSearchSolvers._dynamic!Method. + + + + +```julia +_dynamic!(options, dynamic) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L106-L110) + +
+
+
+# LocalSearchSolvers._dynamicMethod. + + + + +```julia +_dynamic(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L99-L103) + +
+
+
+# LocalSearchSolvers._find_rand_argmaxMethod. + + + + +```julia +_find_rand_argmax(d::DictionaryView) +``` + + +Compute `argmax` of `d` and select one element randomly. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/utils.jl#L7-L10) + +
+
+
+# LocalSearchSolvers._get_constraintsMethod. + + + + +```julia +_get_constraints(x::Variable) +``` + + +Access the list of `constraints` of `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L28-L31) + +
+
+
+# LocalSearchSolvers._get_varsMethod. + + + + +```julia +_get_vars(c::Constraint) +``` + + +Returns the variables constrained by `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L15-L19) + +
+
+
+# LocalSearchSolvers._inc_cons!Method. + + + + +```julia +_inc_vars!(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Increment the maximum constraint id that has been attributed to `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L102-L105) + +
+
+
+# LocalSearchSolvers._inc_objs!Method. + + + + +```julia +_inc_vars!(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Increment the maximum objective id that has been attributed to `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L108-L111) + +
+
+
+# LocalSearchSolvers._inc_vars!Method. + + + + +```julia +_inc_vars!(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Increment the maximum variable id that has been attributed to `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L96-L99) + +
+
+
+# LocalSearchSolvers._info_path!Method. + + + + +```julia +_info_path!(options, iterations) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L120-L124) + +
+
+
+# LocalSearchSolvers._info_pathMethod. + + + + +```julia +_info_path(options, path) +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L113-L117) + +
+
+
+# LocalSearchSolvers._is_emptyMethod. + + + + +```julia +_is_empty(m::Model) +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L385-L389) + +
+
+
+# LocalSearchSolvers._iteration!Method. + + + + +```julia +_iteration!(options, iterations) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L134-L138) + +
+
+
+# LocalSearchSolvers._iterationMethod. + + + + +```julia +_iteration(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L127-L131) + +
+
+
+# LocalSearchSolvers._lengthMethod. + + + + +```julia +_length(c::Constraint) +``` + + +Return the number of constrained variables by `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L36-L40) + +
+
+
+# LocalSearchSolvers._max_consMethod. + + + + +```julia +_max_cons(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Access the maximum constraint id that has been attributed to `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L82-L85) + +
+
+
+# LocalSearchSolvers._max_objsMethod. + + + + +```julia +_max_objs(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Access the maximum objective id that has been attributed to `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L88-L91) + +
+
+
+# LocalSearchSolvers._max_varsMethod. + + + + +```julia +_max_vars(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Access the maximum variable id that has been attributed to `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L76-L79) + +
+
+
+# LocalSearchSolvers._move!Function. + + + + +```julia +_move!(s, x::Int, dim::Int = 0) +``` + + +Perform an improving move in `x` neighbourhood if possible. + +**Arguments:** +- `s`: a solver of type S <: AbstractSolver + +- `x`: selected variable id + +- `dim`: describe the dimension of the considered neighbourhood + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L285-L294) + +
+
+
+# LocalSearchSolvers._neighboursFunction. + + + + +```julia +_neighbours(s, x, dim = 0) +``` + + +DOCSTRING + +**Arguments:** +- `s`: DESCRIPTION + +- `x`: DESCRIPTION + +- `dim`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L185-L194) + +
+
+
+# LocalSearchSolvers._optimizing!Method. + + + + +```julia +_optimizing!(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Set the solver `optimizing` status to `true`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L87-L90) + +
+
+
+# LocalSearchSolvers._optimizingMethod. + + + + +```julia +_optimizing(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Check if `s` is in an optimizing state. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L63-L66) + +
+
+
+# LocalSearchSolvers._print_level!Method. + + + + +```julia +_print_level!(options, level) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L148-L152) + +
+
+
+# LocalSearchSolvers._print_levelMethod. + + + + +```julia +_print_level(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L141-L145) + +
+
+
+# LocalSearchSolvers._restart!Function. + + + + +```julia +_restart!(s, k = 10) +``` + + +Restart a solver. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L251-L255) + +
+
+
+# LocalSearchSolvers._satisfying!Method. + + + + +```julia +_satisfying!(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Set the solver `optimizing` status to `false`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L93-L96) + +
+
+
+# LocalSearchSolvers._select_worseMethod. + + + + +```julia +_select_worse(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Within the non-tabu variables, select the one with the worse error . + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L276-L279) + +
+
+
+# LocalSearchSolvers._set!Method. + + + + +```julia +_set!(s::S, x, val) where S <: Union{_State, AbstractSolver} +``` + + +Set the value of variable `x` to `val`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L135-L138) + +
+
+
+# LocalSearchSolvers._set_domain!Method. + + + + +```julia +_set_domain!(m::Model, x, values) +``` + + +DOCSTRING + +**Arguments:** +- `m`: DESCRIPTION + +- `x`: DESCRIPTION + +- `values`: DESCRIPTION + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L394-L403) + +
+
+
+# LocalSearchSolvers._solutions!Method. + + + + +```julia +_solutions!(options, solutions) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L162-L166) + +
+
+
+# LocalSearchSolvers._solutionsMethod. + + + + +```julia +_solutions(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L155-L159) + +
+
+
+# LocalSearchSolvers._specialize!Method. + + + + +```julia +_specialize!(options, specialize) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L176-L180) + +
+
+
+# LocalSearchSolvers._specializeMethod. + + + + +```julia +_specialize(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L169-L173) + +
+
+
+# LocalSearchSolvers._step!Method. + + + + +```julia +_step!(s) +``` + + +Iterate a step of the solver run. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L337-L341) + +
+
+
+# LocalSearchSolvers._swap_value!Method. + + + + +```julia +_set!(s::S, x, y) where S <: Union{_State, AbstractSolver} +``` + + +Swap the values of variables `x` and `y`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L141-L144) + +
+
+
+# LocalSearchSolvers._tabu_delta!Method. + + + + +```julia +_tabu_delta!(options, time) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L218-L222) + +
+
+
+# LocalSearchSolvers._tabu_deltaMethod. + + + + +```julia +_tabu_delta(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L211-L215) + +
+
+
+# LocalSearchSolvers._tabu_local!Method. + + + + +```julia +_tabu_local!(options, time) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L204-L208) + +
+
+
+# LocalSearchSolvers._tabu_localMethod. + + + + +```julia +_tabu_local(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L197-L201) + +
+
+
+# LocalSearchSolvers._tabu_time!Method. + + + + +```julia +_tabu_time!(options, time) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L190-L194) + +
+
+
+# LocalSearchSolvers._tabu_timeMethod. + + + + +```julia +_tabu_time(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L183-L187) + +
+
+
+# LocalSearchSolvers._threads!Method. + + + + +```julia +_threads!(options, threads) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L232-L236) + +
+
+
+# LocalSearchSolvers._threadsMethod. + + + + +```julia +_threads(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L225-L229) + +
+
+
+# LocalSearchSolvers._time_limit!Method. + + + + +```julia +_time_limit!(options, time::Time) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L246-L250) + +
+
+
+# LocalSearchSolvers._time_limitMethod. + + + + +```julia +_time_limit(options) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L239-L243) + +
+
+
+# LocalSearchSolvers._to_unionMethod. + + + + +```julia +_to_union(datatype) +``` + + +Make a minimal `Union` type from a collection of data types. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/utils.jl#L1-L4) + +
+
+
+# LocalSearchSolvers._value!Method. + + + + +```julia +_value!(s::S, x, val) where S <: Union{_State, AbstractSolver} +``` + + +Set the value of variable `x` to `val`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L129-L132) + +
+
+
+# LocalSearchSolvers._valueMethod. + + + + +```julia +_value(s::S, x) where S <: Union{_State, AbstractSolver} +``` + + +Return the value of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L111-L114) + +
+
+
+# LocalSearchSolvers._values!Method. + + + + +```julia +_values!(s::S, values) where S <: Union{_State, AbstractSolver} +``` + + +Set the variables values. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L81-L84) + +
+
+
+# LocalSearchSolvers._valuesMethod. + + + + +```julia +_vars_costs(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Access the variables costs. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L57-L60) + +
+
+
+# LocalSearchSolvers._var_cost!Method. + + + + +```julia +_var_cost!(s::S, x, cost) where S <: Union{_State, AbstractSolver} +``` + + +Set the `cost` of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L123-L126) + +
+
+
+# LocalSearchSolvers._var_costMethod. + + + + +```julia +_var_cost(s::S, x) where S <: Union{_State, AbstractSolver} +``` + + +Return the cost of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L105-L108) + +
+
+
+# LocalSearchSolvers._vars_costs!Method. + + + + +```julia +_vars_costs!(s::S, costs) where S <: Union{_State, AbstractSolver} +``` + + +Set the variables costs. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L75-L78) + +
+
+
+# LocalSearchSolvers._vars_costsMethod. + + + + +```julia +_vars_costs(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Access the variables costs. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/state.jl#L51-L54) + +
+
+
+# LocalSearchSolvers._verboseMethod. + + + + +```julia +_verbose(settings, str) +``` + + +Temporary logging function. #TODO: use better log instead (LoggingExtra.jl) + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/options.jl#L90-L93) + +
+
+
+# LocalSearchSolvers.add!Method. + + + + +```julia +mts = - get_time_stamp(model) +``` + + +return TimeStamps(mts, mts, mts, mts, mts, mts, mts) end + +``` +add!(m::M, x) where M <: Union{Model, AbstractSolver} +add!(m::M, c) where M <: Union{Model, AbstractSolver} +add!(m::M, o) where M <: Union{Model, AbstractSolver} +``` + + +Add a variable `x`, a constraint `c`, or an objective `o` to `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L253-L262) + +
+
+
+# LocalSearchSolvers.add_value!Method. + + + + +```julia +add_value!(m::M, x, val) where M <: Union{Model, AbstractSolver} +``` + + +Add `val` to `x` domain. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L241-L244) + +
+
+
+# LocalSearchSolvers.add_var_to_cons!Method. + + + + +```julia +add_var_to_cons!(m::M, c, x) where M <: Union{Model, AbstractSolver} +``` + + +Add `x` to the constraint `c` list of restricted variables. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L247-L250) + +
+
+
+# LocalSearchSolvers.constraint!Method. + + + + +```julia +constraint!(m::M, func, vars) where M <: Union{Model, AbstractSolver} +``` + + +Add a constraint with an error function `func` defined over variables `vars`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L287-L290) + +
+
+
+# LocalSearchSolvers.constraintMethod. + + + + +```julia +constraint(f, vars) +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/constraint.jl#L48-L52) + +
+
+
+# LocalSearchSolvers.constrictionMethod. + + + + +```julia +constriction(m::M, x) where M <: Union{Model, AbstractSolver} +``` + + +Return the constriction of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L223-L226) + +
+
+
+# LocalSearchSolvers.decay_tabu!Method. + + + + +```julia +_decay_tabu!(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Decay the tabu list. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/strategies/tabu.jl#L77-L80) + +
+
+
+# LocalSearchSolvers.decrease_tabu!Method. + + + + +```julia +_decrease_tabu!(s::S, x) where S <: Union{_State, AbstractSolver} +``` + + +Decrement the tabu value of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/strategies/tabu.jl#L44-L47) + +
+
+
+# LocalSearchSolvers.delete_tabu!Method. + + + + +```julia +_delete_tabu!(s::S, x) where S <: Union{_State, AbstractSolver} +``` + + +Delete the tabu entry of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/strategies/tabu.jl#L50-L53) + +
+
+
+# LocalSearchSolvers.delete_value!Method. + + + + +```julia +delete_value(m::M, x, val) where M <: Union{Model, AbstractSolver} +``` + + +Delete `val` from `x` domain. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L229-L232) + +
+
+
+# LocalSearchSolvers.delete_var_from_cons!Method. + + + + +```julia +delete_var_from_cons(m::M, c, x) where M <: Union{Model, AbstractSolver} +``` + + +Delete `x` from the constraint `c` list of restricted variables. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L235-L238) + +
+
+
+# LocalSearchSolvers.describeMethod. + + + + +```julia +describe(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Describe the model. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L304-L307) + +
+
+
+# LocalSearchSolvers.domain_sizeMethod. + + + + +```julia +domain_size(m::Model, x) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L423-L427) + +
+
+
+# LocalSearchSolvers.drawMethod. + + + + +```julia +draw(m::M, x) where M <: Union{Model, AbstractSolver} +``` + + +Draw a random value of `x` domain. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L216-L219) + +
+
+
+# LocalSearchSolvers.empty_tabu!Method. + + + + +```julia +_empty_tabu!(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Empty the tabu list. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/strategies/tabu.jl#L56-L59) + +
+
+
+# LocalSearchSolvers.get_cons_from_varMethod. + + + + +```julia +get_cons_from_var(m::M, x) where M <: Union{Model, AbstractSolver} +``` + + +Access the constraints restricting variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L168-L171) + +
+
+
+# LocalSearchSolvers.get_constraintMethod. + + + + +```julia +get_constraint(m::M, c) where M <: Union{Model, AbstractSolver} +``` + + +Access the constraint `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L144-L147) + +
+
+
+# LocalSearchSolvers.get_constraintsMethod. + + + + +```julia +get_constraints(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Access the constraints of `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L120-L123) + +
+
+
+# LocalSearchSolvers.get_domainMethod. + + + + +```julia +get_domain(m::M, x) where M <: Union{Model, AbstractSolver} +``` + + +Access the domain of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L156-L159) + +
+
+
+# LocalSearchSolvers.get_kindMethod. + + + + +```julia +get_kind(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Access the kind of `m`, such as `:sudoku` or `:generic` (default). + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L132-L135) + +
+
+
+# LocalSearchSolvers.get_nameMethod. + + + + +```julia +get_name(m::M, x) where M <: Union{Model, AbstractSolver} +``` + + +Access the name of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L162-L165) + +
+
+
+# LocalSearchSolvers.get_objectiveMethod. + + + + +```julia +get_objective(m::M, o) where M <: Union{Model, AbstractSolver} +``` + + +Access the objective `o`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L150-L153) + +
+
+
+# LocalSearchSolvers.get_objectivesMethod. + + + + +```julia +get_objectives(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Access the objectives of `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L126-L129) + +
+
+
+# LocalSearchSolvers.get_time_stampMethod. + + + + +```julia +get_time_stamp(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Access the time (since epoch) when the model was created. This time stamp is for internal performance measurement. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L180-L183) + +
+
+
+# LocalSearchSolvers.get_variableMethod. + + + + +```julia +get_variable(m::M, x) where M <: Union{Model, AbstractSolver} +``` + + +Access the variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L138-L141) + +
+
+
+# LocalSearchSolvers.get_variablesMethod. + + + + +```julia +get_variables(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Access the variables of `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L114-L117) + +
+
+
+# LocalSearchSolvers.get_vars_from_consMethod. + + + + +```julia +get_vars_from_cons(m::M, c) where M <: Union{Model, AbstractSolver} +``` + + +Access the variables restricted by constraint `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L174-L177) + +
+
+
+# LocalSearchSolvers.insert_tabu!Method. + + + + +```julia +_insert_tabu!(s::S, x, tabu_time) where S <: Union{_State, AbstractSolver} +``` + + +Insert the bariable `x` as tabu for `tabu_time`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/strategies/tabu.jl#L68-L71) + +
+
+
+# LocalSearchSolvers.is_satMethod. + + + + +```julia +is_sat(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Return `true` if `m` is a satisfaction model. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L336-L339) + +
+
+
+# LocalSearchSolvers.is_specializedMethod. + + + + +```julia +is_specialized(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Return `true` if the model is already specialized. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L342-L345) + +
+
+
+# LocalSearchSolvers.length_consMethod. + + + + +```julia +length_cons(m::M, c) where M <: Union{Model, AbstractSolver} +``` + + +Return the length of constraint `c`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L192-L195) + +
+
+
+# LocalSearchSolvers.length_consMethod. + + + + +```julia +length_cons(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Return the number of constraints in `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L210-L213) + +
+
+
+# LocalSearchSolvers.length_objsMethod. + + + + +```julia +length_objs(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Return the number of objectives in `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L198-L201) + +
+
+
+# LocalSearchSolvers.length_tabuMethod. + + + + +```julia +_length_tabu!(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Return the length of the tabu list. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/strategies/tabu.jl#L62-L65) + +
+
+
+# LocalSearchSolvers.length_varMethod. + + + + +```julia +length_var(m::M, x) where M <: Union{Model, AbstractSolver} +``` + + +Return the domain length of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L186-L189) + +
+
+
+# LocalSearchSolvers.length_varsMethod. + + + + +```julia +length_vars(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Return the number of variables in `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L204-L207) + +
+
+
+# LocalSearchSolvers.max_domains_sizeMethod. + + + + +```julia +max_domains_size(m::Model, vars) = begin +``` + + +DOCSTRING + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L430-L434) + +
+
+
+# LocalSearchSolvers.modelMethod. + + + + +```julia +model() +``` + + +Construct a _Model, empty by default. It is recommended to add the constraints, variables, and objectives from an empty _Model. The following keyword arguments are available, +- `vars=Dictionary{Int,Variable}()`: collection of variables + +- `cons=Dictionary{Int,Constraint}()`: collection of constraints + +- `objs=Dictionary{Int,Objective}()`: collection of objectives + +- `kind=:generic`: the kind of problem modeled (useful for specialized methods such as pretty printing) + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L50-L57) + +
+
+
+# LocalSearchSolvers.o_dist_extremaMethod. + + + + +```julia +dist_extrema(values::T...) where {T <: Number} +``` + + +Computes the distance between extrema in an ordered set. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/objectives/extrema.jl#L1-L4) + +
+
+
+# LocalSearchSolvers.o_mincutMethod. + + + + +```julia +o_mincut(graph, values; interdiction = 0) +``` + + +Compute the capacity of a cut (determined by the state of the solver) with a possible `interdiction` on the highest capacited links. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/objectives/cut.jl#L1-L4) + +
+
+
+# LocalSearchSolvers.objective!Method. + + + + +```julia +objective!(m::M, func) where M <: Union{Model, AbstractSolver} +``` + + +Add an objective evaluated by `func`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L296-L299) + +
+
+
+# LocalSearchSolvers.objectiveMethod. + + + + +```julia +objective(func, name) +``` + + +Construct an objective with a function `func` that should be applied to a collection of variables. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/objective.jl#L24-L27) + +
+
+
+# LocalSearchSolvers.post_processMethod. + + + + +```julia +post_process(s::MainSolver) +``` + + +Launch a series of tasks to round-up a solving run, for instance, export a run's info. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L450-L453) + +
+
+
+# LocalSearchSolvers.remote_dispatch!Method. + + + + +```julia +remote_dispatch!(solver) +``` + + +Starts the `LeadSolver`s attached to the `MainSolver`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L425-L428) + +
+
+
+# LocalSearchSolvers.remote_stop!Method. + + + + +```julia +remote_stop!!(solver) +``` + + +Fetch the pool of solutions from `LeadSolvers` and merge it into the `MainSolver`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L444-L447) + +
+
+
+# LocalSearchSolvers.solutionMethod. + + + + +```julia +solution(s) +``` + + +Return the only/best known solution of a satisfaction/optimization model. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L470-L473) + +
+
+
+# LocalSearchSolvers.solve_for_loop!Method. + + + + +```julia +solve_for_loop!(solver, stop, sat, iter) +``` + + +First loop in the solving process that starts `LeadSolver`s from the `MainSolver`, and `_SubSolver`s from each `MetaSolver`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L431-L434) + +
+
+
+# LocalSearchSolvers.solve_while_loop!Method. + + + + +```julia +solve_while_loop!(s, ) +``` + + +Search the space of configurations. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L405-L408) + +
+
+
+# LocalSearchSolvers.specialize!Method. + + + + +```julia +specialize!(solver) +``` + + +Replace the model of `solver` by one with specialized types (variables, constraints, objectives). + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L107-L110) + +
+
+
+# LocalSearchSolvers.specializeMethod. + + + + +```julia +specialize(m::M) where M <: Union{Model, AbstractSolver} +``` + + +Specialize the structure of a model to avoid dynamic type attribution at runtime. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L350-L353) + +
+
+
+# LocalSearchSolvers.statusMethod. + + + + +```julia +status(solver) +``` + + +Return the status of a MainSolver. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solvers/main.jl#L60-L63) + +
+
+
+# LocalSearchSolvers.stop_while_loopMethod. + + + + +```julia +stop_while_loop() +``` + + +Check the stop conditions of the `solve!` while inner loop. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/solver.jl#L399-L402) + +
+
+
+# LocalSearchSolvers.tabu_listMethod. + + + + +```julia +_tabu(s::S) where S <: Union{_State, AbstractSolver} +``` + + +Access the list of tabu variables. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/strategies/tabu.jl#L32-L35) + +
+
+
+# LocalSearchSolvers.tabu_valueMethod. + + + + +```julia +_tabu(s::S, x) where S <: Union{_State, AbstractSolver} +``` + + +Return the tabu value of variable `x`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/strategies/tabu.jl#L38-L41) + +
+
+
+# LocalSearchSolvers.variable!Function. + + + + +```julia +variable!(m::M, d) where M <: Union{Model, AbstractSolver} +``` + + +Add a variable with domain `d` to `m`. + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/model.jl#L278-L281) + +
+
+
+# LocalSearchSolvers.variableMethod. + + + + +```julia +variable(values::AbstractVector{T}, name::AbstractString; domain = :set) where T <: Number +variable(domain::AbstractDomain, name::AbstractString) where D <: AbstractDomain +``` + + +Construct a variable with discrete domain. See the `domain` method for other options. + +```julia +d = domain([1,2,3,4], types = :indices) +x1 = variable(d, "x1") +x2 = variable([-89,56,28], "x2", domain = :indices) +``` + + + +[source](https://github.com/JuliaConstraints/LocalSearchSolvers.jl/blob/v0.4.5/src/variable.jl#L60-L70) + +
+
diff --git a/previews/PR50/siteinfo.js b/previews/PR50/siteinfo.js new file mode 100644 index 0000000..7cde162 --- /dev/null +++ b/previews/PR50/siteinfo.js @@ -0,0 +1 @@ +var DOCUMENTER_CURRENT_VERSION = "previews/PR50";
+# ConstraintCommons.AutomatonType. + + + + +```julia +Automaton{S, T, F <: Union{S, Vector{S}, Set{S}}} <: AbstractAutomaton +``` + + +A minimal implementation of a deterministic automaton structure. + + +[source](https://github.com/JuliaConstraints/ConstraintCommons.jl/blob/v0.2.1/src/automata.jl#L9-L13) + +
+# Constraints.xcsp_all_differentFunction. + + + + +```julia +xcsp_all_different(list::Vector{Int}) +``` + + +Return `true` if all the values of `list` are different, `false` otherwise. + +**Arguments** +- `list::Vector{Int}`: list of values to check. + + +**Variants** +- `:all_different`: Global constraint ensuring that all the values of `x` are all different. + + +```julia +concept(:all_different, x; vals) +concept(:all_different)(x; vals) +``` + + +**Examples** + +```julia +c = concept(:all_different) + +c([1, 2, 3, 4]) +c([1, 2, 3, 1]) +c([1, 0, 0, 4]; vals=[0]) +c([1, 0, 0, 1]; vals=[0]) +``` + + + +[source](https://github.com/JuliaConstraints/Constraints.jl/blob/v0.5.5/src/constraints/all_different.jl#L7-L31) + +