(You can download this as a pdf here.)

1. One of the hardest parts about GraphSynth is learning how to write plugins that will do something interesting with the GraphSynth objects: graphs, rulesets, and rules. To create a search plugin for use in GraphSynth2, you first open Visual Studio, choose "New Project" and then choose "Class Library". Your plugin will be compiled to a .DLL file which GraphSynth2 will find in a prescribed directory. One project (.DLL) file may have any number of plugins within it. Take a moment to think of a good name now for your project. Don''t let it be, ClassLibrary1. Be verbose!image

2. Under the project (in the solution explorer), right-click on References and select "Add Reference". When the pop-up opens. Browse to C:\\Program Files\\GraphSynth2, and select two class libraries (.DLLs):

a. GraphSynth.FundamentalClassesAndInterfaces

b. GraphSynth.Representation

Optionally, you can choose to reference StarMath as well. This is a custom-made matrix library developed in a parallel project (see http://starmath.codeplex.com/).

3. Now for any plugin you would like to create. Add a new class (or use an existing class), and:

  • a. add “using GraphSynth;”
  • b. add “using GraphSynth.Search;”
  • c. add “using GraphSynth.Representation;”
  • d. optionally add “using StarMathLib;”
  • e. to the class declaration, make it inherited from SearchProcess.


For example:

“public class Plugin1 : SearchProcess”

4. It helps to “Go To Definition” (shortcut F12) for SearchProcess and see what type of details you are inheriting. Eventually, when GraphSynth2 scans your folder it will be searching for classes that inherit from SearchProcess.

5. Type override in the new class. You’ll see five things that can be overridden in the base class, SearchProcess. Of course, Equals(object obj), GetHashCode(), and ToString() are universal to any object. But what stands out is “string text { get; }” and “void Run()”. You must override both of these – otherwise the code will not compile. “text” is the string you would like to appear in the drop down menu; and the Run function is where your plugin starts. The “text” string can include whitespaces and special characters, but should probably be kept under 50 characters.

6. There are two additional things to understand. The first is using properties and methods from the base class. Since the Run() function receives nothing and returns nothing, how do we interact with the program? When your plugin is loaded, it is given access to several important objects in GraphSynth. These can be accessed by simply typing them in the Run method, or any non-static method within this plugin class.

  • a. optimize OptimizeDirection : You can set a direction used by all performance parameters within a candidate. This is not a necessity, and your specific search process might require some performance parameters to be maximized while others are minimized. “optimize” is an enumerator that can be set to minimize or maximize.
  • b. designGraph seedGraph : This retrieves whatever graph is set as the seed in GraphSynth2.
  • c. candidate seedCandidate : Simliar to seedGraph, the seedCandidate is simply a new candidate object wrapped around the seedGraph.
  • d. ruleSet[] rulesets : The rulesets set in GraphSynth2 are accessed by this array.
  • e. ISettings settings : There are various other important settings that one can set in GraphSynth2
    (under Edit->Settings, and in a loaded .gsconfig file) and these can be read here. These include:
    • 1. string settings.workingDirectory
    • 2. string settings.helpDirectory
    • 3. string settings.inputDirectory
    • 4. string settings.outputDirectory
    • 5. string settings.compiledparamRules : the location of the .DLL file that accompanies rules if additional functions are loaded for these rules.
    • 6. string defaultSeedFileName
    • 7. int defaultVerbosity
    • 8. int maxRulesToApply : the maximum number of rules to apply. This is up to you to use. It will not limit your generation of designs unless you choose to use it in a condition.
    • 9. int maxRulesToDisplay : likewise to the above. This is mainly used by the User Choose dialog plugin.
    • 10. int numOfRuleSets : The number of rulesets – the same as rulesets.GetLength(0);
    • 11. bool recompileRules : When true, a new compiledparamRules file will be created with every run of the plugin.
  • f. The following are methods that can be used by the plugin.
    void Save(string filename, object o) saves the object (graph, rule, ruleset, or graphWindow, or ruleWindow) to a file named filename. Filename must be rooted (i.e. global).
  • g. object[] Open(string filename) returns the contents of the filename (again must be a rooted/global filename).
  • 1. if you are opening a .gxml file
    • object[0] will be a designGraph
    • object[1] will be the canvas properties for the graph
    • object[2] will be the filename
  • 2. if you are opening a .grxml file
    • object[0] will be a grammarRule
    • object[1] will be the canvas properties for the rule
    • object[2] will be the filename
  • 3. if you are opening a .rsxml file
    • object[0] will be a ruleset
  • h. void addChildToSortedCandList(List<candidate> candidates, candidate child) : Adds the child to the sorted candidate list based on the value of f0 (performanceParams[0]). The OptimizeDirection is not used as the list is always sorted from lowest to highest.
  • i. void addNewCandtoPareto(candidate c, List<candidate> ParetoCands) : Adds the new candidate to the pareto set defined as ParetoCands. The result may be 1) nothing (c is not added), 2) c is added to the list if it is not dominated by any members of ParetoCands, or 3) c is added and elements of ParetoCands are removed because they are dominated by c.
  • j. bool dominates(candidate c1, candidate c2) : is a function used by the above. Does c1 dominate c2? By dominates we are referring to how optimizeDirection was set.
  • k. bool dominates(candidate c1, candidate c2, optimize[] optDirections) : if optimizeDirection was not set or if it is different for the different performanceParams of the candidates than this version may be used.
  • l. int nextRuleSet(int ruleSetIndex, GenerationStatuses status) : A helper function to RecognizeChooseApplyCycle. This function returns what the new ruleSet will be. Here the enumerator nextGenerationSteps and GenerationStatuses is used to great effect. Understand that if a negative number is returned, the cycle will be stopped.
  • m. void transferLmappingToChild(designGraph child, designGraph current, designGraph Lmapping) : A necessary function when multiple (more than one) application of a rule is applied to a host. The function reads in the child graph (often a copy of the current), the current graph, and the Lmapping. The Lmapping is changed but the child and current are unaffected.

