Code Monkey home page Code Monkey logo

chocosolver's Introduction

Build Status

chocosolver

v0.4.4

An instance generator and multi-objective optimizer backend for Clafer using the Choco 4.0.0b constraint programming library. There are two ways to use the project: programmatically via the Java API or via the command-line interface (CLI).

The CLI is used by ClaferIDE, ClaferMooVisualizer, and ClaferConfigurator.

Note: the name "choco-solver" refers to the Java library for Constraint Programming, whereas "chocosolver" (without the "-") is the name of this project. We might change the name in the future to avoid confusion.

Contributors

Getting Clafer Tools

Installation from binaries

Binary distributions of the release 0.4.4 of Clafer Tools for Windows, Mac, and Linux, can be downloaded from Clafer Tools - Binary Distributions.

  1. download the binaries and unpack <target directory> of your choice
  2. add the <target directory> to your system path so that the executables can be found

Integration with Sublime Text 2/3

See ClaferToolsST.

Installation from the source code

Prerequisites

Recommended but optional

  • Clafer compiler, v0.4.4.
    • This backend provides an API for solving Clafer models. The Clafer compiler can compile a Clafer model down to the proper API calls.
    • The API calls can also be written manually quite easily with a bit of extra typing (examples down below).

Follow the installation instructions in the README.md.

Installation

Install the API and the CLI.

git clone https://github.com/gsdlab/chocosolver.git
cd chocosolver
mvn install -DskipTests

Include the following XML snippet in your POM to use the API in your Maven project.

<dependency>
    <groupId>org.clafer</groupId>
    <artifactId>chocosolver</artifactId>
    <version>0.4.4</version>
</dependency>

The CLI is installed to target/chocosolver-0.4.4-jar-with-dependencies.jar; however, in the Clafer Tools binary distribution it is called chocosolver.jar.

You can deploy the files the same way as in Clafer Tools binary distribution by executing

make install to=<target path>

Important: branches must correspond

All related projects are following the simultaneous release model. The branch master contains releases, whereas the branch develop contains code under development. When building the tools, the branches should match. Releases from branches master are guaranteed to work well together. Development versions from branches develop should work well together but this might not always be the case.

Getting started with the CLI

For usage instructions, start the CLI using the command