7. The second issue is enabling and disabling your plugin. While you no longer have to define a constructor, it may be a good idea to, in order to better control how and when your plugin starts. A constructor for your plugin could look like this:

public Plugin1()
{
AutoPlay = false;
RequireSeed = true;
RequiredNumRuleSets = 3;
}

These three properties control the how and when. The default for AutoPlay is, in fact, false; and the default for RequireSeed is, in fact, true. So, in reality one wouldn’t need to define these since they are the defaults. AutoPlay means that the plugin will start automatically (no need to press the play button), and RequireSeed means that the plugin will be disabled until a seed is defined. Finally, the RequiredNumRuleSets as the name implies, sets the number of rulesets that need to be defined before the plugin will be active. It is possible to set this to zero. This is common in cases where the plugin simply manipulates qualities of the seed, or loads in its own files. If it is not defined in a constructor then the default value is either 1 or the number of rulesets defined in the settings (whichever is larger).

8. Finally, running and debugging your plugin. After you write a little code, you will want to see if your plugin is functioning correctly. Since your project is not an executable, it won’t run on its own. You’ll need to go to the properties for the project (right-click on the project and choose the last item “Properties”). Under the fourth tab, Debug, you need to set the “Start external program:” to the GraphSynth executable. It will likely have the path “C:\\Program Files\\GraphSynth2\\GraphSynth.exe” (see attached screenshot).

image
Now, when you can run GraphSynth2 from Visual Studio. After GraphSynth2 starts you may be disappointed to find that the plugin has not been loaded. This is because you still need to tell GraphSynth2 where to find your plugin. Under Edit->Settings in GraphSynth2, find the Search Plugins under the second tab labeled “Directories”. Choose a directory that contains your plugin. GraphSynth will recursively search the entire directory to find your plugin, so you don’t need to dig down so far. However if you choose something like “C:\\Users”, GraphSynth2 will likely hang for some time.

That’s it! Your plugin can be as large as you want with as many additional classes and files that you want. Now you’re all set to write some impressive generative grammar algorithms. Enjoy.

Last edited Feb 8, 2014 at 5:31 PM by mattica, version 1