java -jar chocosolver.jar --help`

Option                                  Description
------                                  -----------
--file <File: Clafer model file (.cfr)  Input file in .cfr or .js format.
  or Clafer Javascript file (.js)>
--help                                  Show help.
--maxint <Integer>                      Specify maximum integer value.
--minint <Integer>                      Specify minimum integer value.
--moo                                   Run in multi-objective optimization mode.
-n <Integer>                            Specify the maximum number of instances.
--output <File: text file>              Output instances to the given file.
--prettify                              Use simple and pretty output format (not formal).
--repl                                  Run in REPL (interactive) mode.
--scope <Integer>                       Override the default global scope value.
--search <ClaferSearchStrategy>         PreferSmallerInstances/PreferLargerInstances/Random.
-v                                      Run in validation mode; checks all assertions.
--version                               Display the tool version.

The CLI supports four modes of operation:

  • -v - validation mode,
  • --repl - interactive mode,
  • -moo - batch multi-objective optimization mode, and
  • (default) batch instance generation mode.

The last mode is selected when no -v and --repl are given and the model does not contain optimization objectives.

If the .cfr file is given, the CLI will first call the Clafer compiler using clafer -k -m choco model.cfr, which will produce model.js. Certain features, such as transitive closure, are not yet supported by Clafer, so they can only be used directly via API call in the .js file. We recommend using the so called Choco escapes, as follows:

[choco|
<your code to be inserted verbatim at the end of the generated output>
|]

CLI interactive mode

When running the interactive mode, the CLI automatically produces an instance and then is ready to accept commands. Here is an example session:

Type 'help' for the list of available REPL commands

=== Instance 1 Begin ===

Bob
  owns -> car
car
  transmission
    manual
  drivenBy -> Bob

--- Instance 1 End ---


ClaferChocoIG> h
'h'elp                              Print the REPL commands.
'n'ext                              Generate the next instance.
<enter>                             Generate the next instance.
'p'rettify                          Toggle prettify on/off.
'r'eload                            Reload the model from the same <file-name.js> file.
'u'nsatCore                         Compute the set of contradicting constraints if any.
min'U'nsat                          Compute the minimal UnSAT core and a near-miss example.
'S'etGlobalScope <value>            Set the global scope to the <value> .
's'etScope <claferUID> <value>      Set the scope of the given clafer to the <value>.
'I'ncGlobalScope <value?>           Increase the global scope by <value> or 1 by default.
'i'ncScope <claferUID> <value?>     Increase the scope of the given clafer by the <value>  or 1 by default.
sa'v'eScopes                        Save the currect scopes to a .cfr-scope file.
'm'axInt <value>                    Set the largest allowed integer to <value>.
ma`x`imize <claferUID>              Find a solution where <claferUID>.dref is maximal.
minimiz'e' <claferUID>              Find a solution where <claferUID>.dref is minimal.
sta't's                             Display statistics about the current search.
'O'ptions                           Display the current solver options.
strate'g'y <smaller|larger|random>  Set search strategy to prefer smaller, prefer larger, or random.
'o'ptimizations                     Toggle optimizations basic/full.
symmetry'B'reaking                  Toggle symmetry breaking basic/full.
'q'uit                              Exit the REPL sesssion.

ClaferChocoIG>

Each command can be invoked using a full name, e.g., IncGlobalScope, or using a shortcut, e.g., I, as indicated by 'I'. The CLI is case sensitive, that is, i is for incScope command, whereas, I is for IncGlobalScope.

Getting Started with the Java API

In general, the CLI classes are good examples of using the API:

  • Main.java - this is the main class of the chocosolver.jar.
  • Validate.java - checks assertions (run with -v).
  • REPL.java - read, eval, print loop (interactive interface, run with --repl).
  • Normal.java - runs batch instance generation or multi-objective optimization up to the given limit of instances (provided using -n) or unlimited (by default).
  • Util.java - various shared utils.

Consider the following Clafer model.

Installation
    xor Status
        Ok
        Bad
    Time -> integer
        [this > 2]

Below is an example of using the API to build the model above. AstModel represents the implicit "root" of the model. Every Clafer in the model is nested below it.

import org.clafer.ast.*;
import static org.clafer.ast.Asts.*;

public static void main(String[] args) {
    AstModel model = newModel();

    AstConcreteClafer installation = model.addChild("Installation").withCard(Mandatory);
        // withCard(Mandatory) and withCard(1, 1) is the same. Pick the one you find more readable.
        AstConcreteClafer status = installation.addChild("Status").withCard(1, 1).withGroupCard(1, 1);
            AstConcreteClafer ok = status.addChild("Ok").withCard(Optional);
            // withCard(Optional) and withCard(0, 1) is the same.
            AstConcreteClafer bad = status.addChild("Bad").withCard(0, 1);
            // Note that ok and bad have an explicit optional cardinality, whereas
            // it was implicit in the oringal model.
        AstConcreteClafer time = installation.addChild("Time").withCard(1, 1).refTo(IntType);
            time.addConstraint(greaterThan(joinRef($this()), constant(2)));
            // Note that joinRef is explicit whereas it was implicit in the original model.
}

The Asts class provides all the functions required for building the model. See the previous link for a list of all the supported expressions. More examples of building models: structure, expressions, quantifiers, and attributed feature models.

Finding Instances

The next step is to solve the model.

import org.clafer.compiler.*;
import org.clafer.scope.*;

public static void main(String[] args) {
    ...
    ClaferSolver solver = ClaferCompiler.compile(model,
        Scope.setScope(installation, 1).setScope(status, 1).setScope(ok, 1).setScope(bad, 1).setScope(time, 1)
        // Set the scope of every Clafer to 1. The code above could be replaced with
        // "Scope.defaultScope(1)".
        .intLow(-16).intHigh(16));
        // intLow is the "suggested" lowest integer for solving. intHigh is the "suggested"
        // highest integer.
    // find will return true when the solver finds another instance.
    while (solver.find()) {
        // Print the solution in a format similar to ClaferIG.
        System.out.println(solver.instance());
    }
}

Finding Optimal Instances

Optimizing on a single objective is supported. Suppose we wanted to optimize on the expression "sum time".

import org.clafer.objective.*;
...
ClaferOptimizer solver = ClaferCompiler.compile(model,
    Scope.defaultScope(1).intLow(-16).intHigh(16),
    Objective.maximize(sum(global(time))));
while (solver.find()) {
    // The instances where time is maximal.
    System.out.println(solver.instance());
}

solver = ClaferCompiler.compile(model,
    Scope.defaultScope(1).intLow(-16).intHigh(16),
    Objective.minimize(sum(global(time))));
while (solver.find()) {
    // The instances where time is minimal.
    System.out.println(solver.instance());
}

The compiler can accept multiple objectives, in which case it will solve for all the Pareto-optimal solutions.

Finding Min-Unsat

Consider the following Clafer model.

Mob
Duck ?
Witch ?
Floats ?
[Floats => Duck]
[Floats <=> Witch]
[!Duck]
[Witch]

The model is overconstrained and has no solutions. The solver can help here as well.

AstModel model = newModel();
AstConcreteClafer mob = model.addChild("Mob").withCard(0, 1);
AstConcreteClafer duck = model.addChild("Duck").withCard(0, 1);
AstConcreteClafer witch = model.addChild("Witch").withCard(0, 1);
AstConcreteClafer floats = model.addChild("Floats").withCard(0, 1);
model.addConstraint(some(mob));
model.addConstraint(implies(some(floats), some(duck)));
model.addConstraint(ifOnlyIf(some(floats), some(witch)));
model.addConstraint(none(duck));
model.addConstraint(some(witch));

ClaferUnsat unsat = ClaferCompiler.compileUnsat(model, Scope.defaultScope(1));
// Print the Min-Unsat and near-miss example.
System.out.println(unsat.minUnsat());

The above code will print two things. First it will print "#(Witch) >= 1" which is the constraint that is unsatisfiable in the model, i.e., the last constraint that enforces there to be some witch. Next, it will print the near-miss example Mob#0. It means that removing the some(Witch) constraint would make the model satisfiable and an example of a solution (after removing the constraint), is the instance with exactly one mob and nothing else. For this example, the min-unsat is not unique, so it is possible that the library may report another set of constraints although the set of constraints is guaranteed to have a size of one.

Finding Unsat-Core

The above example found that removing one constraint will fix the model but you may be wondering why the model cannot have a witch. In this case, it is more useful to compute the unsat-core instead.

ClaferUnsat unsat = ClaferCompiler.compileUnsat(model, Scope.defaultScope(1));
// Print the Unsat-Core.
System.out.println(unsat.unsatCore());

The above code will print the last 4 constraints which are the constraints that are mutually unsatisfiable. What this means is that if you removed all constraints but these 4, the model is still unsatisfiable. The set of constraints is not guaranteed to be minimal but will likely be small.

Javascript vs Java

If you prefer to use the Javascript API over the Java API:

import org.clafer.javascript.Javascript;

public static void main(String[] args) {
    Javascript.readModel(
                "scope({Installation:1, Status:1, Ok:1, Bad:1, Time:1});" +
                "intRange(-16, 16);" +
                "Installation = Clafer('Installation').withCard(1, 1);" +
                ...
}

Configuring as a Web Tool Backend

The configuration is done in the <host-tool-path>/Server/Backends/backends.json file, where <host-tool-path> is a path to the web-based tool (ClaferIDE, etc.) you want to configure to use chocosolver as a backend.

{
    "backends": [
        {
            "id": "chocoIG",
            "label": "Choco-based (IG + MOO)",
            "tooltip": "An instance generator and multi-objective optimizer based on Choco3 solver library",
            "accepted_format": "choco",
            "tool": "java",
            "tool_args": ["-jar", "/home/<user>/bin/chocosolver.jar", "--file=$filepath$", "--repl", "--prettify"],
            "tool_version_args": ["-jar", "/home/<user>/bin/chocosolver.jar", "--version"],
            "scope_options": {
                "set_default_scope" : {"command": "SetGlobalScope $value$\n", "label": "Default:", "argument": "--scope=$value$", "default_value": 1},
                "set_individual_scope": {"command": "setScope $clafer$ $value$\n"},
                "inc_all_scopes" : {"command": "IncGlobalScope $value$\n", "label": "All:", "default_value": 1},
                "inc_individual_scope": {"command": "incScope $clafer$ $value$\n"},
                "produce_scope_file" : {"command": "saveScopes\n"},
                "set_int_scope" : {"command": "maxInt $value$\n", "label": "Max. integer:", "argument": "--maxint=$value$", "default_value": 127}
            },
            "control_buttons": [
                {"id": "next_instance", "command": "n\n", "label" : "Next", "tooltip": "Next Instance"},
                {"id": "reload", "command": "r\n", "label" : "Reload", "tooltip": "Reload the model preserving scopes and other settings"},
                {"id": "quit", "command": "q\n", "label" : "Quit", "tooltip": "Exit the IG safely"}
            ],
            "presentation_specifics": {
                "prompt_title": "ChocoIG> "
            }
        },
    ]
}
{
    "backends": [
        {
            "id": "choco_moo",
            "label": "Choco-based (MOO with magnifier)",
            "tooltip": "A multi-objective optimizer based on Choco3 solver library",
            "accepted_format": "choco",
            "tool": "java",
            "tool_args": ["-jar", "/home/<user>/bin/chocosolver.jar", "--file=$filepath$", "--moo"],
            "tool_version_args": ["-jar", "/home/<user>/bin/chocosolver.jar", "--version"],
            "optimization_options": {
                "set_int_scope" : {"label": "Max. integer:", "argument": "--maxint=$value$", "default_value": 127},
                "set_default_scope" : {"label": "Default scopes:", "argument": "--scope=$value$", "default_value": 25}
            }
        },
    ]
}
{
    "backends": [
        {
            "id": "chocoIG",
            "label": "Choco-based (IG + MOO)",
            "tooltip": "An instance generator based on Choco3 solver library",
            "accepted_format": "choco",
            "tool": "java",
            "tool_args": ["-jar", "/home/<user>/bin/chocosolver.jar", "--file=$filepath$", "--repl"],
            "tool_version_args": ["-jar", "/home/<user>/bin/chocosolver.jar", "--version"],
            "scope_options": {
                "set_default_scope" : {"command": "SetGlobalScope $value$\n"},
                "set_individual_scope": {"command": "setScope $clafer$ $value$\n"},
                "inc_all_scopes" : {"command": "IncGlobalScope $value$\n"},
                "inc_individual_scope": {"command": "incScope $clafer$ $value$\n"},
                "set_int_scope" : {"command": "maxInt $value$\n", "default_value": 127}
            },
            "control_buttons": [
                {"id": "next_instance", "command": "n\n", "label" : "Next", "tooltip": "Next Instance"},
                {"id": "reload", "command": "r\n", "label" : "Reset", "tooltip": "Reset instance generation, applied scopes and other settings"},
                {"id": "quit", "command": "q\n", "label" : "Quit", "tooltip": "Exit the IG safely"}
            ],
            "presentation_specifics": {
                "prompt_title": "",
                "no_more_instances": "No more instances found. Please consider increasing scopes"
            }
        },
    ]
}

Notes:

  • If you make any changes to the backends.json, restart the web-tool completely to make the changes take effect.
  • If you done your configuration properly, the tool will restart successfully and the backend should be listed in the Backends dropdown list. If the tool does not start, the reason may be either a syntax error in the backends.json file, or the paths specified in it are not correct or lead to an inaccessible jar file. Also, check the eXecute permission on the jar file.

Semantic Differences with the Alloy backend

Consider the following constraint.

[5 + 5 = -6]

For this backend, the constraint is always unsatisfiable. For the Alloy backend, the constraint can be satisfied, depending on the set bitwidth. Why? In the default bitwidth of 4, the number succeeding 7 is -8. Hence 5 + 5 is translated to 5 -> 6 -> 7 -> -8 -> -7 -> -6, hence the constraint is true. For any other bitwidth, the constraint is false. Overflow can be a problem for low bitwidths when dealing with arithmetic (in the new Alloy there's an option which prevents overflows). This backend can also suffer from overflow. It essentially, in regards to overflow, has a fixed bitwidth of 32.

Possible Future Work?

  • API for choosing branching strategy. Two reasons. The advantage of constraint programming is the ability to tune the solver to the specific problem. Choosing the right branching strategy can make a world of difference. Secondly, it allows the user to control the order of instances generated. For example, the user would like to see instances where Feature A is present and Feature B is absent before any other instances. This can be done by choosing the branching strategy.
  • Reals

Need help?

chocosolver's People

Contributors

ezulkosk avatar jlianggsd avatar jliangwaterloo avatar mantkiew avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chocosolver's Issues

Issue with multiplication of 'large' numbers

Consider the following code

abstract hisclafer
  atth -> int

abstract yourclafer
  tmpatt -> hisclafer
  att -> int = tmpatt.atth

abstract myclafer
  att1 -> yourclafer 1..3
  att2 -> int = sum att1.att
  att3 -> int = (#att1) * att2

hisclaferinstanceOne : hisclafer
  [atth = 5]

hisclaferinstanceTwo : hisclafer
  [atth = 5]

yourclaferinstanceOne : yourclafer
  [tmpatt = hisclaferinstanceOne]

yourclaferinstanceTwo : yourclafer
  [tmpatt = hisclaferinstanceTwo]

myclaferinstance : myclafer
  [att1 = yourclaferinstanceOne, yourclaferinstanceTwo]

which runs perfectly fine on clafer 0.3.9

 java -jar ~/git/gsdlab/ClaferChocoIG/target/claferchocoig-0.3.9-jar-with-dependencies.jar -n 1 --maxint 64 --prettify --file multiplication.cfr
Compiling the Clafer model...
Running Model...
Generating instances...
=== Instance 1 Begin ===

c0_hisclaferinstanceOne#0
    c0_atth#0 = 5
c0_hisclaferinstanceTwo#0
    c0_atth#1 = 5
c0_yourclaferinstanceOne#0
    c0_tmpatt#0 = c0_hisclaferinstanceOne#0
    c0_att#0 = 5
c0_yourclaferinstanceTwo#0
    c0_tmpatt#1 = c0_hisclaferinstanceTwo#0
    c0_att#1 = 5
c0_myclaferinstance#0
    c0_att1#0 = c0_yourclaferinstanceOne#0
    c0_att1#1 = c0_yourclaferinstanceTwo#0
    c0_att2#0 = 10
    c0_att3#0 = 20
--- Instance 1 End ---

Running the same code with clafer-0.3.10 doesn't produce any outputs at all

 java -jar ~/git/gsdlab/ClaferChocoIG/target/claferchocoig-0.3.10-jar-with-dependencies.jar -n 1 --maxint 64 --prettify --file multiplication.cfr
Compiling the Clafer model...
Running Model...

Generating instances...
Generated 0 instance(s)

It seems like, as soon
att3 -> int = (#att1) * att2 > 16

claferChocoIG fails to produce any outputs

chocosolver chokes on #property * a statement?

Note: Resubmission of gsdlab/ClaferChocoIG#7. I just checked with 0.4.2.1 (binary distribution), and the problem is exactly the same. As it's friday evening, it's a perfect moment to do these kinds of things :-)

Consider the following clafer model

abstract Platform
    price -> int = sum hwComponents.price
    hwComponents -> HWComponent 1..2

abstract HWComponent
    price -> int

abstract Deployment
    price -> int = #platforms * 10 + sum platforms.price // causes chocosolver to choke?
    platforms : Platform 2..3

CAN : HWComponent
   [ price = 10 ]

DO : HWComponent
   [ price = 2 ]

D1: Deployment

// << min D1.price >>

Whereas claferIG seems to be able to succesfully generate instances from this model, it seems like the chocoIG fails to do the same. Removing the #platforms * 10 clause seems to "solve" the issue

[kgad@Klaass-MacBook-Air ~/Workspaces/varies/be.fmtc.costOptimization/Model]$  
 claferIG --maxint 64 ~/Workspaces/varies/be.fmtc.costOptimization/Model/NRE_test.cfr
=== Instance 1 Begin ===

CAN
  price$1 = 10
D1
  price$2 = 32
  platforms$1
    price$3 = 10
    hwComponents$1 = CAN
  platforms$2
    price$4 = 2
    hwComponents$2 = DO
DO
  price$5 = 2

--- Instance 1 End ---


claferIG> q
AlloyIG stream closed.
[kgad@Klaass-MacBook-Air ~/Workspaces/varies/be.fmtc.costOptimization/Model]$  
 java -jar ~/install/clafer/claferchocoig-0.3.9-jar-with-dependencies.jar -n 1 --minint 0 --maxint 64 --file NRE_test.cfr
Clafer Choco Instance Generator and Multi-Objective Optimizer
Compiling the Clafer model...
Running Model...

and then the the solver seems to get stuck in an endless loop...

Add-on questions from a follow-up comment on my side:

On the other hand, would there (in this particular case) be a possibility to somehow declare that the price attribute of the Deployment variable is "derived" (in the UML sense), such that the backend knows it should actually not branch on this variable for instance?

Small typo in docu of the develop branch

[kgad@lt00858 ~/git/gsdlab/chocosolver]$  
 git diff README.md 
diff --git a/README.md b/README.md
index 90ef882..abfbb25 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ See [ClaferToolsST](https://github.com/gsdlab/ClaferToolsST).

 ## Prerequisites

-* [Choco 3.3+](https://github.com/chocoteam/choco3), v3.3.2-SNAPSHOT.
+* [Choco 3.3+](https://github.com/chocoteam/choco3), v3.3.3-SNAPSHOT.
 * [Java 8+](http://www.oracle.com/technetwork/java/javase/downloads/index.html), 64bit.
 * [Maven 3.2+](http://maven.apache.org/). Required for building the project.

Union types

Currently not supported.

A
    B -> int
C
    D -> int
[(A ++ C).B.ref = 3]

Exception thrown: Empty domain does not have a high bound

The error that I am coming across is as follows:

$ java -jar "C:\Users\Jordan\AppData\Roaming\Sublime Text 3\Packages\Clafer-Bin\claferchocoig.jar" --file=wire_debug.js --prettify --repl
Exception in thread "main" org.clafer.ir.IrException: Emtpy domain does not have a high bound.
        at org.clafer.domain.EmptyDomain.getHighBound(EmptyDomain.java:32)
        at org.clafer.ast.compiler.AstCompiler$ExpressionCompiler.compileDecl(AstCompiler.java:1569)
        at org.clafer.ast.compiler.AstCompiler$ExpressionCompiler.visit(AstCompiler.java:1609)
        at org.clafer.ast.compiler.AstCompiler$ExpressionCompiler.visit(AstCompiler.java:877)
        at org.clafer.ast.AstQuantify.accept(AstQuantify.java:36)
        at org.clafer.ast.compiler.AstCompiler$ExpressionCompiler.compile(AstCompiler.java:887)
        at org.clafer.ast.compiler.AstCompiler$ExpressionCompiler.compile(AstCompiler.java:899)
        at org.clafer.ast.compiler.AstCompiler$ExpressionCompiler.access$100(AstCompiler.java:877)
        at org.clafer.ast.compiler.AstCompiler.compile(AstCompiler.java:289)
        at org.clafer.ast.compiler.AstCompiler.compile(AstCompiler.java:160)
        at org.clafer.ast.compiler.AstCompiler.compile(AstCompiler.java:155)
        at org.clafer.compiler.ClaferCompiler.compile(ClaferCompiler.java:210)
        at REPL.runREPL(REPL.java:114)
        at Main.main(Main.java:116)

It happens when I have a model like such:

enum Type = Input | Output

abstract Pin
    rating -> Rating
    type -> Type // A pin has some type (input or output)
    connectedWire -> Wire ? // A pin can only have one connected wire
    [(this in connectedWire.endpoint) <=> connectedWire]

    // We have a connected wire always, if its an input pin. This is because we may not
    // utilize some output pins on devices.
    [(type = Input) => connectedWire]

abstract Wire
    endpoint -> Pin 2..* // The endpoints of the wire
        [this.connectedWire = parent]

    // There must be one and only one output Pin for the wire
    [one ep : endpoint | ep.type = Output]

    // All endpoints of the wire must have the same rating.
    [all disj a; b : endpoint | a.rating.ref = b.rating.ref]

abstract Rating
    volt : Number
    amp : Number

ratingA : Rating
    [volt = 1]
    [amp = 1]

ratingB : Rating
    [volt = 2]
    [amp = 2]

A : Pin
    [rating = ratingA]
    [type = Input]
B : Pin
    [rating = ratingB]
    [type = Input]
ecPin : Pin +
    [type = Output]
    [connectedWire]

wire : Wire +

I have to set the default scope to be something large (like 10). This model will solve if you give the cardinality of ecPin to be bounded (i.e 1..3)

Question serialisation of InstanceClafer class.

hi,

Thanks for this really interesting project. This is a question more than an issue.

I see that utilities are provided to output a String representation of an InstanceClafer Java object. However I can't see any API for parsing such a string representation so that I can round-trip an InstanceClafer back to a Java object from a String ( or any other kind of input format).

Am I missing something? Is there a way I can achieve this use case?

Thanks again.

support nested abstract clafers

abstract Component
    abstract Port

now, Port can be extended as:

Example 1:

WinController : Component
    cmd : Port
    abstract ExceptionPort : Port

NOTE: the compiler also allows declaring ExceptionPort at the top-level but only for abstract clafers like this

WinController : Component
    powerOut : ExceptionPort

abstract ExceptionPort : Port

however, in the IR, ExceptionPort is physically moved as a sibling of Port as in the Example 1.

Relevant test cases are:

Fine-grained intRange

Specify intRange per Clafer, fallback on default if not explicitly specified, i.e., same way it works for scope.

Properly inherit constraints for nested abstracts

The constraints seem not to be inherited properly:

abstract Component
    abstract Port
        throughput -> integer // [Mbit/s]
    abstract Port10Mbit : Port
        [ throughput = 10 ]

abstract Port100Mbit : Port
    [ throughput = 100 ]

C1 : Component
    R1 : Port10Mbit
    R2 : Port100Mbit

The expected instance (produced by AlloyIG) is:

C1
  R1
    throughput$1 -> 10
  R2
    throughput$2 -> 100

However, chocosolver produces:

C1
  R1
    throughput -> -1001
  R2
    throughput$1 -> -1001

Configurable optimization and symmetry breaking settings

Certain optimizations an symmetry breaking are really expensive (in terms of memory, compile time, and propagation time) which don't make sense for models that are "easy" to solve.

Have the option to turn down or off these features.

Support parent of nested abstract clafers

The following model causes an error org.clafer.ast.analysis.TypeException: Cannot join abstract c0_Port . parent:

abstract Component
    abstract Port
    allPorts -> Port *
    // query for all nested ports explicitly
    [ all p : Component.Port | p.parent=this <=> p in this.allPorts ]   // p.parent causes the error


WinController : Component
    cmd : Port
    powerOut : Port

where, in fact, Port has a parent because it is nested under Component.

Duplicate instance when modeling many to many relationship

There is a duplicate in the generated instance when a many to many realtonship is modeled. Consider the following model:

abstract LogicalBus
    realizedBy -> PhysicalBus 1..*
        [parent in this.realizes.ref]


// Physical Connection Mediums
abstract PhysicalBus
    realizes -> LogicalBus 1..*
        [parent in this.realizedBy.ref]

logBusA : LogicalBus
logBusB : LogicalBus

physBusA : PhysicalBus ?
physBusB : PhysicalBus ?
physBusC : PhysicalBus ?

[logBusA => physBusA]
[logBusA => physBusB]
[logBusA.realizedBy = (physBusA, physBusB)]

[logBusB => physBusC]
[logBusB.realizedBy = (physBusC)]

If you generate instances with the current version of chocosolver and IG you get:

Compiling the Clafer model...
Type 'help' for the list of available REPL commands

=== Instance 1 Begin ===

c0_logBusA$0
  c0_realizedBy$0 = c0_physBusA$0
  c0_realizedBy$1 = c0_physBusB$0
c0_logBusB$0
  c0_realizedBy$2 = c0_physBusC$0
c0_physBusA$0
  c0_realizes$0 = c0_logBusA$0
c0_physBusB$0
  c0_realizes$1 = c0_logBusA$0
c0_physBusC$0
  c0_realizes$2 = c0_logBusB$0
--- Instance 1 End ---


claferChocoIG> 

=== Instance 2 Begin ===

c0_logBusA$0
  c0_realizedBy$0 = c0_physBusB$0
  c0_realizedBy$1 = c0_physBusA$0
c0_logBusB$0
  c0_realizedBy$2 = c0_physBusC$0
c0_physBusA$0
  c0_realizes$0 = c0_logBusA$0
c0_physBusB$0
  c0_realizes$1 = c0_logBusA$0
c0_physBusC$0
  c0_realizes$2 = c0_logBusB$0
--- Instance 2 End ---


claferChocoIG> 
No more instances found. Consider increasing scopes.

Support subset of instances of nested abstract clafers

The following example gives a NullPointerException:

abstract Component
    abstract Port
    abstract ExceptionPort : Port
    allPorts -> Port *
    [ allPorts.dref = this.Port ]    // the exception is caused by "this.Port"

WinController : Component
    cmd : Port
    powerOut : ExceptionPort

The expected output is (as produced by AlloyIG):

WinController
  allPorts$1 -> powerOut
  allPorts$2 -> cmd
  powerOut
  cmd

This works nicely for concrete clafers:

Component 3
    Port 1..3
    allPorts -> Port *
    [ allPorts.dref = this.Port ]

produces, for example an instance:

Component
  Port
  Port$1
  allPorts -> Port
  allPorts$1 -> Port$1
Component$1
  Port$2
  Port$3
  allPorts$2 -> Port$2
  allPorts$3 -> Port$3
Component$2
  Port$4
  Port$5
  allPorts$4 -> Port$5
  allPorts$5 -> Port$4

incorrect reference refinement check

For a correct model

abstract ASIL -> integer
A : ASIL -> 1
B : ASIL -> 2
C : ASIL -> 3
D : ASIL -> 4

I am getting an error

Unhandled compilation error occured. Please report this problem.
Wrapped java.lang.IllegalArgumentException: c0_A cannot refine reference uniqueness

The model actually refines the references correctly and it currently works in AlloyIG:

D -> 4
C -> 3
B -> 2
A -> 1

Sum type error when working with inheritance

Consider the following model:

abstract DeviceNode
    cost -> integer

abstract Motor : DeviceNode
abstract Switch : DeviceNode

B : DeviceNode
    [cost = 1]
C : Motor
    [cost = 1]
D : Switch
    [cost = 1]

If I were to query to the total cost of the motors and switches like:

totalCost -> integer
[totalCost = sum (Motor.cost, Switch.cost)]

A type error would produced by choco:

Exception in thread "main" org.clafer.ast.analysis.TypeException: Cannot sum(int)
    at org.clafer.ast.analysis.TypeAnalyzer$TypeVisitor.visit(TypeAnalyzer.java:445)
    at org.clafer.ast.analysis.TypeAnalyzer$TypeVisitor.visit(TypeAnalyzer.java:146)
    at org.clafer.ast.AstSum.accept(AstSum.java:23)
    at org.clafer.ast.analysis.TypeAnalyzer$TypeVisitor.typeCheck(TypeAnalyzer.java:158)
    at org.clafer.ast.analysis.TypeAnalyzer$TypeVisitor.visit(TypeAnalyzer.java:384)
    at org.clafer.ast.analysis.TypeAnalyzer$TypeVisitor.visit(TypeAnalyzer.java:146)
    at org.clafer.ast.AstSetTest.accept(AstSetTest.java:35)
    at org.clafer.ast.analysis.TypeAnalyzer$TypeVisitor.typeCheck(TypeAnalyzer.java:158)
    at org.clafer.ast.analysis.TypeAnalyzer$TypeVisitor.access$000(TypeAnalyzer.java:146)
    at org.clafer.ast.analysis.TypeAnalyzer.analyze(TypeAnalyzer.java:117)
    at org.clafer.ast.analysis.Analysis.analyze(Analysis.java:130)
    at org.clafer.ast.compiler.AstCompiler.<init>(AstCompiler.java:158)
    at org.clafer.ast.compiler.AstCompiler.<init>(AstCompiler.java:154)
    at org.clafer.ast.compiler.AstCompiler.compile(AstCompiler.java:176)
    at org.clafer.ast.compiler.AstCompiler.compile(AstCompiler.java:172)
    at org.clafer.compiler.ClaferCompiler.compile(ClaferCompiler.java:292)
    at org.clafer.cli.REPL.runREPL(REPL.java:114)
    at org.clafer.cli.Main.main(Main.java:123)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.